Add support for generating MR API for Terraform resource's nested single configuration blocks #342
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description of your changes
Related with: crossplane-contrib/provider-upjet-aws#889, crossplane-contrib/provider-upjet-aws#1130
While generating the managed resource (MR) API for Terraform's aws_opensearchserverless_security_config resource, we've observed that the required parameter
saml_options
is not generated and thus, the resulting API is not usable. @erhancagirici did an initial analysis and the root cause of the issue turns out to be upjet skipping code generation for nested configuration blocks with theSchemaNestingModeSingle
nesting mode. Looks like we have initially chosen to do so to prevent the code generation for the resource CRUD timeout parameter generation for each MR API and opted for a static CRUD timeout configuration for the generated MRs (it's currently not possible to configure such timeouts dynamically at runtime).However, this is a blocker for the generation of resources with a required nested configuration block in single mode.
This PR still prevents the generation of top-level CRUD timeouts for the
resource.Terraformed
resources (so we still don't allow dynamic configuration of such timeouts) but allows the code generation for other nested configuration blocks in single mode. We now filter the top-level CRUD timeout configuration blocks by name (instead of the previous nesting mode based approach).For the converted configuration blocks,
Schema.MaxItems
is always set to 1, and if there are any required mappings for the configuration block,Schema.MinItems
is also set to 1, together with theOptional
andRequired
attributes. TheSchema.Type
is alwaysschema.TypeList
for such nested configuration blocks. Thus they are modeled as lists with length constraints.This PR also introduces the
config.SchemaElementOption.EmbeddedObject
API which can be used to configure upjet's code generation pipeline to generate an embedded object instead of a singleton list. We've chosen this explicit approach instead of making the schema block information available to the code generation pipeline and automatically deducing the schema elements with the single nesting mode with the following motivations:MaxLength = 1
constraint on them could change in the future depending on their semantics. So we need to be careful with any sort of automatic conversions and plan ahead for API changes (possibly via conversion functions but converting between a new API supporting multiple elements in a list and an older API with an embedded object is cumbersome to implement in our generated APIs with the proper backwards compatibility constraints).aws_opensearchserverless_security_config
resource'ssaml_options
field. So, a manual configuration approach is okay until we would like to tackle with One-element arrays could be considered as objects #136 (which is subject to [2] above).An example configuration for the
aws_opensearchserverless_security_config
resource'ssaml_options
configuration is as follows:The specified path is the Terraform path of the schema element which is to be generated as an embedded object without any indices or wildcards (the same syntax for the
config.SchemaElementOptions.SetAddToObservation
). Please note that the code generation pipeline currently makes no checks on the size constraints of the list, i.e., it does not assert that the specified path is a singleton list (due to [3] above, this is a very special case we need to handle for just two resources).We also add the
config.ExternalNameFrom
external-name configuration with this PR.ExternalNameFrom
is anExternalName
configuration which uses a parent configuration as its base and modifies any of theGetIDFn
,GetExternalNameFn
orSetIdentifierArgumentsFn
functions of the configuration. This enables us to reuse the existingExternalName
configurations with modifications in their behaviors via compositions. As an example in https://github.com/upbound/provider-aws, there are resources that lend themselves to config.TemplatedStringAsIdentifier but fail or misbehave when the Terraform ID string is initially invalid due to a missing external-name annotation. A common workaround is to use a default string for the external-name if it's missing (that should never resolve to an existing external resource). This can now be achieved with a configuration like the following:This
ExternalName
configuration will use the supplieddefaultName
when the external-name annotation is empty to prevent the underlying resource from misbehaving.I have:
make reviewable
to ensure this PR is ready for review.backport release-x.y
labels to auto-backport this PR if necessary.How has this code been tested
Tested via crossplane-contrib/provider-upjet-aws#1130.