diff --git a/nsxt/data_source_nsxt_policy_edge_node.go b/nsxt/data_source_nsxt_policy_edge_node.go index 315e1fb0d..770762467 100644 --- a/nsxt/data_source_nsxt_policy_edge_node.go +++ b/nsxt/data_source_nsxt_policy_edge_node.go @@ -8,6 +8,8 @@ import ( "strconv" "strings" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/vmware/vsphere-automation-sdk-go/runtime/bindings" @@ -42,7 +44,7 @@ func dataSourceNsxtPolicyEdgeNodeRead(d *schema.ResourceData, m interface{}) err // for bool types, but in this case it works and GetOk doesn't memberIndex, memberIndexSet := d.GetOkExists("member_index") - if isPolicyGlobalManager(m) || nsxVersionHigherOrEqual("3.2.0") { + if isPolicyGlobalManager(m) || util.NsxVersionHigherOrEqual("3.2.0") { query := make(map[string]string) query["parent_path"] = edgeClusterPath if memberIndexSet { diff --git a/nsxt/gateway_common.go b/nsxt/gateway_common.go index 67bf8ce5a..cd6cd66eb 100644 --- a/nsxt/gateway_common.go +++ b/nsxt/gateway_common.go @@ -5,6 +5,10 @@ import ( "log" "strings" + nsx_policy "github.com/vmware/terraform-provider-nsxt/api" + utl "github.com/vmware/terraform-provider-nsxt/api/utl" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/vmware/vsphere-automation-sdk-go/runtime/bindings" @@ -15,9 +19,6 @@ import ( gm_model "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-gm/model" "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/infra/tier_0s" "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model" - - nsx_policy "github.com/vmware/terraform-provider-nsxt/api" - utl "github.com/vmware/terraform-provider-nsxt/api/utl" ) var nsxtPolicyTier0GatewayRedistributionRuleTypes = []string{ @@ -534,7 +535,7 @@ func setLocaleServiceRedistributionRulesConfig(rulesConfig []interface{}, config rule.RouteMapPath = &routeMapPath } - if nsxVersionHigherOrEqual("3.1.0") { + if util.NsxVersionHigherOrEqual("3.1.0") { if bgp { rule.Destinations = append(rule.Destinations, model.Tier0RouteRedistributionRule_DESTINATIONS_BGP) } @@ -565,7 +566,7 @@ func setLocaleServiceRedistributionConfig(redistributionConfigs []interface{}, s BgpEnabled: &bgpEnabled, } - if nsxVersionHigherOrEqual("3.1.0") { + if util.NsxVersionHigherOrEqual("3.1.0") { redistributionStruct.OspfEnabled = &ospfEnabled } @@ -580,7 +581,7 @@ func getLocaleServiceRedistributionRuleConfig(config *model.Tier0RouteRedistribu rule["name"] = ruleConfig.Name rule["route_map_path"] = ruleConfig.RouteMapPath rule["types"] = ruleConfig.RouteRedistributionTypes - if nsxVersionHigherOrEqual("3.1.0") { + if util.NsxVersionHigherOrEqual("3.1.0") { bgp := false ospf := false for _, destination := range ruleConfig.Destinations { diff --git a/nsxt/metadata/metadata.go b/nsxt/metadata/metadata.go new file mode 100644 index 000000000..4479da801 --- /dev/null +++ b/nsxt/metadata/metadata.go @@ -0,0 +1,183 @@ +package metadata + +import ( + "log" + "reflect" + + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +type Metadata struct { + // we need a separate schema type, in addition to terraform SDK type, + // in order to distinguish between single subclause and a list of entries + SchemaType string + ReadOnly bool + SdkFieldName string + // This attribute is parent path for the object + IsParentPath bool + IntroducedInVersion string + // skip handling of this attribute - it will be done manually + Skip bool + ReflectType reflect.Type + TestData Testdata +} + +type ExtendedSchema struct { + Schema schema.Schema + Metadata Metadata +} + +type ExtendedResource struct { + Schema map[string]*ExtendedSchema +} + +type Testdata struct { + CreateValue interface{} + UpdateValue interface{} +} + +// GetExtendedSchema is a helper to convert terraform sdk schema to extended schema +func GetExtendedSchema(sch *schema.Schema) *ExtendedSchema { + shallowCopy := *sch + return &ExtendedSchema{ + Schema: shallowCopy, + Metadata: Metadata{ + Skip: true, + }, + } +} + +// GetSchemaFromExtendedSchema gets terraform sdk schema from extended schema definition +func GetSchemaFromExtendedSchema(ext map[string]*ExtendedSchema) map[string]*schema.Schema { + result := make(map[string]*schema.Schema) + + for key, value := range ext { + log.Printf("[INFO] inspecting schema key %s, value %v", key, value) + shallowCopy := value.Schema + if (value.Schema.Type == schema.TypeList) || (value.Schema.Type == schema.TypeSet) { + elem, ok := shallowCopy.Elem.(*ExtendedSchema) + if ok { + shallowCopy.Elem = elem.Schema + } else { + elem, ok := shallowCopy.Elem.(*ExtendedResource) + if ok { + shallowCopy.Elem = &schema.Resource{ + Schema: GetSchemaFromExtendedSchema(elem.Schema), + } + } + } + } + // TODO: deepcopy needed? + result[key] = &shallowCopy + } + + return result +} + +// StructToSchema converts NSX model struct to terraform schema +// currently supports nested subtype and trivial types +// TODO - support a list of structs +func StructToSchema(elem reflect.Value, d *schema.ResourceData, metadata map[string]*ExtendedSchema, parent string, parentMap map[string]interface{}) { + for key, item := range metadata { + if item.Metadata.Skip { + continue + } + + log.Printf("[INFO] inspecting key %s", key) + if len(parent) > 0 { + log.Printf("[INFO] parent %s key %s", parent, key) + } + if item.Metadata.SchemaType == "struct" { + nestedObj := elem.FieldByName(item.Metadata.SdkFieldName) + nestedSchema := make(map[string]interface{}) + childElem := item.Schema.Elem.(*ExtendedResource) + StructToSchema(nestedObj.Elem(), d, childElem.Schema, key, nestedSchema) + log.Printf("[INFO] assigning struct %v to %s", nestedObj, key) + // TODO - get the schema from nested type if parent in present + var nestedSlice []map[string]interface{} + nestedSlice = append(nestedSlice, nestedSchema) + if len(parent) > 0 { + parentMap[key] = nestedSlice + } else { + d.Set(key, nestedSlice) + } + } else { + if len(parent) > 0 { + log.Printf("[INFO] assigning nested value %v to %s", elem.FieldByName(item.Metadata.SdkFieldName).Interface(), key) + parentMap[key] = elem.FieldByName(item.Metadata.SdkFieldName).Interface() + } else { + log.Printf("[INFO] assigning value %v to %s", elem.FieldByName(item.Metadata.SdkFieldName).Interface(), key) + d.Set(key, elem.FieldByName(item.Metadata.SdkFieldName).Interface()) + } + } + } +} + +// SchemaToStruct converts terraform schema to NSX model struct +// currently supports nested subtype and trivial types +// TODO - support a list of structs +func SchemaToStruct(elem reflect.Value, d *schema.ResourceData, metadata map[string]*ExtendedSchema, parent string, parentMap map[string]interface{}) { + for key, item := range metadata { + if item.Metadata.ReadOnly || item.Metadata.Skip { + continue + } + if item.Metadata.IntroducedInVersion != "" && util.NsxVersionLower(item.Metadata.IntroducedInVersion) { + continue + } + + log.Printf("[INFO] inspecting key %s", key) + if len(parent) > 0 { + log.Printf("[INFO] parent %s key %s", parent, key) + } + if item.Metadata.SchemaType == "string" { + var value string + if len(parent) > 0 { + value = parentMap[key].(string) + } else { + value = d.Get(key).(string) + } + log.Printf("[INFO] assigning string %v to %s", value, key) + elem.FieldByName(item.Metadata.SdkFieldName).Set(reflect.ValueOf(&value)) + } + if item.Metadata.SchemaType == "bool" { + var value bool + if len(parent) > 0 { + value = parentMap[key].(bool) + } else { + value = d.Get(key).(bool) + } + log.Printf("[INFO] assigning bool %v to %s", value, key) + elem.FieldByName(item.Metadata.SdkFieldName).Set(reflect.ValueOf(&value)) + } + if item.Metadata.SchemaType == "int" { + var value int64 + if len(parent) > 0 { + value = int64(parentMap[key].(int)) + } else { + value = int64(d.Get(key).(int)) + } + log.Printf("[INFO] assigning int %v to %s", value, key) + elem.FieldByName(item.Metadata.SdkFieldName).Set(reflect.ValueOf(&value)) + } + if item.Metadata.SchemaType == "struct" { + nestedObj := reflect.New(item.Metadata.ReflectType) + /* + // Helper for list of structs + slice := reflect.MakeSlice(reflect.TypeOf(nestedObj), 1, 1) + */ + nestedSchemaList := d.Get(key).([]interface{}) + if len(nestedSchemaList) == 0 { + continue + } + nestedSchema := nestedSchemaList[0].(map[string]interface{}) + + childElem := item.Schema.Elem.(*ExtendedResource) + SchemaToStruct(nestedObj.Elem(), d, childElem.Schema, key, nestedSchema) + log.Printf("[INFO] assigning struct %v to %s", nestedObj, key) + elem.FieldByName(item.Metadata.SdkFieldName).Set(nestedObj) + // TODO - get the schema from nested type if parent in present + } + } +} diff --git a/nsxt/provider.go b/nsxt/provider.go index 323b98f51..5dfda4fb1 100644 --- a/nsxt/provider.go +++ b/nsxt/provider.go @@ -19,6 +19,9 @@ import ( "strings" "time" + tf_api "github.com/vmware/terraform-provider-nsxt/api/utl" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" api "github.com/vmware/go-vmware-nsxt" @@ -29,8 +32,6 @@ import ( "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-mp/nsx" "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-mp/nsx/model" "golang.org/x/exp/slices" - - tf_api "github.com/vmware/terraform-provider-nsxt/api/utl" ) var defaultRetryOnStatusCodes = []int{400, 409, 429, 500, 503, 504} @@ -1182,7 +1183,7 @@ func getPolicyConnectorWithHeaders(clients interface{}, customHeaders *map[strin // Init NSX version on demand if not done yet // This is also our indication to apply licenses, in case of delayed connection // This step is skipped if the connector is for special purpose, or for different endpoint - if nsxVersion == "" && !standaloneFlow { + if util.NsxVersion == "" && !standaloneFlow { initNSXVersion(connector) err := configureLicenses(connector, c.CommonConfig.LicenseKeys) if err != nil { diff --git a/nsxt/provider_test.go b/nsxt/provider_test.go index cf32196e5..a072d328f 100644 --- a/nsxt/provider_test.go +++ b/nsxt/provider_test.go @@ -12,6 +12,8 @@ import ( "strings" "testing" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" api "github.com/vmware/go-vmware-nsxt" @@ -89,7 +91,7 @@ func testAccGetClient() (*api.APIClient, error) { } func testAccNSXVersion(t *testing.T, requiredVersion string) { - if nsxVersion == "" { + if util.NsxVersion == "" { connector, err := testAccGetPolicyConnector() if err != nil { t.Errorf("Failed to get policy connector") @@ -103,13 +105,13 @@ func testAccNSXVersion(t *testing.T, requiredVersion string) { } } - if nsxVersionLower(requiredVersion) { - t.Skipf("This test can only run in NSX %s or above (Current version %s)", requiredVersion, nsxVersion) + if util.NsxVersionLower(requiredVersion) { + t.Skipf("This test can only run in NSX %s or above (Current version %s)", requiredVersion, util.NsxVersion) } } func testAccNSXVersionLessThan(t *testing.T, requiredVersion string) { - if nsxVersion == "" { + if util.NsxVersion == "" { connector, err := testAccGetPolicyConnector() if err != nil { t.Errorf("Failed to get policy connector") @@ -123,8 +125,8 @@ func testAccNSXVersionLessThan(t *testing.T, requiredVersion string) { } } - if nsxVersionHigherOrEqual(requiredVersion) { - t.Skipf("This test can only run in NSX below %s (Current version %s)", requiredVersion, nsxVersion) + if util.NsxVersionHigherOrEqual(requiredVersion) { + t.Skipf("This test can only run in NSX below %s (Current version %s)", requiredVersion, util.NsxVersion) } } diff --git a/nsxt/resource_nsxt_cluster_virtual_ip.go b/nsxt/resource_nsxt_cluster_virtual_ip.go index 8ebf1f39b..68cc61439 100644 --- a/nsxt/resource_nsxt_cluster_virtual_ip.go +++ b/nsxt/resource_nsxt_cluster_virtual_ip.go @@ -7,6 +7,8 @@ import ( "fmt" "log" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-mp/nsx/cluster" @@ -104,7 +106,7 @@ func setClusterVirtualIP(d *schema.ResourceData, m interface{}) error { forceStr = nsxModel.ClusterVirtualIpProperties_FORCE_FALSE } var err error - if nsxVersionHigherOrEqual("4.0.0") { + if util.NsxVersionHigherOrEqual("4.0.0") { _, err = client.Setvirtualip(&forceStr, &ipv6Address, &ipAddress) } else { // IPv6 not supported @@ -138,7 +140,7 @@ func resourceNsxtClusterVirualIPDelete(d *schema.ResourceData, m interface{}) er log.Printf("[WARNING] Failed to clear virtual ip: %v", err) return handleDeleteError("ClusterVirtualIP", id, err) } - if nsxVersionHigherOrEqual("4.0.0") { + if util.NsxVersionHigherOrEqual("4.0.0") { _, err = client.Clearvirtualip6() if err != nil { log.Printf("[WARNING] Failed to clear virtual ipv6 ip: %v", err) diff --git a/nsxt/resource_nsxt_edge_transport_node.go b/nsxt/resource_nsxt_edge_transport_node.go index 07f39a29a..6f1748ce0 100644 --- a/nsxt/resource_nsxt_edge_transport_node.go +++ b/nsxt/resource_nsxt_edge_transport_node.go @@ -9,6 +9,8 @@ import ( "reflect" "time" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -896,7 +898,7 @@ func getEdgeNodeSettingsFromSchema(s interface{}) (*model.EdgeNodeSettings, erro SearchDomains: searchDomains, SyslogServers: syslogServers, } - if nsxVersionHigherOrEqual("4.0.0") { + if util.NsxVersionHigherOrEqual("4.0.0") { obj.EnableUptMode = &enableUptMode } return obj, nil diff --git a/nsxt/resource_nsxt_firewall_section.go b/nsxt/resource_nsxt_firewall_section.go index 8cf7655f2..fcff4013f 100644 --- a/nsxt/resource_nsxt_firewall_section.go +++ b/nsxt/resource_nsxt_firewall_section.go @@ -8,6 +8,8 @@ import ( "log" "net/http" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/vmware/go-vmware-nsxt/manager" @@ -379,7 +381,7 @@ func resourceNsxtFirewallSectionUpdate(d *schema.ResourceData, m interface{}) er var resp *http.Response var err error - if len(rules) == 0 || nsxVersionLower("2.2.0") { + if len(rules) == 0 || util.NsxVersionLower("2.2.0") { // Due to an NSX bug, the empty update should also be called to update ToS & tags fields section := *firewallSection.GetFirewallSection() // Update the section ignoring the rules diff --git a/nsxt/resource_nsxt_logical_router_downlink_port_test.go b/nsxt/resource_nsxt_logical_router_downlink_port_test.go index 6d1cbc10b..3d4aa5610 100644 --- a/nsxt/resource_nsxt_logical_router_downlink_port_test.go +++ b/nsxt/resource_nsxt_logical_router_downlink_port_test.go @@ -8,6 +8,8 @@ import ( "net/http" "testing" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" ) @@ -69,7 +71,7 @@ func TestAccResourceNsxtLogicalRouterDownlinkPort_withRelay(t *testing.T) { resourceType := "DhcpRelayService" // this is needed to init the version testAccNSXVersion(t, "2.2.0") - if nsxVersionLower("2.5.0") { + if util.NsxVersionLower("2.5.0") { resourceType = "LogicalService" } diff --git a/nsxt/resource_nsxt_nat_rule.go b/nsxt/resource_nsxt_nat_rule.go index b227aeee2..967a7adf2 100644 --- a/nsxt/resource_nsxt_nat_rule.go +++ b/nsxt/resource_nsxt_nat_rule.go @@ -7,6 +7,8 @@ import ( "fmt" "strings" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-mp/nsx/logical_routers/nat" @@ -121,7 +123,7 @@ func resourceNsxtNatRuleCreate(d *schema.ResourceData, m interface{}) error { displayName := d.Get("display_name").(string) tags := getMPTagsFromSchema(d) action := d.Get("action").(string) - if action == "NO_NAT" && nsxVersionHigherOrEqual("3.0.0") { + if action == "NO_NAT" && util.NsxVersionHigherOrEqual("3.0.0") { return fmt.Errorf("NO_NAT action is not supported in NSX versions 3.0.0 and greater. Use NO_SNAT and NO_DNAT instead") } enabled := d.Get("enabled").(bool) @@ -230,7 +232,7 @@ func resourceNsxtNatRuleUpdate(d *schema.ResourceData, m interface{}) error { displayName := d.Get("display_name").(string) tags := getMPTagsFromSchema(d) action := d.Get("action").(string) - if action == "NO_NAT" && nsxVersionHigherOrEqual("3.0.0") { + if action == "NO_NAT" && util.NsxVersionHigherOrEqual("3.0.0") { return fmt.Errorf("NO_NAT action is not supported in NSX versions 3.0.0 and greater. Use NO_SNAT and NO_DNAT instead") } enabled := d.Get("enabled").(bool) diff --git a/nsxt/resource_nsxt_policy_bgp_neighbor.go b/nsxt/resource_nsxt_policy_bgp_neighbor.go index d22cb5d95..c78eec74e 100644 --- a/nsxt/resource_nsxt_policy_bgp_neighbor.go +++ b/nsxt/resource_nsxt_policy_bgp_neighbor.go @@ -8,6 +8,8 @@ import ( "log" "strings" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client" @@ -243,13 +245,13 @@ func resourceNsxtPolicyBgpNeighborResourceDataToStruct(d *schema.ResourceData, i var rFilters []model.BgpRouteFiltering routeFiltering := d.Get("route_filtering").([]interface{}) - if len(routeFiltering) > 1 && nsxVersionLower("3.0.0") { + if len(routeFiltering) > 1 && util.NsxVersionLower("3.0.0") { return neighborStruct, fmt.Errorf("Only 1 element for 'route_filtering' is supported with NSX-T versions up to 3.0.0") } for _, filter := range routeFiltering { data := filter.(map[string]interface{}) addrFamily := data["address_family"].(string) - if addrFamily == model.BgpRouteFiltering_ADDRESS_FAMILY_L2VPN_EVPN && nsxVersionLower("3.0.0") { + if addrFamily == model.BgpRouteFiltering_ADDRESS_FAMILY_L2VPN_EVPN && util.NsxVersionLower("3.0.0") { return neighborStruct, fmt.Errorf("'%s' is not supported for 'address_family' with NSX-T versions less than 3.0.0", model.BgpRouteFiltering_ADDRESS_FAMILY_L2VPN_EVPN) } enabled := data["enabled"].(bool) @@ -271,7 +273,7 @@ func resourceNsxtPolicyBgpNeighborResourceDataToStruct(d *schema.ResourceData, i filterStruct.OutRouteFilters = outFilters } - if nsxVersionHigherOrEqual("3.0.0") && data["maximum_routes"] != 0 { + if util.NsxVersionHigherOrEqual("3.0.0") && data["maximum_routes"] != 0 { maxRoutes := int64(data["maximum_routes"].(int)) filterStruct.MaximumRoutes = &maxRoutes } @@ -448,7 +450,7 @@ func resourceNsxtPolicyBgpNeighborRead(d *schema.ResourceData, m interface{}) er } rf["in_route_filter"] = inFilter rf["out_route_filter"] = outFilter - if nsxVersionHigherOrEqual("3.0.0") && filter.MaximumRoutes != nil { + if util.NsxVersionHigherOrEqual("3.0.0") && filter.MaximumRoutes != nil { rf["maximum_routes"] = int(*filter.MaximumRoutes) } rFilters = append(rFilters, rf) diff --git a/nsxt/resource_nsxt_policy_context_profile.go b/nsxt/resource_nsxt_policy_context_profile.go index bb8523fa6..da19f5f50 100644 --- a/nsxt/resource_nsxt_policy_context_profile.go +++ b/nsxt/resource_nsxt_policy_context_profile.go @@ -7,14 +7,15 @@ import ( "fmt" "log" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client" - "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model" - "github.com/vmware/terraform-provider-nsxt/api/infra" cont_prof "github.com/vmware/terraform-provider-nsxt/api/infra/context_profiles" custom_attr "github.com/vmware/terraform-provider-nsxt/api/infra/context_profiles/custom_attributes" utl "github.com/vmware/terraform-provider-nsxt/api/utl" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client" + "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model" ) var attributeKeyMap = map[string]string{ @@ -470,7 +471,7 @@ func fillAttributesInSchema(d *schema.ResourceData, policyAttributes []model.Pol elem["sub_attribute"] = fillSubAttributesInSchema(policyAttribute.SubAttributes) } elem["is_alg_type"] = policyAttribute.IsALGType - } else if *policyAttribute.Key == model.PolicyAttributes_KEY_CUSTOM_URL && nsxVersionHigherOrEqual("4.0.0") { + } else if *policyAttribute.Key == model.PolicyAttributes_KEY_CUSTOM_URL && util.NsxVersionHigherOrEqual("4.0.0") { elem["custom_url_partial_match"] = policyAttribute.CustomUrlPartialMatch } attributes[key] = append(attributes[key], elem) diff --git a/nsxt/resource_nsxt_policy_gateway_dns_forwarder.go b/nsxt/resource_nsxt_policy_gateway_dns_forwarder.go index 1e641c11f..3186a6097 100644 --- a/nsxt/resource_nsxt_policy_gateway_dns_forwarder.go +++ b/nsxt/resource_nsxt_policy_gateway_dns_forwarder.go @@ -7,14 +7,15 @@ import ( "fmt" "log" + tier0s "github.com/vmware/terraform-provider-nsxt/api/infra/tier_0s" + tier1s "github.com/vmware/terraform-provider-nsxt/api/infra/tier_1s" + utl "github.com/vmware/terraform-provider-nsxt/api/utl" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client" "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model" - - tier0s "github.com/vmware/terraform-provider-nsxt/api/infra/tier_0s" - tier1s "github.com/vmware/terraform-provider-nsxt/api/infra/tier_1s" - utl "github.com/vmware/terraform-provider-nsxt/api/utl" ) var gatewayDNSForwarderLogLevelTypeValues = []string{ @@ -149,7 +150,7 @@ func patchNsxtPolicyGatewayDNSForwarder(sessionContext utl.SessionContext, conne obj.ConditionalForwarderZonePaths = conditionalZonePaths } - if nsxVersionHigherOrEqual("3.2.0") { + if util.NsxVersionHigherOrEqual("3.2.0") { obj.CacheSize = &cacheSize } diff --git a/nsxt/resource_nsxt_policy_gateway_redistribution_config.go b/nsxt/resource_nsxt_policy_gateway_redistribution_config.go index 2e459b7f0..9e79044da 100644 --- a/nsxt/resource_nsxt_policy_gateway_redistribution_config.go +++ b/nsxt/resource_nsxt_policy_gateway_redistribution_config.go @@ -7,10 +7,11 @@ import ( "fmt" "strings" + tier0s "github.com/vmware/terraform-provider-nsxt/api/infra/tier_0s" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model" - - tier0s "github.com/vmware/terraform-provider-nsxt/api/infra/tier_0s" ) func resourceNsxtPolicyGatewayRedistributionConfig() *schema.Resource { @@ -71,7 +72,7 @@ func policyGatewayRedistributionConfigPatch(d *schema.ResourceData, m interface{ BgpEnabled: &bgpEnabled, } - if nsxVersionHigherOrEqual("3.1.0") { + if util.NsxVersionHigherOrEqual("3.1.0") { redistributionStruct.OspfEnabled = &ospfEnabled } diff --git a/nsxt/resource_nsxt_policy_group.go b/nsxt/resource_nsxt_policy_group.go index 53c88d9e3..73b48b399 100644 --- a/nsxt/resource_nsxt_policy_group.go +++ b/nsxt/resource_nsxt_policy_group.go @@ -8,15 +8,16 @@ import ( "log" "strings" + "github.com/vmware/terraform-provider-nsxt/api/infra/domains" + utl "github.com/vmware/terraform-provider-nsxt/api/utl" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/vmware/vsphere-automation-sdk-go/runtime/bindings" "github.com/vmware/vsphere-automation-sdk-go/runtime/data" "github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client" "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model" - - "github.com/vmware/terraform-provider-nsxt/api/infra/domains" - utl "github.com/vmware/terraform-provider-nsxt/api/utl" ) var conditionKeyValues = []string{ @@ -874,7 +875,7 @@ func resourceNsxtPolicyGroupCreate(d *schema.ResourceData, m interface{}) error ExtendedExpression: extendedExpressionList, } - if groupType != "" && nsxVersionHigherOrEqual("3.2.0") { + if groupType != "" && util.NsxVersionHigherOrEqual("3.2.0") { obj.GroupType = groupTypes } @@ -913,7 +914,7 @@ func resourceNsxtPolicyGroupRead(d *schema.ResourceData, m interface{}) error { d.Set("domain", getDomainFromResourcePath(*obj.Path)) d.Set("revision", obj.Revision) groupType := "" - if len(obj.GroupType) > 0 && nsxVersionHigherOrEqual("3.2.0") { + if len(obj.GroupType) > 0 && util.NsxVersionHigherOrEqual("3.2.0") { groupType = obj.GroupType[0] d.Set("group_type", groupType) } @@ -987,7 +988,7 @@ func resourceNsxtPolicyGroupUpdate(d *schema.ResourceData, m interface{}) error ExtendedExpression: extendedExpressionList, } - if groupType != "" && nsxVersionHigherOrEqual("3.2.0") { + if groupType != "" && util.NsxVersionHigherOrEqual("3.2.0") { obj.GroupType = groupTypes } diff --git a/nsxt/resource_nsxt_policy_ip_block.go b/nsxt/resource_nsxt_policy_ip_block.go index d477992cb..87d3f0596 100644 --- a/nsxt/resource_nsxt_policy_ip_block.go +++ b/nsxt/resource_nsxt_policy_ip_block.go @@ -7,13 +7,14 @@ import ( "fmt" "log" + "github.com/vmware/terraform-provider-nsxt/api/infra" + utl "github.com/vmware/terraform-provider-nsxt/api/utl" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client" "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model" - - "github.com/vmware/terraform-provider-nsxt/api/infra" - utl "github.com/vmware/terraform-provider-nsxt/api/utl" ) var visibilityTypes = []string{ @@ -117,7 +118,7 @@ func resourceNsxtPolicyIPBlockCreate(d *schema.ResourceData, m interface{}) erro Cidr: &cidr, Tags: tags, } - if nsxVersionHigherOrEqual("4.2.0") && len(visibility) > 0 { + if util.NsxVersionHigherOrEqual("4.2.0") && len(visibility) > 0 { obj.Visibility = &visibility } // Create the resource using PATCH @@ -157,7 +158,7 @@ func resourceNsxtPolicyIPBlockUpdate(d *schema.ResourceData, m interface{}) erro Tags: tags, Revision: &revision, } - if nsxVersionHigherOrEqual("4.2.0") && len(visibility) > 0 { + if util.NsxVersionHigherOrEqual("4.2.0") && len(visibility) > 0 { obj.Visibility = &visibility } diff --git a/nsxt/resource_nsxt_policy_ipsec_vpn_session.go b/nsxt/resource_nsxt_policy_ipsec_vpn_session.go index ce734b8fe..c636bcc98 100644 --- a/nsxt/resource_nsxt_policy_ipsec_vpn_session.go +++ b/nsxt/resource_nsxt_policy_ipsec_vpn_session.go @@ -8,12 +8,13 @@ import ( "log" "strings" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/vmware/vsphere-automation-sdk-go/runtime/bindings" "github.com/vmware/vsphere-automation-sdk-go/runtime/data" "github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client" - t0_ipsec_services "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/infra/tier_0s/ipsec_vpn_services" t0_ipsec_nested_services "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/infra/tier_0s/locale_services/ipsec_vpn_services" t1_ipsec_services "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/infra/tier_1s/ipsec_vpn_services" @@ -223,7 +224,7 @@ func getIPSecVPNSessionFromSchema(d *schema.ResourceData) (*data.StructValue, er Psk: &psk, Tags: tags, } - if nsxVersionHigherOrEqual("3.2.0") { + if util.NsxVersionHigherOrEqual("3.2.0") { if direction != "" { tcpMSSClamping := model.TcpMaximumSegmentSizeClamping{ Direction: &direction, @@ -271,7 +272,7 @@ func getIPSecVPNSessionFromSchema(d *schema.ResourceData) (*data.StructValue, er Psk: &psk, Tags: tags, } - if nsxVersionHigherOrEqual("3.2.0") { + if util.NsxVersionHigherOrEqual("3.2.0") { if direction != "" { tcpMSSClamping := model.TcpMaximumSegmentSizeClamping{ Direction: &direction, @@ -627,7 +628,7 @@ func resourceNsxtPolicyIPSecVpnSessionRead(d *schema.ResourceData, m interface{} d.Set("tunnel_profile_path", blockVPN.TunnelProfilePath) d.Set("peer_address", blockVPN.PeerAddress) d.Set("peer_id", blockVPN.PeerId) - if nsxVersionHigherOrEqual("3.2.0") { + if util.NsxVersionHigherOrEqual("3.2.0") { if blockVPN.TcpMssClamping != nil { direction := blockVPN.TcpMssClamping.Direction mss := blockVPN.TcpMssClamping.MaxSegmentSize @@ -684,7 +685,7 @@ func resourceNsxtPolicyIPSecVpnSessionRead(d *schema.ResourceData, m interface{} if blockVPN.Rules != nil { setRuleInSchema(d, blockVPN.Rules) } - if nsxVersionHigherOrEqual("3.2.0") { + if util.NsxVersionHigherOrEqual("3.2.0") { if blockVPN.TcpMssClamping != nil { direction := blockVPN.TcpMssClamping.Direction mss := blockVPN.TcpMssClamping.MaxSegmentSize diff --git a/nsxt/resource_nsxt_policy_l2_vpn_session.go b/nsxt/resource_nsxt_policy_l2_vpn_session.go index 999619e6e..8007d9ff1 100644 --- a/nsxt/resource_nsxt_policy_l2_vpn_session.go +++ b/nsxt/resource_nsxt_policy_l2_vpn_session.go @@ -7,6 +7,8 @@ import ( "fmt" "strings" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client" @@ -125,7 +127,7 @@ func resourceNsxtPolicyL2VPNSessionCreate(d *schema.ResourceData, m interface{}) TransportTunnels: transportTunnel, } - if nsxVersionHigherOrEqual("3.2.0") { + if util.NsxVersionHigherOrEqual("3.2.0") { direction := d.Get("direction").(string) maxSegmentSize := int64(d.Get("max_segment_size").(int)) if direction != "" { @@ -244,7 +246,7 @@ func resourceNsxtPolicyL2VPNSessionRead(d *schema.ResourceData, m interface{}) e if len(obj.TransportTunnels) > 0 { d.Set("transport_tunnels", obj.TransportTunnels) } - if nsxVersionHigherOrEqual("3.2.0") { + if util.NsxVersionHigherOrEqual("3.2.0") { if obj.TcpMssClamping != nil { direction := obj.TcpMssClamping.Direction mss := obj.TcpMssClamping.MaxSegmentSize @@ -324,7 +326,7 @@ func resourceNsxtPolicyL2VPNSessionUpdate(d *schema.ResourceData, m interface{}) Revision: &revision, Enabled: &enabled, } - if nsxVersionHigherOrEqual("3.2.0") { + if util.NsxVersionHigherOrEqual("3.2.0") { direction := d.Get("direction").(string) maxSegmentSize := int64(d.Get("max_segment_size").(int)) if direction != "" { diff --git a/nsxt/resource_nsxt_policy_lb_service.go b/nsxt/resource_nsxt_policy_lb_service.go index 2b2c46be5..dfc4bd6ff 100644 --- a/nsxt/resource_nsxt_policy_lb_service.go +++ b/nsxt/resource_nsxt_policy_lb_service.go @@ -7,6 +7,8 @@ import ( "fmt" "log" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client" @@ -110,7 +112,7 @@ func resourceNsxtPolicyLBServiceCreate(d *schema.ResourceData, m interface{}) er enabled := d.Get("enabled").(bool) errorLogLevel := d.Get("error_log_level").(string) size := d.Get("size").(string) - if size == "XLARGE" && nsxVersionLower("3.0.0") { + if size == "XLARGE" && util.NsxVersionLower("3.0.0") { return fmt.Errorf("XLARGE size is not supported before NSX version 3.0.0") } @@ -191,7 +193,7 @@ func resourceNsxtPolicyLBServiceUpdate(d *schema.ResourceData, m interface{}) er enabled := d.Get("enabled").(bool) errorLogLevel := d.Get("error_log_level").(string) size := d.Get("size").(string) - if size == "XLARGE" && nsxVersionLower("3.0.0") { + if size == "XLARGE" && util.NsxVersionLower("3.0.0") { return fmt.Errorf("XLARGE size is not supported before NSX version 3.0.0") } diff --git a/nsxt/resource_nsxt_policy_lb_virtual_server.go b/nsxt/resource_nsxt_policy_lb_virtual_server.go index 7293f7531..e56320330 100644 --- a/nsxt/resource_nsxt_policy_lb_virtual_server.go +++ b/nsxt/resource_nsxt_policy_lb_virtual_server.go @@ -7,6 +7,8 @@ import ( "fmt" "log" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/vmware/vsphere-automation-sdk-go/runtime/bindings" @@ -1561,7 +1563,7 @@ func getPolicyLbRulesFromSchema(d *schema.ResourceData) []model.LBRule { } func policyLBVirtualServerVersionDependantSet(d *schema.ResourceData, obj *model.LBVirtualServer) { - if nsxVersionHigherOrEqual("3.0.0") { + if util.NsxVersionHigherOrEqual("3.0.0") { logSignificantOnly := d.Get("log_significant_event_only").(bool) obj.LogSignificantEventOnly = &logSignificantOnly obj.AccessListControl = getPolicyAccessListControlFromSchema(d) diff --git a/nsxt/resource_nsxt_policy_mac_discovery_profile.go b/nsxt/resource_nsxt_policy_mac_discovery_profile.go index e53287194..f570cea14 100644 --- a/nsxt/resource_nsxt_policy_mac_discovery_profile.go +++ b/nsxt/resource_nsxt_policy_mac_discovery_profile.go @@ -15,6 +15,7 @@ import ( "github.com/vmware/terraform-provider-nsxt/api/infra" utl "github.com/vmware/terraform-provider-nsxt/api/utl" + "github.com/vmware/terraform-provider-nsxt/nsxt/metadata" ) var macDiscoveryProfileMacLimitPolicyValues = []string{ @@ -22,170 +23,103 @@ var macDiscoveryProfileMacLimitPolicyValues = []string{ model.MacDiscoveryProfile_MAC_LIMIT_POLICY_DROP, } -type testdata struct { - createValue interface{} - updateValue interface{} -} - -type metadata struct { - // we need a separate schema type, in addition to terraform SDK type, - // in order to distinguish between single subclause and a list of entries - schemaType string - readOnly bool - sdkFieldName string - // This attribute is parent path for the object - isParentPath bool - introducedInVersion string - // skip handling of this attribute - it will be done manually - skip bool - reflectType reflect.Type - testData testdata -} - -type extendedSchema struct { - s schema.Schema - m metadata -} - -type extendedResource struct { - Schema map[string]*extendedSchema -} - -// a helper to convert terraform sdk schema to extended schema -func getExtendedSchema(sch *schema.Schema) *extendedSchema { - shallowCopy := *sch - return &extendedSchema{ - s: shallowCopy, - m: metadata{ - skip: true, - }, - } -} - -// get terraform sdk schema from extended schema definition -func getSchemaFromExtendedSchema(ext map[string]*extendedSchema) map[string]*schema.Schema { - result := make(map[string]*schema.Schema) - - for key, value := range ext { - log.Printf("[INFO] inspecting schema key %s, value %v", key, value) - shallowCopy := value.s - if (value.s.Type == schema.TypeList) || (value.s.Type == schema.TypeSet) { - elem, ok := shallowCopy.Elem.(*extendedSchema) - if ok { - shallowCopy.Elem = elem.s - } else { - elem, ok := shallowCopy.Elem.(*extendedResource) - if ok { - shallowCopy.Elem = &schema.Resource{ - Schema: getSchemaFromExtendedSchema(elem.Schema), - } - } - } - } - // TODO: deepcopy needed? - result[key] = &shallowCopy - } - - return result -} - -var macDiscoveryProfileSchema = map[string]*extendedSchema{ - "nsx_id": getExtendedSchema(getNsxIDSchema()), - "path": getExtendedSchema(getPathSchema()), - "display_name": getExtendedSchema(getDisplayNameSchema()), - "description": getExtendedSchema(getDescriptionSchema()), - "revision": getExtendedSchema(getRevisionSchema()), - "tag": getExtendedSchema(getTagsSchema()), - "context": getExtendedSchema(getContextSchema(false, false)), +var macDiscoveryProfileSchema = map[string]*metadata.ExtendedSchema{ + "nsx_id": metadata.GetExtendedSchema(getNsxIDSchema()), + "path": metadata.GetExtendedSchema(getPathSchema()), + "display_name": metadata.GetExtendedSchema(getDisplayNameSchema()), + "description": metadata.GetExtendedSchema(getDescriptionSchema()), + "revision": metadata.GetExtendedSchema(getRevisionSchema()), + "tag": metadata.GetExtendedSchema(getTagsSchema()), + "context": metadata.GetExtendedSchema(getContextSchema(false, false)), "mac_change_enabled": { - s: schema.Schema{ + Schema: schema.Schema{ Type: schema.TypeBool, Optional: true, Default: false, }, - m: metadata{ - schemaType: "bool", - sdkFieldName: "MacChangeEnabled", - testData: testdata{ - createValue: "true", - updateValue: "false", + Metadata: metadata.Metadata{ + SchemaType: "bool", + SdkFieldName: "MacChangeEnabled", + TestData: metadata.Testdata{ + CreateValue: "true", + UpdateValue: "false", }, }, }, "mac_learning_enabled": { - s: schema.Schema{ + Schema: schema.Schema{ Type: schema.TypeBool, Optional: true, }, - m: metadata{ - schemaType: "bool", - sdkFieldName: "MacLearningEnabled", - testData: testdata{ - createValue: "true", - updateValue: "false", + Metadata: metadata.Metadata{ + SchemaType: "bool", + SdkFieldName: "MacLearningEnabled", + TestData: metadata.Testdata{ + CreateValue: "true", + UpdateValue: "false", }, }, }, "mac_limit": { - s: schema.Schema{ + Schema: schema.Schema{ Type: schema.TypeInt, Optional: true, ValidateFunc: validation.IntBetween(0, 4096), Default: 4096, }, - m: metadata{ - schemaType: "int", - sdkFieldName: "MacLimit", - testData: testdata{ - createValue: "20", - updateValue: "50", + Metadata: metadata.Metadata{ + SchemaType: "int", + SdkFieldName: "MacLimit", + TestData: metadata.Testdata{ + CreateValue: "20", + UpdateValue: "50", }, }, }, "mac_limit_policy": { - s: schema.Schema{ + Schema: schema.Schema{ Type: schema.TypeString, ValidateFunc: validation.StringInSlice(macDiscoveryProfileMacLimitPolicyValues, false), Optional: true, Default: "ALLOW", }, - m: metadata{ - schemaType: "string", - sdkFieldName: "MacLimitPolicy", - testData: testdata{ - createValue: "ALLOW", - updateValue: "DROP", + Metadata: metadata.Metadata{ + SchemaType: "string", + SdkFieldName: "MacLimitPolicy", + TestData: metadata.Testdata{ + CreateValue: "ALLOW", + UpdateValue: "DROP", }, }, }, "remote_overlay_mac_limit": { - s: schema.Schema{ + Schema: schema.Schema{ Type: schema.TypeInt, Optional: true, ValidateFunc: validation.IntBetween(2048, 8192), Default: 2048, }, - m: metadata{ - schemaType: "int", - sdkFieldName: "RemoteOverlayMacLimit", - testData: testdata{ - createValue: "2048", - updateValue: "4096", + Metadata: metadata.Metadata{ + SchemaType: "int", + SdkFieldName: "RemoteOverlayMacLimit", + TestData: metadata.Testdata{ + CreateValue: "2048", + UpdateValue: "4096", }, }, }, "unknown_unicast_flooding_enabled": { - s: schema.Schema{ + Schema: schema.Schema{ Type: schema.TypeBool, Optional: true, }, - m: metadata{ - schemaType: "bool", - sdkFieldName: "UnknownUnicastFloodingEnabled", - introducedInVersion: "4.0.0", - testData: testdata{ - createValue: "true", - updateValue: "false", + Metadata: metadata.Metadata{ + SchemaType: "bool", + SdkFieldName: "UnknownUnicastFloodingEnabled", + IntroducedInVersion: "4.0.0", + TestData: metadata.Testdata{ + CreateValue: "true", + UpdateValue: "false", }, }, }, @@ -200,7 +134,8 @@ func resourceNsxtPolicyMacDiscoveryProfile() *schema.Resource { Importer: &schema.ResourceImporter{ State: nsxtPolicyPathResourceImporter, }, - Schema: getSchemaFromExtendedSchema(macDiscoveryProfileSchema), + + Schema: metadata.GetSchemaFromExtendedSchema(macDiscoveryProfileSchema), } } @@ -219,112 +154,6 @@ func resourceNsxtPolicyMacDiscoveryProfileExists(sessionContext utl.SessionConte return false, logAPIError("Error retrieving resource", err) } -// convert NSX model struct to terraform schema -// currently supports nested subtype and trivial types -// TODO - support a list of structs -func structToSchema(elem reflect.Value, d *schema.ResourceData, metadata map[string]*extendedSchema, parent string, parentMap map[string]interface{}) { - for key, item := range metadata { - if item.m.skip { - continue - } - - log.Printf("[INFO] inspecting key %s", key) - if len(parent) > 0 { - log.Printf("[INFO] parent %s key %s", parent, key) - } - if item.m.schemaType == "struct" { - nestedObj := elem.FieldByName(item.m.sdkFieldName) - nestedSchema := make(map[string]interface{}) - childElem := item.s.Elem.(*extendedResource) - structToSchema(nestedObj.Elem(), d, childElem.Schema, key, nestedSchema) - log.Printf("[INFO] assigning struct %v to %s", nestedObj, key) - // TODO - get the schema from nested type if parent in present - var nestedSlice []map[string]interface{} - nestedSlice = append(nestedSlice, nestedSchema) - if len(parent) > 0 { - parentMap[key] = nestedSlice - } else { - d.Set(key, nestedSlice) - } - } else { - if len(parent) > 0 { - log.Printf("[INFO] assigning nested value %v to %s", elem.FieldByName(item.m.sdkFieldName).Interface(), key) - parentMap[key] = elem.FieldByName(item.m.sdkFieldName).Interface() - } else { - log.Printf("[INFO] assigning value %v to %s", elem.FieldByName(item.m.sdkFieldName).Interface(), key) - d.Set(key, elem.FieldByName(item.m.sdkFieldName).Interface()) - } - } - } -} - -// convert terraform schema to NSX model struct -// currently supports nested subtype and trivial types -// TODO - support a list of structs -func schemaToStruct(elem reflect.Value, d *schema.ResourceData, metadata map[string]*extendedSchema, parent string, parentMap map[string]interface{}) { - for key, item := range metadata { - if item.m.readOnly || item.m.skip { - continue - } - if item.m.introducedInVersion != "" && nsxVersionLower(item.m.introducedInVersion) { - continue - } - - log.Printf("[INFO] inspecting key %s", key) - if len(parent) > 0 { - log.Printf("[INFO] parent %s key %s", parent, key) - } - if item.m.schemaType == "string" { - var value string - if len(parent) > 0 { - value = parentMap[key].(string) - } else { - value = d.Get(key).(string) - } - log.Printf("[INFO] assigning string %v to %s", value, key) - elem.FieldByName(item.m.sdkFieldName).Set(reflect.ValueOf(&value)) - } - if item.m.schemaType == "bool" { - var value bool - if len(parent) > 0 { - value = parentMap[key].(bool) - } else { - value = d.Get(key).(bool) - } - log.Printf("[INFO] assigning bool %v to %s", value, key) - elem.FieldByName(item.m.sdkFieldName).Set(reflect.ValueOf(&value)) - } - if item.m.schemaType == "int" { - var value int64 - if len(parent) > 0 { - value = int64(parentMap[key].(int)) - } else { - value = int64(d.Get(key).(int)) - } - log.Printf("[INFO] assigning int %v to %s", value, key) - elem.FieldByName(item.m.sdkFieldName).Set(reflect.ValueOf(&value)) - } - if item.m.schemaType == "struct" { - nestedObj := reflect.New(item.m.reflectType) - /* - // Helper for list of structs - slice := reflect.MakeSlice(reflect.TypeOf(nestedObj), 1, 1) - */ - nestedSchemaList := d.Get(key).([]interface{}) - if len(nestedSchemaList) == 0 { - continue - } - nestedSchema := nestedSchemaList[0].(map[string]interface{}) - - childElem := item.s.Elem.(*extendedResource) - schemaToStruct(nestedObj.Elem(), d, childElem.Schema, key, nestedSchema) - log.Printf("[INFO] assigning struct %v to %s", nestedObj, key) - elem.FieldByName(item.m.sdkFieldName).Set(nestedObj) - // TODO - get the schema from nested type if parent in present - } - } -} - func resourceNsxtPolicyMacDiscoveryProfileCreate(d *schema.ResourceData, m interface{}) error { connector := getPolicyConnector(m) @@ -346,7 +175,7 @@ func resourceNsxtPolicyMacDiscoveryProfileCreate(d *schema.ResourceData, m inter } elem := reflect.ValueOf(&obj).Elem() - schemaToStruct(elem, d, macDiscoveryProfileSchema, "", nil) + metadata.SchemaToStruct(elem, d, macDiscoveryProfileSchema, "", nil) // Create the resource using PATCH log.Printf("[INFO] Creating MacDiscoveryProfile with ID %s", id) @@ -385,7 +214,7 @@ func resourceNsxtPolicyMacDiscoveryProfileRead(d *schema.ResourceData, m interfa d.Set("path", obj.Path) elem := reflect.ValueOf(&obj).Elem() - structToSchema(elem, d, macDiscoveryProfileSchema, "", nil) + metadata.StructToSchema(elem, d, macDiscoveryProfileSchema, "", nil) return nil } @@ -413,7 +242,7 @@ func resourceNsxtPolicyMacDiscoveryProfileUpdate(d *schema.ResourceData, m inter } elem := reflect.ValueOf(&obj).Elem() - schemaToStruct(elem, d, macDiscoveryProfileSchema, "", nil) + metadata.SchemaToStruct(elem, d, macDiscoveryProfileSchema, "", nil) // Update the resource using PATCH boolFalse := false diff --git a/nsxt/resource_nsxt_policy_mac_discovery_profile_test.go b/nsxt/resource_nsxt_policy_mac_discovery_profile_test.go index 53dc6fb79..2c38234c6 100644 --- a/nsxt/resource_nsxt_policy_mac_discovery_profile_test.go +++ b/nsxt/resource_nsxt_policy_mac_discovery_profile_test.go @@ -8,6 +8,8 @@ import ( "log" "testing" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" @@ -44,16 +46,16 @@ func getMacDiscoveryProfileTestCheckFunc(testResourceName string, create bool) [ resource.TestCheckResourceAttr(testResourceName, "tag.#", "1"), } for key, item := range macDiscoveryProfileSchema { - if item.m.skip { + if item.Metadata.Skip { continue } - if item.m.introducedInVersion != "" && nsxVersionLower(item.m.introducedInVersion) { + if item.Metadata.IntroducedInVersion != "" && util.NsxVersionLower(item.Metadata.IntroducedInVersion) { continue } - value := item.m.testData.createValue + value := item.Metadata.TestData.CreateValue if !create { - value = item.m.testData.updateValue + value = item.Metadata.TestData.UpdateValue } result = append(result, resource.TestCheckResourceAttr(testResourceName, key, value.(string))) } @@ -65,17 +67,17 @@ func getMacDiscoveryProfileTestConfigAttributes(create bool) string { result := "" schemaDef := resourceNsxtPolicyMacDiscoveryProfile().Schema for key, item := range macDiscoveryProfileSchema { - if item.m.skip { + if item.Metadata.Skip { continue } log.Printf("[INFO] inspecting schema test key %s", key) - if item.m.introducedInVersion != "" && nsxVersionLower(item.m.introducedInVersion) { + if item.Metadata.IntroducedInVersion != "" && util.NsxVersionLower(item.Metadata.IntroducedInVersion) { continue } - value := item.m.testData.createValue + value := item.Metadata.TestData.CreateValue if !create { - value = item.m.testData.updateValue + value = item.Metadata.TestData.UpdateValue } if schemaDef[key].Type == schema.TypeString { diff --git a/nsxt/resource_nsxt_policy_nat_rule.go b/nsxt/resource_nsxt_policy_nat_rule.go index 24d0e56b6..fc4cc32ba 100644 --- a/nsxt/resource_nsxt_policy_nat_rule.go +++ b/nsxt/resource_nsxt_policy_nat_rule.go @@ -9,15 +9,16 @@ import ( "log" "strings" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" - "github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client" - "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model" - "github.com/vmware/terraform-provider-nsxt/api/infra" t0nat "github.com/vmware/terraform-provider-nsxt/api/infra/tier_0s/nat" t1nat "github.com/vmware/terraform-provider-nsxt/api/infra/tier_1s/nat" utl "github.com/vmware/terraform-provider-nsxt/api/utl" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client" + "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model" ) var policyNATRuleActionTypeValues = []string{ @@ -197,7 +198,7 @@ func patchNsxtPolicyNATRule(sessionContext utl.SessionContext, connector client. if err != nil { return err } - if nsxVersionHigherOrEqual("4.0.0") { + if util.NsxVersionHigherOrEqual("4.0.0") { _, err = getPolicyBasedVpnMode(rule) if err != nil { return err @@ -295,7 +296,7 @@ func resourceNsxtPolicyNATRuleRead(d *schema.ResourceData, m interface{}) error } d.Set("translated_ports", obj.TranslatedPorts) d.Set("scope", obj.Scope) - if nsxVersionHigherOrEqual("4.0.0") { + if util.NsxVersionHigherOrEqual("4.0.0") { d.Set("policy_based_vpn_mode", obj.PolicyBasedVpnMode) } d.SetId(id) @@ -369,7 +370,7 @@ func resourceNsxtPolicyNATRuleCreate(d *schema.ResourceData, m interface{}) erro if ports != "" { ruleStruct.TranslatedPorts = &ports } - if pbvmMatch != "" && nsxVersionHigherOrEqual("4.0.0") { + if pbvmMatch != "" && util.NsxVersionHigherOrEqual("4.0.0") { ruleStruct.PolicyBasedVpnMode = &pbvmMatch } @@ -443,7 +444,7 @@ func resourceNsxtPolicyNATRuleUpdate(d *schema.ResourceData, m interface{}) erro ruleStruct.TranslatedPorts = &tPorts } pbvmMatch := d.Get("policy_based_vpn_mode").(string) - if pbvmMatch != "" && nsxVersionHigherOrEqual("4.0.0") { + if pbvmMatch != "" && util.NsxVersionHigherOrEqual("4.0.0") { ruleStruct.PolicyBasedVpnMode = &pbvmMatch } diff --git a/nsxt/resource_nsxt_policy_project_test.go b/nsxt/resource_nsxt_policy_project_test.go index 469d031c3..f410d22a7 100644 --- a/nsxt/resource_nsxt_policy_project_test.go +++ b/nsxt/resource_nsxt_policy_project_test.go @@ -7,6 +7,8 @@ import ( "fmt" "testing" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" ) @@ -26,7 +28,7 @@ var accTestPolicyProjectUpdateAttributes = map[string]string{ } func getExpectedSiteInfoCount(t *testing.T) string { - if nsxVersion == "" { + if util.NsxVersion == "" { connector, err := testAccGetPolicyConnector() if err != nil { t.Errorf("Failed to get policy connector") @@ -39,7 +41,7 @@ func getExpectedSiteInfoCount(t *testing.T) string { return "0" } } - if nsxVersionHigherOrEqual("4.1.1") { + if util.NsxVersionHigherOrEqual("4.1.1") { return "1" } return "0" diff --git a/nsxt/resource_nsxt_policy_segment_security_profile.go b/nsxt/resource_nsxt_policy_segment_security_profile.go index 5e72beab6..564a8a34f 100644 --- a/nsxt/resource_nsxt_policy_segment_security_profile.go +++ b/nsxt/resource_nsxt_policy_segment_security_profile.go @@ -8,25 +8,26 @@ import ( "log" "reflect" + "github.com/vmware/terraform-provider-nsxt/api/infra" + utl "github.com/vmware/terraform-provider-nsxt/api/utl" + "github.com/vmware/terraform-provider-nsxt/nsxt/metadata" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client" "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model" - - "github.com/vmware/terraform-provider-nsxt/api/infra" - utl "github.com/vmware/terraform-provider-nsxt/api/utl" ) -var segmentSecurityProfileSchema = map[string]*extendedSchema{ - "nsx_id": getExtendedSchema(getNsxIDSchema()), - "path": getExtendedSchema(getPathSchema()), - "display_name": getExtendedSchema(getDisplayNameSchema()), - "description": getExtendedSchema(getDescriptionSchema()), - "revision": getExtendedSchema(getRevisionSchema()), - "tag": getExtendedSchema(getTagsSchema()), - "context": getExtendedSchema(getContextSchema(false, false)), +var segmentSecurityProfileSchema = map[string]*metadata.ExtendedSchema{ + "nsx_id": metadata.GetExtendedSchema(getNsxIDSchema()), + "path": metadata.GetExtendedSchema(getPathSchema()), + "display_name": metadata.GetExtendedSchema(getDisplayNameSchema()), + "description": metadata.GetExtendedSchema(getDescriptionSchema()), + "revision": metadata.GetExtendedSchema(getRevisionSchema()), + "tag": metadata.GetExtendedSchema(getTagsSchema()), + "context": metadata.GetExtendedSchema(getContextSchema(false, false)), "bpdu_filter_allow": { - s: schema.Schema{ + Schema: schema.Schema{ Type: schema.TypeSet, Elem: &schema.Schema{ Type: schema.TypeString, @@ -34,192 +35,192 @@ var segmentSecurityProfileSchema = map[string]*extendedSchema{ }, Optional: true, }, - m: metadata{ - skip: true, + Metadata: metadata.Metadata{ + Skip: true, }, }, "bpdu_filter_enable": { - s: schema.Schema{ + Schema: schema.Schema{ Type: schema.TypeBool, Optional: true, Default: true, }, - m: metadata{ - schemaType: "bool", - sdkFieldName: "BpduFilterEnable", - testData: testdata{ - createValue: "true", - updateValue: "false", + Metadata: metadata.Metadata{ + SchemaType: "bool", + SdkFieldName: "BpduFilterEnable", + TestData: metadata.Testdata{ + CreateValue: "true", + UpdateValue: "false", }, }, }, "dhcp_client_block_enabled": { - s: schema.Schema{ + Schema: schema.Schema{ Type: schema.TypeBool, Optional: true, Default: false, }, - m: metadata{ - schemaType: "bool", - sdkFieldName: "DhcpClientBlockEnabled", - testData: testdata{ - createValue: "true", - updateValue: "false", + Metadata: metadata.Metadata{ + SchemaType: "bool", + SdkFieldName: "DhcpClientBlockEnabled", + TestData: metadata.Testdata{ + CreateValue: "true", + UpdateValue: "false", }, }, }, "dhcp_server_block_enabled": { - s: schema.Schema{ + Schema: schema.Schema{ Type: schema.TypeBool, Optional: true, Default: true, }, - m: metadata{ - schemaType: "bool", - sdkFieldName: "DhcpServerBlockEnabled", - testData: testdata{ - createValue: "true", - updateValue: "false", + Metadata: metadata.Metadata{ + SchemaType: "bool", + SdkFieldName: "DhcpServerBlockEnabled", + TestData: metadata.Testdata{ + CreateValue: "true", + UpdateValue: "false", }, }, }, "dhcp_client_block_v6_enabled": { - s: schema.Schema{ + Schema: schema.Schema{ Type: schema.TypeBool, Optional: true, Default: false, }, - m: metadata{ - schemaType: "bool", - sdkFieldName: "DhcpClientBlockV6Enabled", - testData: testdata{ - createValue: "true", - updateValue: "false", + Metadata: metadata.Metadata{ + SchemaType: "bool", + SdkFieldName: "DhcpClientBlockV6Enabled", + TestData: metadata.Testdata{ + CreateValue: "true", + UpdateValue: "false", }, }, }, "dhcp_server_block_v6_enabled": { - s: schema.Schema{ + Schema: schema.Schema{ Type: schema.TypeBool, Optional: true, Default: true, }, - m: metadata{ - schemaType: "bool", - sdkFieldName: "DhcpServerBlockV6Enabled", - testData: testdata{ - createValue: "true", - updateValue: "false", + Metadata: metadata.Metadata{ + SchemaType: "bool", + SdkFieldName: "DhcpServerBlockV6Enabled", + TestData: metadata.Testdata{ + CreateValue: "true", + UpdateValue: "false", }, }, }, "non_ip_traffic_block_enabled": { - s: schema.Schema{ + Schema: schema.Schema{ Type: schema.TypeBool, Optional: true, Default: false, }, - m: metadata{ - schemaType: "bool", - sdkFieldName: "NonIpTrafficBlockEnabled", - testData: testdata{ - createValue: "true", - updateValue: "false", + Metadata: metadata.Metadata{ + SchemaType: "bool", + SdkFieldName: "NonIpTrafficBlockEnabled", + TestData: metadata.Testdata{ + CreateValue: "true", + UpdateValue: "false", }, }, }, "ra_guard_enabled": { - s: schema.Schema{ + Schema: schema.Schema{ Type: schema.TypeBool, Optional: true, Default: false, }, - m: metadata{ - schemaType: "bool", - sdkFieldName: "RaGuardEnabled", - testData: testdata{ - createValue: "true", - updateValue: "false", + Metadata: metadata.Metadata{ + SchemaType: "bool", + SdkFieldName: "RaGuardEnabled", + TestData: metadata.Testdata{ + CreateValue: "true", + UpdateValue: "false", }, }, }, "rate_limits_enabled": { - s: schema.Schema{ + Schema: schema.Schema{ Type: schema.TypeBool, Optional: true, Default: false, }, - m: metadata{ - schemaType: "bool", - sdkFieldName: "RateLimitsEnabled", - testData: testdata{ - createValue: "true", - updateValue: "false", + Metadata: metadata.Metadata{ + SchemaType: "bool", + SdkFieldName: "RateLimitsEnabled", + TestData: metadata.Testdata{ + CreateValue: "true", + UpdateValue: "false", }, }, }, "rate_limit": { - s: schema.Schema{ + Schema: schema.Schema{ Type: schema.TypeList, - Elem: &extendedResource{ - Schema: map[string]*extendedSchema{ + Elem: &metadata.ExtendedResource{ + Schema: map[string]*metadata.ExtendedSchema{ "rx_broadcast": { - s: schema.Schema{ + Schema: schema.Schema{ Type: schema.TypeInt, Optional: true, Default: 0, }, - m: metadata{ - schemaType: "int", - sdkFieldName: "RxBroadcast", - testData: testdata{ - createValue: "100", - updateValue: "1000", + Metadata: metadata.Metadata{ + SchemaType: "int", + SdkFieldName: "RxBroadcast", + TestData: metadata.Testdata{ + CreateValue: "100", + UpdateValue: "1000", }, }, }, "rx_multicast": { - s: schema.Schema{ + Schema: schema.Schema{ Type: schema.TypeInt, Optional: true, Default: 0, }, - m: metadata{ - schemaType: "int", - sdkFieldName: "RxMulticast", - testData: testdata{ - createValue: "100", - updateValue: "1000", + Metadata: metadata.Metadata{ + SchemaType: "int", + SdkFieldName: "RxMulticast", + TestData: metadata.Testdata{ + CreateValue: "100", + UpdateValue: "1000", }, }, }, "tx_broadcast": { - s: schema.Schema{ + Schema: schema.Schema{ Type: schema.TypeInt, Optional: true, Default: 0, }, - m: metadata{ - schemaType: "int", - sdkFieldName: "TxBroadcast", - testData: testdata{ - createValue: "100", - updateValue: "1000", + Metadata: metadata.Metadata{ + SchemaType: "int", + SdkFieldName: "TxBroadcast", + TestData: metadata.Testdata{ + CreateValue: "100", + UpdateValue: "1000", }, }, }, "tx_multicast": { - s: schema.Schema{ + Schema: schema.Schema{ Type: schema.TypeInt, Optional: true, Default: 0, }, - m: metadata{ - schemaType: "int", - sdkFieldName: "TxMulticast", - testData: testdata{ - createValue: "100", - updateValue: "1000", + Metadata: metadata.Metadata{ + SchemaType: "int", + SdkFieldName: "TxMulticast", + TestData: metadata.Testdata{ + CreateValue: "100", + UpdateValue: "1000", }, }, }, @@ -228,10 +229,10 @@ var segmentSecurityProfileSchema = map[string]*extendedSchema{ Optional: true, Computed: true, }, - m: metadata{ - schemaType: "struct", - sdkFieldName: "RateLimits", - reflectType: reflect.TypeOf(model.TrafficRateLimits{}), + Metadata: metadata.Metadata{ + SchemaType: "struct", + SdkFieldName: "RateLimits", + ReflectType: reflect.TypeOf(model.TrafficRateLimits{}), }, }, } @@ -245,7 +246,8 @@ func resourceNsxtPolicySegmentSecurityProfile() *schema.Resource { Importer: &schema.ResourceImporter{ State: nsxtPolicyPathResourceImporter, }, - Schema: getSchemaFromExtendedSchema(segmentSecurityProfileSchema), + + Schema: metadata.GetSchemaFromExtendedSchema(segmentSecurityProfileSchema), } } @@ -280,7 +282,7 @@ func resourceNsxtPolicySegmentSecurityProfilePatch(d *schema.ResourceData, m int BpduFilterAllow: bpduFilterAllow, } elem := reflect.ValueOf(&obj).Elem() - schemaToStruct(elem, d, segmentSecurityProfileSchema, "", nil) + metadata.SchemaToStruct(elem, d, segmentSecurityProfileSchema, "", nil) log.Printf("[INFO] Sending SegmentSecurityProfile with ID %s", id) client := infra.NewSegmentSecurityProfilesClient(getSessionContext(d, m), connector) @@ -321,7 +323,7 @@ func resourceNsxtPolicySegmentSecurityProfileRead(d *schema.ResourceData, m inte } elem := reflect.ValueOf(&obj).Elem() - structToSchema(elem, d, segmentSecurityProfileSchema, "", nil) + metadata.StructToSchema(elem, d, segmentSecurityProfileSchema, "", nil) d.Set("display_name", obj.DisplayName) d.Set("description", obj.Description) diff --git a/nsxt/resource_nsxt_policy_tier0_gateway.go b/nsxt/resource_nsxt_policy_tier0_gateway.go index f1fbe03c9..66eaa82e1 100644 --- a/nsxt/resource_nsxt_policy_tier0_gateway.go +++ b/nsxt/resource_nsxt_policy_tier0_gateway.go @@ -7,6 +7,9 @@ import ( "fmt" "log" + utl "github.com/vmware/terraform-provider-nsxt/api/utl" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/vmware/vsphere-automation-sdk-go/runtime/bindings" @@ -15,8 +18,6 @@ import ( gm_infra "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-gm/global_infra" gm_tier_0s "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-gm/global_infra/tier_0s" gm_model "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-gm/model" - - utl "github.com/vmware/terraform-provider-nsxt/api/utl" "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/infra" "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/infra/tier_0s" "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/infra/tier_0s/locale_services" @@ -438,7 +439,7 @@ func resourceNsxtPolicyTier0GatewayReadBGPConfig(d *schema.ResourceData, connect func getPolicyVRFConfigFromSchema(d *schema.ResourceData) *model.Tier0VrfConfig { - if nsxVersionLower("3.0.0") { + if util.NsxVersionLower("3.0.0") { // VRF Lite is supported from 3.0.0 onwards return nil } @@ -758,11 +759,11 @@ func policyTier0GatewayResourceToInfraStruct(context utl.SessionContext, d *sche VrfConfig: vrfConfig, } - if nsxVersionHigherOrEqual("3.0.0") { + if util.NsxVersionHigherOrEqual("3.0.0") { t0Struct.RdAdminField = rdAdminField } - if nsxVersionHigherOrEqual("4.1.0") { + if util.NsxVersionHigherOrEqual("4.1.0") { t0Struct.VrfTransitSubnets = vrfTransitSubnets } @@ -928,7 +929,7 @@ func resourceNsxtPolicyTier0GatewayRead(d *schema.ResourceData, m interface{}) e d.Set("transit_subnets", obj.TransitSubnets) d.Set("vrf_transit_subnets", obj.VrfTransitSubnets) d.Set("revision", obj.Revision) - if nsxVersionHigherOrEqual("3.0.0") { + if util.NsxVersionHigherOrEqual("3.0.0") { d.Set("rd_admin_address", obj.RdAdminField) } vrfErr := setPolicyVRFConfigInSchema(d, obj.VrfConfig) diff --git a/nsxt/resource_nsxt_policy_tier0_gateway_interface.go b/nsxt/resource_nsxt_policy_tier0_gateway_interface.go index 366c305f3..04db4a046 100644 --- a/nsxt/resource_nsxt_policy_tier0_gateway_interface.go +++ b/nsxt/resource_nsxt_policy_tier0_gateway_interface.go @@ -8,6 +8,8 @@ import ( "log" "strings" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" gm_infra "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-gm/global_infra" @@ -144,7 +146,7 @@ func getGatewayInterfaceOspfSchema() *schema.Schema { } func gatewayInterfaceVersionDepenantSet(d *schema.ResourceData, m interface{}, obj *model.Tier0Interface) error { - if nsxVersionLower("3.0.0") { + if util.NsxVersionLower("3.0.0") { return nil } interfaceType := d.Get("type").(string) diff --git a/nsxt/resource_nsxt_policy_tier1_gateway.go b/nsxt/resource_nsxt_policy_tier1_gateway.go index 5283a9f44..bd2437f1c 100644 --- a/nsxt/resource_nsxt_policy_tier1_gateway.go +++ b/nsxt/resource_nsxt_policy_tier1_gateway.go @@ -7,16 +7,17 @@ import ( "fmt" "log" + "github.com/vmware/terraform-provider-nsxt/api/infra" + tier1s "github.com/vmware/terraform-provider-nsxt/api/infra/tier_1s" + utl "github.com/vmware/terraform-provider-nsxt/api/utl" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/vmware/vsphere-automation-sdk-go/runtime/bindings" "github.com/vmware/vsphere-automation-sdk-go/runtime/data" "github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client" "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model" - - "github.com/vmware/terraform-provider-nsxt/api/infra" - tier1s "github.com/vmware/terraform-provider-nsxt/api/infra/tier_1s" - utl "github.com/vmware/terraform-provider-nsxt/api/utl" ) var advertismentTypeValues = []string{ @@ -318,7 +319,7 @@ func resourceNsxtPolicyTier1GatewaySetQos(d *schema.ResourceData, obj *model.Tie } func resourceNsxtPolicyTier1GatewaySetVersionDependentAttrs(d *schema.ResourceData, obj *model.Tier1) { - if nsxVersionLower("3.0.0") { + if util.NsxVersionLower("3.0.0") { return } @@ -382,7 +383,7 @@ func policyTier1GatewayResourceToInfraStruct(context utl.SessionContext, d *sche connectivityType := d.Get("type").(string) revision := int64(d.Get("revision").(int)) - if haMode == model.Tier1_HA_MODE_ACTIVE && nsxVersionLower("4.0.0") { + if haMode == model.Tier1_HA_MODE_ACTIVE && util.NsxVersionLower("4.0.0") { return infraStruct, fmt.Errorf("ACTIVE_ACTIVE HA mode is not supported in NSX versions lower than 4.0.0. Use ACTIVE_BACKUP instead") } @@ -404,7 +405,7 @@ func policyTier1GatewayResourceToInfraStruct(context utl.SessionContext, d *sche ResourceType: &t1Type, } - if nsxVersionHigherOrEqual("3.2.0") { + if util.NsxVersionHigherOrEqual("3.2.0") { if haMode != "NONE" && haMode != "" { obj.HaMode = &haMode } @@ -546,7 +547,7 @@ func resourceNsxtPolicyTier1GatewayRead(d *schema.ResourceData, m interface{}) e d.Set("enable_firewall", !(*obj.DisableFirewall)) d.Set("enable_standby_relocation", obj.EnableStandbyRelocation) d.Set("force_whitelisting", obj.ForceWhitelisting) - if nsxVersionHigherOrEqual("3.2.0") { + if util.NsxVersionHigherOrEqual("3.2.0") { if obj.HaMode == nil { d.Set("ha_mode", "NONE") } else { diff --git a/nsxt/resource_nsxt_policy_tier1_gateway_interface.go b/nsxt/resource_nsxt_policy_tier1_gateway_interface.go index 9e09af1e1..050703019 100644 --- a/nsxt/resource_nsxt_policy_tier1_gateway_interface.go +++ b/nsxt/resource_nsxt_policy_tier1_gateway_interface.go @@ -10,14 +10,15 @@ import ( "strconv" "strings" + "github.com/vmware/terraform-provider-nsxt/api/infra" + localeservices "github.com/vmware/terraform-provider-nsxt/api/infra/tier_1s/locale_services" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" gm_tier1s "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-gm/global_infra/tier_1s" gm_locale_services "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-gm/global_infra/tier_1s/locale_services" gm_model "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-gm/model" "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model" - - "github.com/vmware/terraform-provider-nsxt/api/infra" - localeservices "github.com/vmware/terraform-provider-nsxt/api/infra/tier_1s/locale_services" ) func resourceNsxtPolicyTier1GatewayInterface() *schema.Resource { @@ -153,7 +154,7 @@ func resourceNsxtPolicyTier1GatewayInterfaceCreate(d *schema.ResourceData, m int obj.Mtu = &mtu } - if nsxVersionHigherOrEqual("3.0.0") { + if util.NsxVersionHigherOrEqual("3.0.0") { urpfMode := d.Get("urpf_mode").(string) obj.UrpfMode = &urpfMode } @@ -279,7 +280,7 @@ func resourceNsxtPolicyTier1GatewayInterfaceUpdate(d *schema.ResourceData, m int obj.Mtu = &mtu } - if nsxVersionHigherOrEqual("3.0.0") { + if util.NsxVersionHigherOrEqual("3.0.0") { urpfMode := d.Get("urpf_mode").(string) obj.UrpfMode = &urpfMode } diff --git a/nsxt/resource_nsxt_policy_vm_tags.go b/nsxt/resource_nsxt_policy_vm_tags.go index 5c3761290..b0d041d85 100644 --- a/nsxt/resource_nsxt_policy_vm_tags.go +++ b/nsxt/resource_nsxt_policy_vm_tags.go @@ -9,11 +9,13 @@ import ( "strconv" "strings" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" realizedstate "github.com/vmware/terraform-provider-nsxt/api/infra/realized_state" "github.com/vmware/terraform-provider-nsxt/api/infra/segments" t1_segments "github.com/vmware/terraform-provider-nsxt/api/infra/tier_1s/segments" utl "github.com/vmware/terraform-provider-nsxt/api/utl" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/vmware/vsphere-automation-sdk-go/runtime/bindings" "github.com/vmware/vsphere-automation-sdk-go/runtime/data" "github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client" @@ -167,7 +169,7 @@ func findNsxtPolicyVMByNamePrefix(context utl.SessionContext, connector client.C var perfectMatch, prefixMatch, allVMs []model.VirtualMachine var err error - if nsxVersionHigherOrEqual("4.1.2") { + if util.NsxVersionHigherOrEqual("4.1.2") { // Search API works for inventory objects for 4.1.2 and above resourceType := "VirtualMachine" resultValues, err1 := listInventoryResourcesByNameAndType(connector, context, namePrefix, resourceType, nil) @@ -215,7 +217,7 @@ func findNsxtPolicyVMByID(context utl.SessionContext, connector client.Connector var vms []model.VirtualMachine var err error - if nsxVersionHigherOrEqual("4.1.2") { + if util.NsxVersionHigherOrEqual("4.1.2") { // Search API works for inventory objects for 4.1.2 and above resourceType := "VirtualMachine" resultValues, err1 := listInventoryResourcesByAnyFieldAndType(connector, context, vmID, resourceType, nil) @@ -252,7 +254,7 @@ func updateNsxtPolicyVMTags(connector client.Connector, externalID string, tags Tags: tags, VirtualMachineId: &externalID, } - if nsxVersionHigherOrEqual("4.1.1") { + if util.NsxVersionHigherOrEqual("4.1.1") { client := virtual_machines.NewTagsClient(connector) return client.Create(externalID, tagUpdate, nil, nil, nil, nil, nil, nil, nil) } diff --git a/nsxt/resource_nsxt_upgrade_prepare.go b/nsxt/resource_nsxt_upgrade_prepare.go index 64d7fc187..4a1bbfa4f 100644 --- a/nsxt/resource_nsxt_upgrade_prepare.go +++ b/nsxt/resource_nsxt_upgrade_prepare.go @@ -9,6 +9,8 @@ import ( "strings" "time" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/vmware/vsphere-automation-sdk-go/lib/vapi/std/errors" @@ -248,10 +250,10 @@ func uploadPrecheckAndUpgradeBundle(d *schema.ResourceData, m interface{}) error } func precheckBundleCompatibilityCheck(precheckBundleURL string) bool { - if nsxVersionLower("4.1.1") && len(precheckBundleURL) > 0 { + if util.NsxVersionLower("4.1.1") && len(precheckBundleURL) > 0 { return false } - if nsxVersionHigherOrEqual("4.1.1") && len(precheckBundleURL) == 0 { + if util.NsxVersionHigherOrEqual("4.1.1") && len(precheckBundleURL) == 0 { return false } return true @@ -299,7 +301,7 @@ func uploadUpgradeBundle(d *schema.ResourceData, m interface{}, bundleType strin bundleFetchRequest := nsxModel.UpgradeBundleFetchRequest{ Url: &url, } - if nsxVersionHigherOrEqual("4.1.1") { + if util.NsxVersionHigherOrEqual("4.1.1") { bundleFetchRequest.BundleType = &bundleType bundleFetchRequest.Password = &password bundleFetchRequest.Username = &userName diff --git a/nsxt/segment_common.go b/nsxt/segment_common.go index e54aa5898..814cbfee7 100644 --- a/nsxt/segment_common.go +++ b/nsxt/segment_common.go @@ -6,7 +6,11 @@ import ( "strings" "time" + "github.com/vmware/terraform-provider-nsxt/api/infra" + "github.com/vmware/terraform-provider-nsxt/api/infra/segments" tier1s "github.com/vmware/terraform-provider-nsxt/api/infra/tier_1s" + utl "github.com/vmware/terraform-provider-nsxt/api/utl" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -17,10 +21,6 @@ import ( gm_segments "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-gm/global_infra/segments" gm_model "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-gm/model" "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model" - - "github.com/vmware/terraform-provider-nsxt/api/infra" - "github.com/vmware/terraform-provider-nsxt/api/infra/segments" - utl "github.com/vmware/terraform-provider-nsxt/api/utl" ) var connectivityValues = []string{ @@ -491,7 +491,7 @@ func getDhcpOptsFromMap(dhcpConfig map[string]interface{}) *model.DhcpV4Options } func getSegmentSubnetDhcpConfigFromSchema(schemaConfig map[string]interface{}) (*data.StructValue, error) { - if nsxVersionLower("3.0.0") { + if util.NsxVersionLower("3.0.0") { return nil, nil } @@ -727,7 +727,7 @@ func policySegmentResourceToInfraStruct(context utl.SessionContext, id string, d if tzPath != "" { obj.TransportZonePath = &tzPath } - if nsxVersionHigherOrEqual("3.0.0") { + if util.NsxVersionHigherOrEqual("3.0.0") { obj.ReplicationMode = &replicationMode if dhcpConfigPath != "" { obj.DhcpConfigPath = &dhcpConfigPath @@ -807,7 +807,7 @@ func policySegmentResourceToInfraStruct(context utl.SessionContext, id string, d advConfigStruct.Connectivity = &connectivity } - if nsxVersionHigherOrEqual("3.0.0") { + if util.NsxVersionHigherOrEqual("3.0.0") { teamingPolicy := advConfigMap["uplink_teaming_policy"].(string) if teamingPolicy != "" { advConfigStruct.UplinkTeamingPolicyName = &teamingPolicy @@ -818,7 +818,7 @@ func policySegmentResourceToInfraStruct(context utl.SessionContext, id string, d advConfigStruct.AddressPoolPaths = append(advConfigStruct.AddressPoolPaths, poolPath) } - if nsxVersionHigherOrEqual("3.1.0") { + if util.NsxVersionHigherOrEqual("3.1.0") { urpfMode := advConfigMap["urpf_mode"].(string) advConfigStruct.UrpfMode = &urpfMode } @@ -1370,7 +1370,7 @@ func nsxtPolicySegmentRead(d *schema.ResourceData, m interface{}, isVlan bool, i } } - if nsxVersionHigherOrEqual("3.0.0") { + if util.NsxVersionHigherOrEqual("3.0.0") { d.Set("replication_mode", obj.ReplicationMode) } @@ -1389,7 +1389,7 @@ func nsxtPolicySegmentRead(d *schema.ResourceData, m interface{}, isVlan bool, i if obj.AdvancedConfig.UrpfMode != nil { advConfig["urpf_mode"] = *obj.AdvancedConfig.UrpfMode } else { - if nsxVersionLower("3.1.0") { + if util.NsxVersionLower("3.1.0") { // set to default in early versions advConfig["urpf_mode"] = model.SegmentAdvancedConfig_URPF_MODE_STRICT } diff --git a/nsxt/util/utils.go b/nsxt/util/utils.go new file mode 100644 index 000000000..1689a4ca9 --- /dev/null +++ b/nsxt/util/utils.go @@ -0,0 +1,31 @@ +package util + +import ( + "log" + + "github.com/hashicorp/go-version" +) + +var NsxVersion = "" + +func NsxVersionLower(ver string) bool { + + requestedVersion, err1 := version.NewVersion(ver) + currentVersion, err2 := version.NewVersion(NsxVersion) + if err1 != nil || err2 != nil { + log.Printf("[ERROR] Failed perform version check for version %s", ver) + return true + } + return currentVersion.LessThan(requestedVersion) +} + +func NsxVersionHigherOrEqual(ver string) bool { + + requestedVersion, err1 := version.NewVersion(ver) + currentVersion, err2 := version.NewVersion(NsxVersion) + if err1 != nil || err2 != nil { + log.Printf("[ERROR] Failed perform version check for version %s", ver) + return false + } + return currentVersion.Compare(requestedVersion) >= 0 +} diff --git a/nsxt/utils.go b/nsxt/utils.go index 59f2864a2..c797c3fb8 100644 --- a/nsxt/utils.go +++ b/nsxt/utils.go @@ -9,7 +9,8 @@ import ( "hash/crc32" "log" - "github.com/hashicorp/go-version" + "github.com/vmware/terraform-provider-nsxt/nsxt/util" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" api "github.com/vmware/go-vmware-nsxt" @@ -23,7 +24,6 @@ import ( ) var adminStateValues = []string{"UP", "DOWN"} -var nsxVersion = "" func interface2StringList(configured []interface{}) []string { vs := make([]string, 0, len(configured)) @@ -583,7 +583,7 @@ func getNSXVersion(connector client.Connector) (string, error) { func initNSXVersion(connector client.Connector) error { var err error - nsxVersion, err = getNSXVersion(connector) + util.NsxVersion, err = getNSXVersion(connector) return err } @@ -591,7 +591,7 @@ func initNSXVersionVMC(clients interface{}) { // TODO: find a ireliable way to retrieve NSX version on VMC // For now, we need to determine whether the deployment is 3.0.0 and up, or below // For this purpose, we fire indicator search API (introduced in 3.0.0) - nsxVersion = "3.0.0" + util.NsxVersion = "3.0.0" connector := getPolicyConnector(clients) client := search.NewQueryClient(connector) @@ -607,7 +607,7 @@ func initNSXVersionVMC(clients interface{}) { if isNotFoundError(err) { // search API not supported log.Printf("[INFO] Assuming NSX version < 3.0.0 in VMC environment") - nsxVersion = "2.5.0" + util.NsxVersion = "2.5.0" return } @@ -615,28 +615,6 @@ func initNSXVersionVMC(clients interface{}) { log.Printf("[ERROR] Failed to determine NSX version in VMC environment: %s", err) } -func nsxVersionLower(ver string) bool { - - requestedVersion, err1 := version.NewVersion(ver) - currentVersion, err2 := version.NewVersion(nsxVersion) - if err1 != nil || err2 != nil { - log.Printf("[ERROR] Failed perform version check for version %s", ver) - return true - } - return currentVersion.LessThan(requestedVersion) -} - -func nsxVersionHigherOrEqual(ver string) bool { - - requestedVersion, err1 := version.NewVersion(ver) - currentVersion, err2 := version.NewVersion(nsxVersion) - if err1 != nil || err2 != nil { - log.Printf("[ERROR] Failed perform version check for version %s", ver) - return false - } - return currentVersion.Compare(requestedVersion) >= 0 -} - func resourceNotSupportedError() error { return fmt.Errorf("This resource is not supported with given provider settings") }