Skip to content

Commit eac88d3

Browse files
committed
Inject merge strategies into the config rather than the output, implement support for singleton lists.
Move applying SSA merge default config to provider. Use correct Computed value for list merge keys Signed-off-by: Jonathan Oddy <jonathan@woaf.net>
1 parent 2ef7077 commit eac88d3

File tree

3 files changed

+54
-33
lines changed

3 files changed

+54
-33
lines changed

pkg/config/provider.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@ func NewProvider(schema []byte, prefix string, modulePath string, metadata []byt
351351
p.Resources[name] = DefaultResource(name, terraformResource, terraformPluginFrameworkResource, providerMetadata.Resources[name], p.DefaultResourceOptions...)
352352
p.Resources[name].useTerraformPluginSDKClient = isTerraformPluginSDK
353353
p.Resources[name].useTerraformPluginFrameworkClient = isPluginFrameworkResource
354+
p.injectServerSideApplyDefaults(p.Resources[name], terraformResource, "")
354355
}
355356
for i, refInjector := range p.refInjectors {
356357
if err := refInjector.InjectReferences(p.Resources); err != nil {
@@ -360,6 +361,58 @@ func NewProvider(schema []byte, prefix string, modulePath string, metadata []byt
360361
return p
361362
}
362363

364+
func (p *Provider) injectServerSideApplyDefaults(cfg *Resource, res *schema.Resource, basePath string) { //nolint:gocyclo // Easier to follow the logic in a single function
365+
366+
for k, es := range res.Schema {
367+
368+
var fieldPath string
369+
if basePath == "" {
370+
fieldPath = k
371+
} else {
372+
fieldPath = fmt.Sprintf("%s.%s", basePath, k)
373+
}
374+
375+
if r, ok := es.Elem.(*schema.Resource); ok {
376+
if es.Type == schema.TypeList && es.MaxItems == 1 {
377+
cfg.ServerSideApplyMergeStrategies[fieldPath] = MergeStrategy{
378+
ListMergeStrategy: ListMergeStrategy{
379+
MergeStrategy: ListTypeMap,
380+
ListMapKeys: ListMapKeys{InjectedKey: InjectedKey{
381+
Key: "ssamergekey",
382+
DefaultValue: `"0"`,
383+
}},
384+
},
385+
}
386+
}
387+
p.injectServerSideApplyDefaults(cfg, r, fieldPath)
388+
} else {
389+
switch es.Type { //nolint:exhaustive
390+
case schema.TypeSet:
391+
if el, ok := es.Elem.(*schema.Schema); ok {
392+
switch el.Type { //nolint:exhaustive
393+
case schema.TypeString, schema.TypeBool, schema.TypeInt, schema.TypeFloat:
394+
cfg.ServerSideApplyMergeStrategies[fieldPath] = MergeStrategy{
395+
ListMergeStrategy: ListMergeStrategy{
396+
MergeStrategy: ListTypeSet,
397+
},
398+
}
399+
}
400+
}
401+
case schema.TypeMap:
402+
if el, ok := es.Elem.(*schema.Schema); ok {
403+
switch el.Type { //nolint:exhaustive
404+
case schema.TypeString, schema.TypeBool, schema.TypeInt, schema.TypeFloat:
405+
// TODO(jono): I think this may be unnecessary since maps appear to default to granular?
406+
cfg.ServerSideApplyMergeStrategies[fieldPath] = MergeStrategy{
407+
MapMergeStrategy: MapTypeGranular,
408+
}
409+
}
410+
}
411+
}
412+
}
413+
}
414+
}
415+
363416
// AddResourceConfigurator adds resource specific configurators.
364417
func (p *Provider) AddResourceConfigurator(resource string, c ResourceConfiguratorFn) { //nolint:interfacer
365418
// Note(turkenh): nolint reasoning - easier to provide a function without

pkg/types/builder.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ func injectServerSideApplyListMergeKeys(cfg *config.Resource) error { //nolint:g
115115
el.Schema[s.ListMergeStrategy.ListMapKeys.InjectedKey.Key] = &schema.Schema{
116116
Type: schema.TypeString,
117117
Required: true,
118+
Computed: sch.Computed,
118119
Description: descriptionInjectedKey,
119120
}
120121
if s.ListMergeStrategy.ListMapKeys.InjectedKey.DefaultValue != "" {

pkg/types/field.go

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -161,42 +161,9 @@ func NewField(g *Builder, cfg *config.Resource, r *resource, sch *schema.Schema,
161161
f.FieldType = fieldType
162162
f.InitType = initType
163163

164-
AddServerSideApplyMarkers(f)
165164
return f, errors.Wrapf(AddServerSideApplyMarkersFromConfig(f, cfg), "cannot add the server-side apply merge strategy markers for the field")
166165
}
167166

168-
// AddServerSideApplyMarkers adds server-side apply comment markers to indicate
169-
// that scalar maps and sets can be merged granularly, not replace atomically.
170-
func AddServerSideApplyMarkers(f *Field) {
171-
// for sensitive fields, we generate secret or secret key references
172-
if f.Schema.Sensitive {
173-
return
174-
}
175-
176-
switch f.Schema.Type { //nolint:exhaustive
177-
case schema.TypeMap:
178-
// A map should always have an element of type Schema.
179-
if es, ok := f.Schema.Elem.(*schema.Schema); ok {
180-
switch es.Type { //nolint:exhaustive
181-
// We assume scalar types can be granular maps.
182-
case schema.TypeString, schema.TypeBool, schema.TypeInt, schema.TypeFloat:
183-
f.Comment.ServerSideApplyOptions.MapType = ptr.To[config.MapType](config.MapTypeGranular)
184-
}
185-
}
186-
case schema.TypeSet:
187-
if es, ok := f.Schema.Elem.(*schema.Schema); ok {
188-
switch es.Type { //nolint:exhaustive
189-
// We assume scalar types can be granular sets.
190-
case schema.TypeString, schema.TypeBool, schema.TypeInt, schema.TypeFloat:
191-
f.Comment.ServerSideApplyOptions.ListType = ptr.To[config.ListType](config.ListTypeSet)
192-
}
193-
}
194-
}
195-
// TODO(negz): Can we reliably add SSA markers for lists of objects? Do we
196-
// have cases where we're turning a Terraform map of maps into a list of
197-
// objects with a well-known key that we could merge on?
198-
}
199-
200167
func setInjectedField(fp, k string, f *Field, s config.MergeStrategy) bool {
201168
if fp != fmt.Sprintf("%s.%s", k, s.ListMergeStrategy.ListMapKeys.InjectedKey.Key) {
202169
return false

0 commit comments

Comments
 (0)