@@ -5,67 +5,82 @@ import (
55 "io"
66 "slices"
77 "strings"
8+ "sync"
89
910 "github.com/operator-framework/operator-registry/alpha/declcfg"
1011)
1112
12- // BundleRenderer defines the function signature for rendering bundle images
13+ // BundleRenderer defines the function signature for rendering a string containing a bundle image/path/file into a DeclarativeConfig fragment
14+ // It's provided as a discrete type to allow for easy mocking in tests as well as facilitating variable
15+ // restrictions on reference types
1316type BundleRenderer func (context.Context , string ) (* declcfg.DeclarativeConfig , error )
1417
1518// Template defines the common interface for all template types
1619type Template interface {
17- // RenderBundle renders a bundle image reference into a DeclarativeConfig
18- RenderBundle (ctx context.Context , image string ) (* declcfg.DeclarativeConfig , error )
19- // Render processes the template input and returns a DeclarativeConfig
20+ // RenderBundle renders a bundle image reference into a DeclarativeConfig fragment.
21+ // This function is used to render a single bundle image reference by a template instance,
22+ // and is provided to the template on construction.
23+ // This is typically used in the call to Render the template to DeclarativeConfig, and
24+ // needs to be configurable to handle different bundle image formats and configurations.
25+ RenderBundle (ctx context.Context , imageRef string ) (* declcfg.DeclarativeConfig , error )
26+ // Render processes the raw template yaml/json input and returns an expanded DeclarativeConfig
27+ // in the case where expansion fails, it returns an error
2028 Render (ctx context.Context , reader io.Reader ) (* declcfg.DeclarativeConfig , error )
2129 // Schema returns the schema identifier for this template type
2230 Schema () string
2331}
2432
25- // TemplateFactory creates template instances based on schema
26- type TemplateFactory interface {
33+ // Factory creates template instances based on schema
34+ type Factory interface {
2735 // CreateTemplate creates a new template instance with the given RenderBundle function
2836 CreateTemplate (renderBundle BundleRenderer ) Template
2937 // Schema returns the schema identifier this factory handles
3038 Schema () string
3139}
3240
33- // TemplateRegistry maintains a mapping of schema identifiers to template factories
34- type TemplateRegistry struct {
35- factories map [string ]TemplateFactory
41+ // templateRegistry maintains a mapping of schema identifiers to template factories
42+ type templateRegistry struct {
43+ mu sync.RWMutex
44+ factories map [string ]Factory
3645}
3746
3847// NewTemplateRegistry creates a new template registry
39- func NewTemplateRegistry () * TemplateRegistry {
40- return & TemplateRegistry {
41- factories : make (map [string ]TemplateFactory ),
48+ func NewTemplateRegistry () * templateRegistry {
49+ return & templateRegistry {
50+ factories : make (map [string ]Factory ),
4251 }
4352}
4453
4554// Register adds a template factory to the registry
46- func (r * TemplateRegistry ) Register (factory TemplateFactory ) {
55+ func (r * templateRegistry ) Register (factory Factory ) {
56+ r .mu .Lock ()
57+ defer r .mu .Unlock ()
4758 r .factories [factory .Schema ()] = factory
4859}
4960
5061// CreateTemplateBySchema creates a template instance based on the schema found in the input
5162// and returns a reader that can be used to render the template. The returned reader includes
5263// both the data consumed during schema detection and the remaining unconsumed data.
53- func (r * TemplateRegistry ) CreateTemplateBySchema (reader io.Reader , renderBundle BundleRenderer ) (Template , io.Reader , error ) {
64+ func (r * templateRegistry ) CreateTemplateBySchema (reader io.Reader , renderBundle BundleRenderer ) (Template , io.Reader , error ) {
5465 schema , replayReader , err := detectSchema (reader )
5566 if err != nil {
5667 return nil , nil , err
5768 }
5869
70+ r .mu .RLock ()
5971 factory , exists := r .factories [schema ]
72+ r .mu .RUnlock ()
6073 if ! exists {
6174 return nil , nil , & UnknownSchemaError {Schema : schema }
6275 }
6376
6477 return factory .CreateTemplate (renderBundle ), replayReader , nil
6578}
6679
67- func (r * TemplateRegistry ) CreateTemplateByType (templateType string , renderBundle BundleRenderer ) (Template , error ) {
80+ func (r * templateRegistry ) CreateTemplateByType (templateType string , renderBundle BundleRenderer ) (Template , error ) {
81+ r .mu .RLock ()
6882 factory , exists := r .factories [templateType ]
83+ r .mu .RUnlock ()
6984 if ! exists {
7085 return nil , & UnknownSchemaError {Schema : templateType }
7186 }
@@ -74,7 +89,9 @@ func (r *TemplateRegistry) CreateTemplateByType(templateType string, renderBundl
7489}
7590
7691// GetSupportedSchemas returns all supported schema identifiers
77- func (r * TemplateRegistry ) GetSupportedSchemas () []string {
92+ func (r * templateRegistry ) GetSupportedSchemas () []string {
93+ r .mu .RLock ()
94+ defer r .mu .RUnlock ()
7895 schemas := make ([]string , 0 , len (r .factories ))
7996 for schema := range r .factories {
8097 schemas = append (schemas , schema )
@@ -86,7 +103,9 @@ func (r *TemplateRegistry) GetSupportedSchemas() []string {
86103// GetSupportedTypes returns all supported template types
87104// TODO: in future, might store the type separately from the schema
88105// right now it's just the last part of the schema string
89- func (r * TemplateRegistry ) GetSupportedTypes () []string {
106+ func (r * templateRegistry ) GetSupportedTypes () []string {
107+ r .mu .RLock ()
108+ defer r .mu .RUnlock ()
90109 types := make ([]string , 0 , len (r .factories ))
91110 for schema := range r .factories {
92111 types = append (types , schema [strings .LastIndex (schema , "." )+ 1 :])
@@ -95,11 +114,18 @@ func (r *TemplateRegistry) GetSupportedTypes() []string {
95114 return types
96115}
97116
98- func (r * TemplateRegistry ) HasSchema (schema string ) bool {
117+ func (r * templateRegistry ) HasSchema (schema string ) bool {
118+ r .mu .RLock ()
119+ defer r .mu .RUnlock ()
99120 _ , exists := r .factories [schema ]
100121 return exists
101122}
102123
124+ func (r * templateRegistry ) HasType (templateType string ) bool {
125+ types := r .GetSupportedTypes ()
126+ return slices .Contains (types , templateType )
127+ }
128+
103129// UnknownSchemaError is returned when a schema is not recognized
104130type UnknownSchemaError struct {
105131 Schema string
0 commit comments