Skip to content
This repository was archived by the owner on Jun 2, 2022. It is now read-only.

Commit 25a3700

Browse files
authored
Merge pull request #739 from ekinanp/727
Include core plugin entry sgraph in external plugin entry sgraph
2 parents e1f7ef3 + 90027b5 commit 25a3700

File tree

4 files changed

+127
-29
lines changed

4 files changed

+127
-29
lines changed

plugin/entrySchema.go

+50-16
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,31 @@ func TypeID(e Entry) string {
1818
pluginName := pluginName(e)
1919
rawTypeID := rawTypeID(e)
2020
if pluginName == "" {
21-
// e is the plugin registry
21+
// e is the plugin registry or a core entry used by an external plugin
2222
return rawTypeID
2323
}
2424
return namespace(pluginName, rawTypeID)
2525
}
2626

27+
// SchemaGraph returns e's schema graph. This is effectively a
28+
// map[string]plugin.EntrySchema object that preserves insertion
29+
// order (where the string is each entry's type ID).
30+
func SchemaGraph(e Entry) (*linkedhashmap.Map, error) {
31+
s, err := schema(e)
32+
if err != nil {
33+
return nil, err
34+
}
35+
if s == nil {
36+
return nil, nil
37+
}
38+
if s.graph == nil {
39+
// e is a core plugin entry so fill its graph
40+
s.graph = linkedhashmap.New()
41+
s.fill(s.graph)
42+
}
43+
return s.graph, nil
44+
}
45+
2746
func schema(e Entry) (*EntrySchema, error) {
2847
switch t := e.(type) {
2948
case externalPlugin:
@@ -49,7 +68,10 @@ func schema(e Entry) (*EntrySchema, error) {
4968
IsSingleton().
5069
SetDescription(registryDescription)
5170
schema.graph = linkedhashmap.New()
52-
schema.graph.Put(TypeID(t), &schema.entrySchema)
71+
typeID := TypeID(t)
72+
// We start by putting in a stub value for s so that we preserve the insertion
73+
// order. We'll then update this value once the "Children" array's been calculated.
74+
schema.graph.Put(typeID, EntrySchema{})
5375
for _, root := range t.pluginRoots {
5476
childSchema, err := Schema(root)
5577
if err != nil {
@@ -73,6 +95,8 @@ func schema(e Entry) (*EntrySchema, error) {
7395
schema.graph.Put(key, value)
7496
})
7597
}
98+
// Update the graph
99+
schema.graph.Put(typeID, schema.clone())
76100
return schema, nil
77101
default:
78102
// e is a core-plugin
@@ -137,9 +161,10 @@ func NewEntrySchema(e Entry, label string) *EntrySchema {
137161
// how plugin.EntrySchema objects are meant to be used.
138162
func (s EntrySchema) MarshalJSON() ([]byte, error) {
139163
if s.entry == nil {
140-
// Nodes in the external plugin graph don't use NewEntrySchema, they directly set the
141-
// undocumented fields of EntrySchema. Since graph and entry won't be set - and this is
142-
// part of a graph already - directly serialize entrySchema instead of using the graph.
164+
// This corresponds to an "EntrySchema" value in another entry's schema graph.
165+
// These values directly set the undocumented fields of EntrySchema. Since graph
166+
// and entry won't be set - and this is part of a graph already - directly serialize
167+
// entrySchema instead of using the graph.
143168
return json.Marshal(s.entrySchema)
144169
}
145170

@@ -253,12 +278,18 @@ func (s *EntrySchema) fill(graph *linkedhashmap.Map) {
253278
s.fillPanicf("bad value passed into SetMetadataSchema: %v", err)
254279
}
255280
}
256-
graph.Put(TypeID(s.entry), &s.entrySchema)
281+
typeID := TypeID(s.entry)
257282

258-
// Fill-in the children
259283
if !ListAction().IsSupportedOn(s.entry) {
284+
graph.Put(typeID, s.clone())
260285
return
261286
}
287+
288+
// Fill-in the children. We start by putting in a stub value for s
289+
// so that we preserve the insertion order and so that we can mark
290+
// the node as visited. We'll then update this value once the "Children"
291+
// array's been calculated.
292+
graph.Put(typeID, EntrySchema{})
262293
// "sParent" is read as "s.parent"
263294
sParent := s.entry.(Parent)
264295
children := sParent.ChildSchemas()
@@ -280,6 +311,16 @@ func (s *EntrySchema) fill(graph *linkedhashmap.Map) {
280311
passAlongWrappedTypes(sParent, child.entry)
281312
child.fill(graph)
282313
}
314+
// Update the graph
315+
graph.Put(typeID, s.clone())
316+
}
317+
318+
// clone returns a copy of s.entrySchema's fields as an EntrySchema
319+
// object
320+
func (s *EntrySchema) clone() EntrySchema {
321+
var copy EntrySchema
322+
copy.entrySchema = s.entrySchema
323+
return copy
283324
}
284325

285326
// This helper's used by CachedList + EntrySchema#fill(). The reason for
@@ -339,16 +380,9 @@ func pluginName(e Entry) string {
339380
switch e.(type) {
340381
case Root:
341382
return CName(e)
342-
case *Registry:
343-
return ""
344383
default:
345-
// e has no ID. This is possible if e's from the apifs package. For now,
346-
// it is enough to return "__apifs__" here because this is an unlikely
347-
// edge case.
348-
//
349-
// TODO: Panic here once https://github.com/puppetlabs/wash/issues/438
350-
// is resolved.
351-
return "__apifs__"
384+
// e is an apifs entry or a core plugin entry used by an external plugin
385+
return ""
352386
}
353387
}
354388
segments := strings.SplitN(trimmedID, "/", 2)

plugin/external/coreEntries.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010

1111
type coreEntry interface {
1212
createInstance(parent *pluginEntry, decodedEntry decodedExternalPluginEntry) (plugin.Entry, error)
13-
schema() *plugin.EntrySchema
13+
template() plugin.Entry
1414
}
1515

1616
var coreEntries = map[string]coreEntry{
@@ -31,6 +31,6 @@ func (volumeFS) createInstance(parent *pluginEntry, e decodedExternalPluginEntry
3131
return volume.NewFS(e.Name, parent, int(opts.Maxdepth)), nil
3232
}
3333

34-
func (volumeFS) schema() *plugin.EntrySchema {
35-
return (&volume.FS{}).Schema()
34+
func (volumeFS) template() plugin.Entry {
35+
return &volume.FS{}
3636
}

plugin/external/pluginEntry.go

+19-10
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
"time"
1414

1515
"github.com/getlantern/deepcopy"
16-
"github.com/jinzhu/copier"
1716

1817
"github.com/emirpasic/gods/maps/linkedhashmap"
1918
"github.com/puppetlabs/wash/activity"
@@ -711,17 +710,24 @@ func unmarshalSchemaGraph(pluginName, rawTypeID string, stdout []byte) (*linkedh
711710
graph := linkedhashmap.New()
712711
putNode := func(rawTypeID string, rawSchema interface{}) error {
713712
if coreEnt, ok := coreEntries[rawTypeID]; ok {
714-
pluginSchema := coreEnt.schema()
715-
716-
// Copy only the public fields so we serialize it as just data. Uses copier because it uses
717-
// reflect to copy public fields, rather than Marshal/UnmarshalJSON which we've overridden.
718-
var schema plugin.EntrySchema
719-
err := copier.Copy(&schema, pluginSchema)
720-
if err != nil {
721-
panic(fmt.Sprintf("should always be able to copy from EntrySchema to EntrySchema: %v", err))
713+
template := coreEnt.template()
714+
rawTypeID = plugin.TypeID(template)
715+
if populatedTypeIDs[rawTypeID] {
716+
// We've already included this entry's schema-graph
717+
return nil
722718
}
719+
coreEntSchemaGraph, _ := plugin.SchemaGraph(template)
720+
coreEntSchemaGraph.Each(func(rawTypeIDV interface{}, schemaV interface{}) {
721+
// Munge the schema's children's type IDs
722+
schema := schemaV.(plugin.EntrySchema)
723+
children := []string{}
724+
for _, child := range schema.Children {
725+
children = append(children, namespace(pluginName, child))
726+
}
727+
schema.Children = children
728+
graph.Put(namespace(pluginName, rawTypeIDV.(string)), schema)
729+
})
723730
populatedTypeIDs[rawTypeID] = true
724-
graph.Put(namespace(pluginName, rawTypeID), schema)
725731
return nil
726732
}
727733

@@ -764,6 +770,9 @@ func unmarshalSchemaGraph(pluginName, rawTypeID string, stdout []byte) (*linkedh
764770
}
765771
var namespacedChildren []string
766772
for _, child := range node.Children {
773+
if coreEnt, ok := coreEntries[child]; ok {
774+
child = plugin.TypeID(coreEnt.template())
775+
}
767776
requiredTypeIDs[child] = true
768777
namespacedChildren = append(namespacedChildren, namespace(pluginName, child))
769778
}

plugin/external/pluginEntry_test.go

+55
Original file line numberDiff line numberDiff line change
@@ -1385,6 +1385,61 @@ func (suite *ExternalPluginEntryTestSuite) TestUnmarshalSchemaGraph_ValidInput()
13851385
}
13861386
}
13871387

1388+
func (suite *ExternalPluginEntryTestSuite) TestUnmarshalSchemaGraph_CoreEntries() {
1389+
entry := &pluginEntry{
1390+
rawTypeID: "foo",
1391+
}
1392+
entry.SetTestID("fooPlugin")
1393+
1394+
stdout := []byte(`
1395+
{
1396+
"foo":{
1397+
"label": "fooLabel",
1398+
"methods": ["list"],
1399+
"children": ["__volume::fs__"]
1400+
},
1401+
"__volume::fs__": {}
1402+
}
1403+
`)
1404+
1405+
graph, err := unmarshalSchemaGraph(pluginName(entry), rawTypeID(entry), stdout)
1406+
if suite.NoError(err) {
1407+
assertSchema := func(typeID string, assertFunc func(plugin.EntrySchema)) {
1408+
schema, found := graph.Get(typeID)
1409+
if !found {
1410+
suite.FailNow("expected %v to be present in schema graph", typeID)
1411+
}
1412+
assertFunc(schema.(plugin.EntrySchema))
1413+
}
1414+
1415+
// Ensure that only four nodes exist in schema graph -- "foo", volume::fs,
1416+
// volume::dir, and volume::file
1417+
suite.Equal(int(4), graph.Size())
1418+
1419+
// Now ensure that the right nodes are set in the graph
1420+
volumeFSTemplate := (&volumeFS{}).template()
1421+
assertSchema("fooPlugin::foo", func(s plugin.EntrySchema) {
1422+
expectedVolumeFSTypeID := fmt.Sprintf("fooPlugin::%v", plugin.TypeID(volumeFSTemplate))
1423+
suite.Equal([]string{expectedVolumeFSTypeID}, s.Children)
1424+
})
1425+
// Ensure that volume::fs' schema-graph's been merged with our schema graph
1426+
// and that all the type IDs are properly namespaced
1427+
volumeFSGraph, _ := plugin.SchemaGraph(volumeFSTemplate)
1428+
volumeFSGraph.Each(func(typeIDV interface{}, schemaV interface{}) {
1429+
typeID := typeIDV.(string)
1430+
schema := schemaV.(plugin.EntrySchema)
1431+
expectedChildren := []string{}
1432+
for _, child := range schema.Children {
1433+
expectedChildren = append(expectedChildren, "fooPlugin::"+child)
1434+
}
1435+
assertSchema("fooPlugin::"+typeID, func(s plugin.EntrySchema) {
1436+
suite.Equal(schema.Label, s.Label)
1437+
suite.Equal(expectedChildren, s.Children)
1438+
})
1439+
})
1440+
}
1441+
}
1442+
13881443
func TestExternalPluginEntry(t *testing.T) {
13891444
suite.Run(t, new(ExternalPluginEntryTestSuite))
13901445
}

0 commit comments

Comments
 (0)