@@ -18,12 +18,31 @@ func TypeID(e Entry) string {
18
18
pluginName := pluginName (e )
19
19
rawTypeID := rawTypeID (e )
20
20
if pluginName == "" {
21
- // e is the plugin registry
21
+ // e is the plugin registry or a core entry used by an external plugin
22
22
return rawTypeID
23
23
}
24
24
return namespace (pluginName , rawTypeID )
25
25
}
26
26
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
+
27
46
func schema (e Entry ) (* EntrySchema , error ) {
28
47
switch t := e .(type ) {
29
48
case externalPlugin :
@@ -49,7 +68,10 @@ func schema(e Entry) (*EntrySchema, error) {
49
68
IsSingleton ().
50
69
SetDescription (registryDescription )
51
70
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 {})
53
75
for _ , root := range t .pluginRoots {
54
76
childSchema , err := Schema (root )
55
77
if err != nil {
@@ -73,6 +95,8 @@ func schema(e Entry) (*EntrySchema, error) {
73
95
schema .graph .Put (key , value )
74
96
})
75
97
}
98
+ // Update the graph
99
+ schema .graph .Put (typeID , schema .clone ())
76
100
return schema , nil
77
101
default :
78
102
// e is a core-plugin
@@ -137,9 +161,10 @@ func NewEntrySchema(e Entry, label string) *EntrySchema {
137
161
// how plugin.EntrySchema objects are meant to be used.
138
162
func (s EntrySchema ) MarshalJSON () ([]byte , error ) {
139
163
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.
143
168
return json .Marshal (s .entrySchema )
144
169
}
145
170
@@ -253,12 +278,18 @@ func (s *EntrySchema) fill(graph *linkedhashmap.Map) {
253
278
s .fillPanicf ("bad value passed into SetMetadataSchema: %v" , err )
254
279
}
255
280
}
256
- graph . Put ( TypeID (s .entry ), & s . entrySchema )
281
+ typeID := TypeID (s .entry )
257
282
258
- // Fill-in the children
259
283
if ! ListAction ().IsSupportedOn (s .entry ) {
284
+ graph .Put (typeID , s .clone ())
260
285
return
261
286
}
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 {})
262
293
// "sParent" is read as "s.parent"
263
294
sParent := s .entry .(Parent )
264
295
children := sParent .ChildSchemas ()
@@ -280,6 +311,16 @@ func (s *EntrySchema) fill(graph *linkedhashmap.Map) {
280
311
passAlongWrappedTypes (sParent , child .entry )
281
312
child .fill (graph )
282
313
}
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
283
324
}
284
325
285
326
// This helper's used by CachedList + EntrySchema#fill(). The reason for
@@ -339,16 +380,9 @@ func pluginName(e Entry) string {
339
380
switch e .(type ) {
340
381
case Root :
341
382
return CName (e )
342
- case * Registry :
343
- return ""
344
383
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 ""
352
386
}
353
387
}
354
388
segments := strings .SplitN (trimmedID , "/" , 2 )
0 commit comments