diff --git a/nsxt/provider.go b/nsxt/provider.go index 6783bed44..983d78824 100644 --- a/nsxt/provider.go +++ b/nsxt/provider.go @@ -470,6 +470,7 @@ func Provider() *schema.Provider { "nsxt_policy_lb_tcp_monitor_profile": resourceNsxtPolicyLBTcpMonitorProfile(), "nsxt_policy_lb_udp_monitor_profile": resourceNsxtPolicyLBUdpMonitorProfile(), "nsxt_policy_tier0_gateway_gre_tunnel": resourceNsxtPolicyTier0GatewayGRETunnel(), + "nsxt_policy_site": resourceNsxtPolicySite(), }, ConfigureFunc: providerConfigure, diff --git a/nsxt/resource_nsxt_policy_site.go b/nsxt/resource_nsxt_policy_site.go new file mode 100644 index 000000000..28ad61192 --- /dev/null +++ b/nsxt/resource_nsxt_policy_site.go @@ -0,0 +1,267 @@ +package nsxt + +import ( + "fmt" + + "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-gm/global_infra" + gm_model "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-gm/model" +) + +var siteTypeValues = []string{ + "ONPREM_LM", + "SDDC_LM", +} + +func resourceNsxtPolicySite() *schema.Resource { + return &schema.Resource{ + Create: resourceNsxtPolicySiteCreate, + Read: resourceNsxtPolicySiteRead, + Update: resourceNsxtPolicySiteUpdate, + Delete: resourceNsxtPolicySiteDelete, + Importer: &schema.ResourceImporter{ + State: nsxtPolicyPathResourceImporter, + }, + + Schema: map[string]*schema.Schema{ + "nsx_id": getNsxIDSchema(), + "path": getPathSchema(), + "display_name": getDisplayNameSchema(), + "description": getDescriptionSchema(), + "revision": getRevisionSchema(), + "tag": getTagsSchema(), + "fail_if_rtep_misconfigured": { + Type: schema.TypeBool, + Optional: true, + Description: "Fail onboarding if RTEPs misconfigured", + Default: true, + }, + "fail_if_rtt_exceeded": { + Type: schema.TypeBool, + Optional: true, + Description: "Fail onboarding if maximum RTT exceeded", + Default: true, + }, + "maximum_rtt": { + Type: schema.TypeInt, + Optional: true, + Description: "Maximum acceptable packet round trip time (RTT)", + Default: 250, + ValidateFunc: validation.IntBetween(0, 1000), + }, + "site_connection_info": { + Type: schema.TypeList, + Optional: true, + Description: "Connection information", + MaxItems: 3, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "fqdn": { + Type: schema.TypeString, + Optional: true, + Description: "Fully Qualified Domain Name of the Management Node", + }, + "password": { + Type: schema.TypeString, + Optional: true, + Sensitive: true, + Description: "Password", + }, + "site_uuid": { + Type: schema.TypeString, + Optional: true, + Description: "id of Site", + }, + "thumbprint": { + Type: schema.TypeString, + Optional: true, + Description: "Thumbprint of Enforcement Point", + }, + "username": { + Type: schema.TypeString, + Optional: true, + Description: "Username", + }, + }, + }, + }, + "site_type": { + Type: schema.TypeString, + Optional: true, + Description: "Persistent Site Type", + ValidateFunc: validation.StringInSlice(siteTypeValues, false), + }, + }, + } +} + +func getSiteFromSchema(d *schema.ResourceData) gm_model.Site { + displayName := d.Get("display_name").(string) + description := d.Get("description").(string) + var tags []gm_model.Tag + tagListIntface := d.Get("tag") + if tagListIntface != nil { + tagList := tagListIntface.(*schema.Set).List() + for _, t := range tagList { + elem := t.(map[string]interface{}) + scope := elem["scope"].(string) + tag := elem["tag"].(string) + tags = append(tags, gm_model.Tag{Scope: &scope, Tag: &tag}) + } + } + failIfRtepMisconfigured := d.Get("fail_if_rtep_misconfigured").(bool) + failIfRttExceeded := d.Get("fail_if_rtt_exceeded").(bool) + maximumRtt := int64(d.Get("maximum_rtt").(int)) + + var siteConnectionInfos []gm_model.SiteNodeConnectionInfo + siteConnectionInfoList := d.Get("site_connection_info").([]interface{}) + for _, sci := range siteConnectionInfoList { + elem := sci.(map[string]interface{}) + fqdn := elem["fqdn"].(string) + password := elem["password"].(string) + siteUUID := elem["site_uuid"].(string) + thumbprint := elem["thumbprint"].(string) + username := elem["username"].(string) + + siteConnectionInfo := gm_model.SiteNodeConnectionInfo{ + Fqdn: &fqdn, + Password: &password, + SiteUuid: &siteUUID, + Thumbprint: &thumbprint, + Username: &username, + } + siteConnectionInfos = append(siteConnectionInfos, siteConnectionInfo) + } + siteType := d.Get("site_type").(string) + + return gm_model.Site{ + DisplayName: &displayName, + Description: &description, + Tags: tags, + FailIfRtepMisconfigured: &failIfRtepMisconfigured, + FailIfRttExceeded: &failIfRttExceeded, + MaximumRtt: &maximumRtt, + SiteConnectionInfo: siteConnectionInfos, + SiteType: &siteType, + } +} + +func resourceNsxtPolicySiteExists(id string, connector client.Connector, isGlobal bool) (bool, error) { + client := global_infra.NewSitesClient(connector) + _, err := client.Get(id) + if err == nil { + return true, nil + } + + if isNotFoundError(err) { + return false, nil + } + + return false, logAPIError("Error retrieving resource", err) +} + +func resourceNsxtPolicySiteCreate(d *schema.ResourceData, m interface{}) error { + id, err := getOrGenerateID(d, m, resourceNsxtPolicySiteExists) + if err != nil { + return err + } + + connector := getPolicyConnector(m) + client := global_infra.NewSitesClient(connector) + site := getSiteFromSchema(d) + + err = client.Patch(id, site) + if err != nil { + return handleCreateError("Site", id, err) + } + + d.SetId(id) + d.Set("nsx_id", id) + + return resourceNsxtPolicySiteRead(d, m) +} + +func resourceNsxtPolicySiteRead(d *schema.ResourceData, m interface{}) error { + connector := getPolicyConnector(m) + + id := d.Id() + if id == "" { + return fmt.Errorf("error obtaining Site ID") + } + client := global_infra.NewSitesClient(connector) + obj, err := client.Get(id) + if err != nil { + return handleReadError(d, "Site", id, err) + } + d.Set("display_name", obj.DisplayName) + d.Set("description", obj.Description) + var tags []interface{} + for _, tag := range obj.Tags { + elem := make(map[string]interface{}) + elem["scope"] = tag.Scope + elem["tag"] = tag.Tag + tags = append(tags, elem) + } + d.Set("nsx_id", id) + d.Set("path", obj.Path) + d.Set("revision", obj.Revision) + d.Set("realized_id", obj.RealizationId) + + d.Set("fail_if_rtep_misconfigured", obj.FailIfRtepMisconfigured) + d.Set("fail_if_rtt_exceeded", obj.FailIfRttExceeded) + d.Set("maximum_rtt", obj.MaximumRtt) + + var siteConnectionInfos []interface{} + for _, sci := range obj.SiteConnectionInfo { + elem := make(map[string]interface{}) + elem["fqdn"] = sci.Fqdn + elem["password"] = sci.Password + elem["site_uuid"] = sci.SiteUuid + elem["thumbprint"] = sci.Thumbprint + elem["username"] = sci.Username + + siteConnectionInfos = append(siteConnectionInfos, elem) + } + d.Set("site_connection_info", siteConnectionInfos) + d.Set("site_type", obj.SiteType) + + return nil +} + +func resourceNsxtPolicySiteUpdate(d *schema.ResourceData, m interface{}) error { + id := d.Id() + if id == "" { + return fmt.Errorf("Error obtaining Site ID") + } + + connector := getPolicyConnector(m) + client := global_infra.NewSitesClient(connector) + + obj := getSiteFromSchema(d) + revision := int64(d.Get("revision").(int)) + obj.Revision = &revision + + _, err := client.Update(id, obj) + if err != nil { + return handleUpdateError("Site", id, err) + } + + return nil +} + +func resourceNsxtPolicySiteDelete(d *schema.ResourceData, m interface{}) error { + id := d.Id() + if id == "" { + return fmt.Errorf("error obtaining Site ID") + } + connector := getPolicyConnector(m) + client := global_infra.NewSitesClient(connector) + err := client.Delete(id, nil) + if err != nil { + return handleDeleteError("Site", id, err) + } + + return nil +} diff --git a/website/docs/r/policy_site.html.markdown b/website/docs/r/policy_site.html.markdown new file mode 100644 index 000000000..591097d21 --- /dev/null +++ b/website/docs/r/policy_site.html.markdown @@ -0,0 +1,65 @@ +--- +subcategory: "Beta" +layout: "nsxt" +page_title: "NSXT: nsxt_policy_site" +description: A resource to configure Policy Site. +--- + +# nsxt_policy_site + +This resource provides a method for the management of Policy Site. + +This resource is applicable to NSX Global Manager. + +## Example Usage + +```hcl +resource "nsxt_policy_site" "test" { + display_name = "test" + description = "Terraform provisioned Site" + site_connection_info { + fqdn = "192.168.230.230" + username = "admin" + password = "somepasswd" + thumbprint = "207d65dcb6f17aa5a1ef2365ee6ae0b396867baa92464e5f8a46f6853708b9ef" + } + site_type = "ONPREM_LM" +} +``` +## Argument Reference + +The following arguments are supported: + +* `display_name` - (Required) Display name of the resource. +* `description` - (Optional) Description of the resource. +* `tag` - (Optional) A list of scope + tag pairs to associate with this resource. +* `nsx_id` - (Optional) The NSX ID of this resource. If set, this ID will be used to create the resource. +* `fail_if_rtep_misconfigured` - (Optional) Fail onboarding if RTEPs misconfigured. Default is true. +* `fail_if_rtt_exceeded` - (Optional) Fail onboarding if maximum RTT exceeded. Default is true. +* `maximum_rtt` - (Optional) Maximum acceptable packet round trip time (RTT). Default is 250. +* `site_connection_info` - (Optional) Connection information. + * `fqdn` - (Optional) Fully Qualified Domain Name of the Management Node. + * `password` - (Optional) Password. + * `site_uuid` - (Optional) ID of Site. + * `thumbprint` - (Optional) Thumbprint of Enforcement Point. + * `username` - (Optional) Username. +* `site_type` - (Optional) Persistent Site Type. Allowed values are ONPREM_LM, SDDC_LM. Default is ONPREM_LM. + +## Attributes Reference + +In addition to arguments listed above, the following attributes are exported: + +* `id` - ID of the resource. +* `revision` - Indicates current revision number of the object as seen by NSX-T API server. This attribute can be useful for debugging. +* `path` - The NSX path of the policy resource. + +## Importing + +An existing object can be [imported][docs-import] into this resource, via the following command: + +[docs-import]: https://www.terraform.io/cli/import + +``` +terraform import nsxt_policy_site.test POLICY_PATH +``` +The above command imports Site named `test` with policy path `POLICY_PATH`.