Generate example manifests with dependencies#15
Conversation
bb1235f to
c1fa3e0
Compare
13c5e71 to
66f6774
Compare
pkg/config/provider.go
Outdated
There was a problem hiding this comment.
What would be the advantage of this separate chain over using the existing configurators to manipulate the example like done here?
There was a problem hiding this comment.
In the configuration use-cases we've met so far, we observed that we may need the config.Resource associated with a manifest which we want to modify. An example is injecting region field to non-IAM resources. Currently, when we load the metadata we only have the config.Resource object available to the root resource and not the dependencies. That's why I went with a modifier function that we can call with a config.Resource for both the root resource and any associated dependencies.
One alternative I considered was to just introduce a SetPathValue function for dependencies and require the caller to make any checks solely based on the Terraform resource name (such as if the resource name starts with aws_iam, do not inject a region field). But this API allows us to write shorter & cleaner configuration overrides compared to this approach.
Another approach that I did not want to implement here as I think it would deserve a separate PR was to change the registry.MetaResource structure so that we can associate config.Resource with the dependencies. One challenge here (associated with both the root resource and its dependencies) is that the associated config.Resource may not have been finalized yet as we load the provider metadata. The deferring made possible with the modifier functions is that we make sure we consume the final config.Resource.
An example consumption for this API is as follows:
func setDefaultRegion(object *fieldpath.Paved, r *config.Resource) error {
if r.ShortGroup == "iam" {
return nil
}
return errors.Wrap(object.SetValue("spec.forProvider.region", "us-west-1"), "cannot set default region")
}, which is used to set the default region for both root resources and any dependencies encountered.
There was a problem hiding this comment.
Currently, when we load the metadata we only have the config.Resource object available to the root resource and not the dependencies. That's why I went with a modifier function that we can call with a config.Resource for both the root resource and any associated dependencies.
Another approach that I did not want to implement here as I think it would deserve a separate PR was to change the registry.MetaResource structure so that we can associate config.Resource with the dependencies. One challenge here (associated with both the root resource and its dependencies) is that the associated config.Resource may not have been finalized yet as we load the provider metadata. The deferring made possible with the modifier functions is that we make sure we consume the final config.Resource.
What do you mean by dependencies, is it the .MetaResource.Examples[*].Dependencies field or something else? If it's MetaResource field, after a recent change, it's loaded here before any configurator is run, we're able to set the region for all examples via a configuration and all config.Resource objects are finalized before any codegen starts.
If I understand correctly, at the moment, functionally the difference between using a configurator and the example modifier introduced here is when they are called; the latter being called after all operations are done on the examples, the former being called before any codegen starts. I think this touches a little bit to our discussion here regarding finalization of the config/instructions before starting the codegen and I see a similar pattern here with SkipReferencesTo as well where we give instruction to be applied later, independent of other generators.
In general, I think if we can do what these additional config endpoints can do with a configurator, we should do so because:
- It'd keep the whole configuration story cohesive that there is only one place to change the source of truth for all things regarding the resource and you can have any generator be confident that they state of the config they're given is finalized and shared across other generators when they're run.
- Having examples or schema or
MetaResourcein some way modified separately strips them off from that assumption, i.e. you might have removed a field from an example that the CRD builder used to derive some information.- One recent example is that if we were to give a config to CRD builder regarding move of a field from spec to status instead of manipulating the schema itself, then other generators wouldn't have this information so we'd have to build a dependency graph of builders to keep all of their outputs in sync with each other.
- Having examples or schema or
- If we can do everything that can be done in an example modifier using resource configurator, are we really getting value from the additional field? If the function signature is the concern, we can come with common helper functions with a UX similar to the example modifier that can be called inside a configurator.
There was a problem hiding this comment.
I wanted to have the structured resource.Config available for the dependency manifests as we modify them but now removed the modifier chain. Now we may do something like the following for our configuration case (assuming no IAM resource has some non-IAM dependencies):
func RegionAddition() config.ResourceOption {
return func(r *config.Resource) {
if r.ShortGroup == "iam" {
return
}
...
for _, ex := range r.MetaResource.Examples {
if err := ex.SetPathValue("region", "us-west-1"); err != nil {
panic(err)
}
for k := range ex.Dependencies {
if strings.HasPrefix(k, "aws_iam") {
continue
}
if err := ex.Dependencies.SetPathValue(k, "region", "us-west-1"); err != nil {
panic(err)
}
}
}There was a problem hiding this comment.
Also removed the Resource.SkipReferencesTo API. Without regex matching it was not powerful enough and as you mentioned above, we would not prefer to invest in it.
pkg/pipeline/example.go
Outdated
There was a problem hiding this comment.
This is so much logic without tests but I can't block this anymore. Opened #47
- The target (to be tested) resource is marked with the "testing.upbound.io/test-target" annotation
…xample manifests Signed-off-by: Alper Rifat Ulucinar <ulucinar@users.noreply.github.com>
Signed-off-by: Alper Rifat Ulucinar <ulucinar@users.noreply.github.com>
Signed-off-by: Alper Rifat Ulucinar <ulucinar@users.noreply.github.com>
Signed-off-by: Alper Rifat Ulucinar <ulucinar@users.noreply.github.com>
- Remove Resource.SkipReferencesTo API Signed-off-by: Alper Rifat Ulucinar <ulucinar@users.noreply.github.com>
Description of your changes
Fixes #14
This PR depends on #12. With this PR, we now generate example manifests together with their dependencies and any auxiliary dependencies.
I have:
make reviewableto ensure this PR is ready for review.backport release-x.ylabels to auto-backport this PR if necessary.How has this code been tested
Here is a sample for the
azurerm_disk_encryption_setresource: