Closed wsquan171 closed 1 month ago
Is poly_struct
a necessary building block in polymorphic support? Unfortunately resources we have today do not have this wrapper. For example, service resource with polymorphic entries may look something like:
resource "nsxt_policy_service" "x" {
display_name = "S1"
l4_port_set_entry {
display_name = "TCP80"
protocol = "TCP"
destination_ports = ["80"]
}
}
I understand this would mean that we will not be able to refactor most existing resources with the new library.
Is
poly_struct
a necessary building block in polymorphic support? Unfortunately resources we have today do not have this wrapper. For example, service resource with polymorphic entries may look something like:
For the current approach this is true. For some resources like you mentioned, poly_struct
is the additional layer, however, for some others the inner layer is the extra one (especially when most attrs are shared across the child classes on NSX)
The problem here to address is that we want an explicit (and standard) way to express the two following items:
If we remove the poly_struct
layer, the sdk name need to be repeated for all child attrs in tf schema (i.e. in the test example cat and coffee), along with the mapping of tf attr name to nsx resource type. I don't think this will fit all current resources, as we don't currently have a standard approach to polymorphic fields. However, if this is a fit for majority of cases, I think it would worth it to make the change. Do you think the new format looks better?
@annakhm I've added support for both formats: with or without an wrapping layer. Also cleaned up some exisiting code.
As summerized in the internal doc, this should be able to cover >50% of exisiting resource that involves polymorphism. The ones needs further work (probably a future PR when needed) are:
Looks great and also thanks for the thorough test coverage! The only thing I think can be improved it tests is nested polymorphic structure (unless i missed it). Is is possible to cover this?
@annakhm Thanks. Let's track the test imporvements in a follow-up PR
This PR adds support of polymorphic struct for the reflect lib. Two approaches used in existing TF resource schema are supported in this PR.
Dedicated attribute wrapping polymorphic classes
Suppose an attr
poly_struct
can accept two types:cat
andcoffee
, the "wrapped" format expects the followings:Suppose
poly_struct
is a list, and resource is defined as below:metadata
definition expects the followings:At
poly_struct
levelPolymorphicType
aswrapped
ResourceTypeMap
, where the key is all potential tf sub-object (in this case,cat
andcoffee
), and value is theResourceType
value reported from NSXTypeIdentifier
providing the SDK field name and API JSON name for the attr to identify the resource type. Defaults to useResourceType
andresource_type
respectivelypoly_struct
should include all sub-objects, while indicating them as mutal exclusive usingConflictsWith
At sub-object level
ReflectType
should be the golang type directly matching with this sub classBindingType
is required from SDK so it can be statically converted as*data.StructValue
(or slice equivalant)TypeIdentifier
to match with the wrapping levelSdkFieldName
will be ignoredNo wrapping level ("flat")
Similiarly, if the SDK field is a polymorphic list, it's also possible to express elements of the same child class as a separate terraform schema attr. In this case, the resource is defined as below:
In this case, multiple attrs will be combined into one SDK list. For each object, the followings are expected:
PolymorphicType
asflat
ReflectType
matching with the corresponding sub classBindingType
matching withReflectType
TypeIdentifier
ResourceType
Refer to
nsxt/metadata/metadata_poly_test.go
for the full example for both use cases.