From 0b67d0953fc972798e66ac3e5f805c87aacf02e1 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Mon, 13 Jun 2022 15:31:11 +0530 Subject: [PATCH 1/7] resource for static route --- client/v3/v3_service.go | 33 ++- client/v3/v3_structs.go | 52 +++- nutanix/data_source_nutanix_static_routes.go | 19 ++ nutanix/provider.go | 2 + nutanix/resource_nutanix_static_routes.go | 275 +++++++++++++++++++ 5 files changed, 375 insertions(+), 6 deletions(-) create mode 100644 nutanix/data_source_nutanix_static_routes.go create mode 100644 nutanix/resource_nutanix_static_routes.go diff --git a/client/v3/v3_service.go b/client/v3/v3_service.go index b40a8d8e8..e03a9e3e7 100644 --- a/client/v3/v3_service.go +++ b/client/v3/v3_service.go @@ -137,6 +137,8 @@ type Service interface { UpdateFloatingIP(ctx context.Context, uuid string, body *FIPIntentInput) (*FloatingIPsIntentResponse, error) ListFloatingIPs(ctx context.Context, getRequest *DSMetadata) (*FloatingIPsListIntentResponse, error) ListAllFloatingIPs(ctx context.Context, filter string) (*FloatingIPsListIntentResponse, error) + GetStaticRoute(ctx context.Context, vpcUUID string) (*StaticRouteIntentResponse, error) + UpdateStaticRoute(ctx context.Context, uuid string, body *StaticRouteIntentInput) (*StaticRouteIntentResponse, error) } /*CreateVM Creates a VM @@ -2565,11 +2567,12 @@ func (op Operations) CreatePBR(ctx context.Context, body *PbrIntentInput) (*PbrI func (op Operations) GetPBR(ctx context.Context, uuid string) (*PbrIntentResponse, error) { path := fmt.Sprintf("/routing_policies/%s", uuid) req, err := op.client.NewRequest(ctx, http.MethodGet, path, nil) - pbrIntentResponse := new(PbrIntentResponse) if err != nil { return nil, err } + + pbrIntentResponse := new(PbrIntentResponse) return pbrIntentResponse, op.client.Do(ctx, req, pbrIntentResponse) } @@ -2623,7 +2626,6 @@ func (op Operations) ListAllPBR(ctx context.Context, filter string) (*PbrListInt if err != nil { return nil, err } - totalEntities := utils.Int64Value(resp.Metadata.TotalMatches) remaining := totalEntities offset := utils.Int64Value(resp.Metadata.Offset) @@ -2650,6 +2652,33 @@ func (op Operations) ListAllPBR(ctx context.Context, filter string) (*PbrListInt } return resp, nil + +} + +func (op Operations) GetStaticRoute(ctx context.Context, uuid string) (*StaticRouteIntentResponse, error) { + path := fmt.Sprintf("/vpcs/%s/route_tables", uuid) + req, err := op.client.NewRequest(ctx, http.MethodGet, path, nil) + + if err != nil { + return nil, err + } + + staticIntentResponse := new(StaticRouteIntentResponse) + + return staticIntentResponse, op.client.Do(ctx, req, staticIntentResponse) +} + +func (op Operations) UpdateStaticRoute(ctx context.Context, uuid string, body *StaticRouteIntentInput) (*StaticRouteIntentResponse, error) { + path := fmt.Sprintf("/vpcs/%s/route_tables", uuid) + req, err := op.client.NewRequest(ctx, http.MethodPut, path, body) + + if err != nil { + return nil, err + } + + staticIntentResponse := new(StaticRouteIntentResponse) + + return staticIntentResponse, op.client.Do(ctx, req, staticIntentResponse) } func (op Operations) CreateFloatingIPs(ctx context.Context, request *FIPIntentInput) (*FloatingIPsIntentResponse, error) { diff --git a/client/v3/v3_structs.go b/client/v3/v3_structs.go index ec8108490..323885fa6 100644 --- a/client/v3/v3_structs.go +++ b/client/v3/v3_structs.go @@ -2730,6 +2730,46 @@ type PbrIntentInput struct { Spec *PbrSpec `json:"spec" mapstructure:"spec"` } +type PbrListIntentResponse struct { + APIVersion *string `json:"api_version"` + Metadata *ListMetadataOutput `json:"metadata"` + Entities []*PbrIntentResponse `json:"entities"` +} + +type NextHop struct { + ExternalSubnetReference *Reference `json:"external_subnet_reference,omitempty"` +} + +type StaticRoutesList struct { + NextHop *NextHop `json:"nexthop,omitempty"` + Destination *string `json:"destination,omitempty"` + Priority *int64 `json:"priority,omitempty"` + IsActive *bool `json:"is_active,omitempty"` +} + +type StaticRouteResources struct { + StaticRoutesList []*StaticRoutesList `json:"static_routes_list,omitempty"` +} + +type StaticRouteSpec struct { + Name *string `json:"name,omitempty"` + Resources *StaticRouteResources `json:"resources,omitempty"` +} + +type StaticRouteDefStatus struct { + State *string `json:"state,omitempty"` + Resources *StaticRouteResources `json:"resources,omitempty"` + ExecutionContext *ExecutionContext `json:"execution_context,omitempty"` +} + +type StaticRouteIntentInput struct { + APIVersion *string `json:"api_version,omitempty" mapstructure:"api_version,omitempty"` + + Metadata *Metadata `json:"metadata" mapstructure:"metadata"` + + Spec *StaticRouteSpec `json:"spec" mapstructure:"spec"` +} + type PbrDefStatus struct { State *string `json:"state,omitempty" mapstructure:"state,omitempty"` ExecutionContext *ExecutionContext `json:"execution_context,omitempty" mapstructure:"execution_context,omitempty"` @@ -2746,10 +2786,14 @@ type PbrIntentResponse struct { Status *PbrDefStatus `json:"status"` } -type PbrListIntentResponse struct { - APIVersion *string `json:"api_version"` - Metadata *ListMetadataOutput `json:"metadata"` - Entities []*PbrIntentResponse `json:"entities"` +type StaticRouteIntentResponse struct { + APIVersion *string `json:"api_version,omitempty" mapstructure:"api_version,omitempty"` + + Metadata *Metadata `json:"metadata" mapstructure:"metadata"` + + Spec *StaticRouteSpec `json:"spec" mapstructure:"spec"` + + Status *StaticRouteDefStatus `json:"status"` } type FIPResource struct { diff --git a/nutanix/data_source_nutanix_static_routes.go b/nutanix/data_source_nutanix_static_routes.go new file mode 100644 index 000000000..18f797dd9 --- /dev/null +++ b/nutanix/data_source_nutanix_static_routes.go @@ -0,0 +1,19 @@ +package nutanix + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func dataSourceNutanixStaticRoute() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceNutanixStaticRouteRead, + Schema: map[string]*schema.Schema{}, + } +} + +func dataSourceNutanixStaticRouteRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return nil +} diff --git a/nutanix/provider.go b/nutanix/provider.go index dee9771b9..847b34eba 100644 --- a/nutanix/provider.go +++ b/nutanix/provider.go @@ -166,6 +166,7 @@ func Provider() *schema.Provider { "nutanix_pbrs": dataSourceNutanixPbrs(), "nutanix_floating_ip": dataSourceNutanixFloatingIP(), "nutanix_floating_ips": dataSourceNutanixFloatingIPs(), + "nutanix_static_routes": dataSourceNutanixStaticRoute(), }, ResourcesMap: map[string]*schema.Resource{ "nutanix_virtual_machine": resourceNutanixVirtualMachine(), @@ -192,6 +193,7 @@ func Provider() *schema.Provider { "nutanix_vpc": resourceNutanixVPC(), "nutanix_pbr": resourceNutanixPbr(), "nutanix_floating_ip": resourceNutanixFloatingIP(), + "nutanix_static_routes": resourceNutanixStaticRoute(), }, ConfigureContextFunc: providerConfigure, } diff --git a/nutanix/resource_nutanix_static_routes.go b/nutanix/resource_nutanix_static_routes.go new file mode 100644 index 000000000..7d3992ee8 --- /dev/null +++ b/nutanix/resource_nutanix_static_routes.go @@ -0,0 +1,275 @@ +package nutanix + +import ( + "context" + "encoding/json" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + v3 "github.com/terraform-providers/terraform-provider-nutanix/client/v3" + "github.com/terraform-providers/terraform-provider-nutanix/utils" +) + +func resourceNutanixStaticRoute() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceNutanixStaticRouteCreate, + ReadContext: resourceNutanixStaticRouteRead, + UpdateContext: resourceNutanixStaticRouteUpdate, + DeleteContext: resourceNutanixStaticRouteDelete, + Schema: map[string]*schema.Schema{ + "vpc_uuid": { + Type: schema.TypeString, + Required: true, + }, + "static_routes_list": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "destination": { + Type: schema.TypeString, + Required: true, + }, + "external_subnet_reference_uuid": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + "api_version": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "metadata": { + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + } +} + +func resourceNutanixStaticRouteCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*Client).API + + request := &v3.StaticRouteIntentInput{} + spec := &v3.StaticRouteSpec{} + res := &v3.StaticRouteResources{} + metadata := &v3.Metadata{} + + // get the details for route table + + vpcUUID, ok := d.GetOk("vpc_uuid") + if !ok { + return diag.Errorf("vpc_uuid is required") + } + resp, err := conn.V3.GetStaticRoute(ctx, vpcUUID.(string)) + if err != nil { + return diag.FromErr(err) + } + + if resp.Metadata != nil { + metadata = resp.Metadata + } + + // request.Metadata = resp.Metadata + if resp.Spec != nil { + spec = resp.Spec + + if resp.Spec.Resources != nil { + res = resp.Spec.Resources + } + } + + if err := getMetadataAttributes(d, metadata, "vpc_route_table"); err != nil { + return diag.Errorf("error reading metadata for VPC Route table %s", err) + } + + if stat, ok := d.GetOk("static_routes_list"); ok { + res.StaticRoutesList = expandStaticRouteList(stat) + } + fmt.Println("heyyyyyy") + aJSON, _ := json.Marshal(res.StaticRoutesList) + fmt.Printf("JSON Print - \n%s\n", string(aJSON)) + fmt.Println(&res.StaticRoutesList) + + spec.Resources = res + request.Spec = spec + request.Metadata = metadata + + // make a request to update the VPC Static Route Table + + fmt.Print("helloooo", &request) + bJSON, _ := json.Marshal(request) + fmt.Printf("JSON Print 22- \n%s\n", string(bJSON)) + fmt.Printf("JSON Print 33- \n%s\n", string(vpcUUID.(string))) + response, err := conn.V3.UpdateStaticRoute(ctx, vpcUUID.(string), request) + if err != nil { + return diag.FromErr(err) + } + + taskUUID := response.Status.ExecutionContext.TaskUUID.(string) + + // Wait for the Static Route to be available + stateConf := &resource.StateChangeConf{ + Pending: []string{"PENDING", "RUNNING"}, + Target: []string{"SUCCEEDED"}, + Refresh: taskStateRefreshFunc(conn, taskUUID), + Timeout: d.Timeout(schema.TimeoutCreate), + Delay: VpcDelayTime, + MinTimeout: VpcMinTimeout, + } + + if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { + return diag.Errorf("error waiting for vpc Static Route (%s) to create: %s", d.Id(), errWaitTask) + } + + d.SetId(vpcUUID.(string)) + + log.Println(response) + + return resourceNutanixStaticRouteRead(ctx, d, meta) +} + +func resourceNutanixStaticRouteRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*Client).API + + // Get API to read the static routes + + resp, err := conn.V3.GetStaticRoute(ctx, d.Id()) + if err != nil { + return diag.FromErr(err) + } + m, _ := setRSEntityMetadata(resp.Metadata) + + if err = d.Set("metadata", m); err != nil { + return diag.Errorf("error setting metadata for VPC %s: %s", d.Id(), err) + } + d.Set("api_version", resp.APIVersion) + d.Set("vpc_uuid", d.Id()) + d.Set("static_routes_list", flattenStaticRouteList(resp.Spec.Resources.StaticRoutesList)) + return nil +} + +func resourceNutanixStaticRouteUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*Client).API + + request := &v3.StaticRouteIntentInput{} + spec := &v3.StaticRouteSpec{} + res := &v3.StaticRouteResources{} + metadata := &v3.Metadata{} + + // get the details for route table + + resp, err := conn.V3.GetStaticRoute(ctx, d.Id()) + if err != nil { + return diag.FromErr(err) + } + + if resp.Metadata != nil { + metadata = resp.Metadata + } + + if resp.Spec != nil { + spec = resp.Spec + + if resp.Spec.Resources != nil { + res = resp.Spec.Resources + } + } + + if err := getMetadataAttributes(d, metadata, "vpc_route_table"); err != nil { + return diag.Errorf("error reading metadata for VPC Route table %s", err) + } + + if d.HasChange("static_routes_list") { + res.StaticRoutesList = expandStaticRouteList(d.Get("static_routes_list")) + } + fmt.Println("heyyyyyy") + aJSON, _ := json.Marshal(res.StaticRoutesList) + fmt.Printf("JSON Print - \n%s\n", string(aJSON)) + fmt.Println(&res.StaticRoutesList) + + spec.Resources = res + request.Spec = spec + request.Metadata = metadata + + // make a request to update the VPC Static Route Table + + response, err := conn.V3.UpdateStaticRoute(ctx, d.Id(), request) + if err != nil { + return diag.FromErr(err) + } + + taskUUID := response.Status.ExecutionContext.TaskUUID.(string) + + // Wait for the Static Route to be available + stateConf := &resource.StateChangeConf{ + Pending: []string{"PENDING", "RUNNING"}, + Target: []string{"SUCCEEDED"}, + Refresh: taskStateRefreshFunc(conn, taskUUID), + Timeout: d.Timeout(schema.TimeoutCreate), + Delay: VpcDelayTime, + MinTimeout: VpcMinTimeout, + } + + if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { + return diag.Errorf("error waiting for vpc Static Route (%s) to create: %s", d.Id(), errWaitTask) + } + + return resourceNutanixStaticRouteRead(ctx, d, meta) +} + +func resourceNutanixStaticRouteDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return nil +} + +func expandStaticRouteList(pr interface{}) []*v3.StaticRoutesList { + prI := pr.([]interface{}) + if len(prI) > 0 { + prList := make([]*v3.StaticRoutesList, len(prI)) + for k, val := range prI { + stat := &v3.StaticRoutesList{} + v := val.(map[string]interface{}) + + if v1, ok1 := v["destination"]; ok1 { + stat.Destination = utils.StringPtr(v1.(string)) + } + if v, ok := v["external_subnet_reference_uuid"]; ok { + nexthop := &v3.NextHop{} + + nexthop.ExternalSubnetReference = buildReference(v.(string), "subnet") + + stat.NextHop = nexthop + } + + prList[k] = stat + } + return prList + } + return nil +} + +func flattenStaticRouteList(stat []*v3.StaticRoutesList) []map[string]interface{} { + if len(stat) > 0 { + statList := make([]map[string]interface{}, len(stat)) + + for k, v := range stat { + stats := make(map[string]interface{}) + + stats["destination"] = v.Destination + stats["external_subnet_reference"] = v.NextHop.ExternalSubnetReference.UUID + + statList[k] = stats + } + return statList + } + return nil +} From 25c172d5f2e9bc72c18b5fd081b553e54224fb0f Mon Sep 17 00:00:00 2001 From: Abhishek Date: Mon, 13 Jun 2022 18:44:36 +0530 Subject: [PATCH 2/7] added data sources --- nutanix/data_source_nutanix_static_routes.go | 123 ++++++++++++++++++- 1 file changed, 122 insertions(+), 1 deletion(-) diff --git a/nutanix/data_source_nutanix_static_routes.go b/nutanix/data_source_nutanix_static_routes.go index 18f797dd9..c4860ceff 100644 --- a/nutanix/data_source_nutanix_static_routes.go +++ b/nutanix/data_source_nutanix_static_routes.go @@ -10,7 +10,128 @@ import ( func dataSourceNutanixStaticRoute() *schema.Resource { return &schema.Resource{ ReadContext: dataSourceNutanixStaticRouteRead, - Schema: map[string]*schema.Schema{}, + Schema: map[string]*schema.Schema{ + "api_version": { + Type: schema.TypeString, + Computed: true, + }, + "metadata": { + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "spec": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + }, + "resources": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "static_routes_list": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "nexthop": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "external_subnet_reference": { + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "destination": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "status": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "state": { + Type: schema.TypeString, + Computed: true, + }, + "resources": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "static_routes_list": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "priority": { + Type: schema.TypeInt, + Computed: true, + }, + "nexthop": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "external_subnet_reference": { + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "destination": { + Type: schema.TypeString, + Computed: true, + }, + "is_active": { + Type: schema.TypeBool, + Computed: true, + }, + }, + }, + }, + }, + }, + }, + "execution_context": { + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, } } From ea9d179ab8ca79ff32de0482ed73f6fb1919d880 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Tue, 14 Jun 2022 12:02:53 +0530 Subject: [PATCH 3/7] added ReadContext --- nutanix/data_source_nutanix_static_routes.go | 156 ++++++++++++++++++- nutanix/resource_nutanix_static_routes.go | 2 +- 2 files changed, 154 insertions(+), 4 deletions(-) diff --git a/nutanix/data_source_nutanix_static_routes.go b/nutanix/data_source_nutanix_static_routes.go index c4860ceff..e8358e208 100644 --- a/nutanix/data_source_nutanix_static_routes.go +++ b/nutanix/data_source_nutanix_static_routes.go @@ -5,12 +5,17 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + v3 "github.com/terraform-providers/terraform-provider-nutanix/client/v3" ) func dataSourceNutanixStaticRoute() *schema.Resource { return &schema.Resource{ ReadContext: dataSourceNutanixStaticRouteRead, Schema: map[string]*schema.Schema{ + "vpc_reference_uuid": { + Type: schema.TypeString, + Required: true, + }, "api_version": { Type: schema.TypeString, Computed: true, @@ -122,10 +127,18 @@ func dataSourceNutanixStaticRoute() *schema.Resource { }, }, "execution_context": { - Type: schema.TypeMap, + Type: schema.TypeList, Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "task_uuid": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, }, }, }, @@ -136,5 +149,142 @@ func dataSourceNutanixStaticRoute() *schema.Resource { } func dataSourceNutanixStaticRouteRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*Client).API + + vpc, ok := d.GetOk("vpc_reference_uuid") + if !ok { + return diag.Errorf("please provide one of vpc_reference_uuid attributes") + } + + // Get request to static Routes + + resp, err := conn.V3.GetStaticRoute(ctx, vpc.(string)) + if err != nil { + return diag.FromErr(err) + } + + m, _ := setRSEntityMetadata(resp.Metadata) + + if err := d.Set("metadata", m); err != nil { + return diag.FromErr(err) + } + + if err := d.Set("api_version", resp.APIVersion); err != nil { + return diag.FromErr(err) + } + + if err := d.Set("spec", flattenStaticRouteSpec(resp.Spec)); err != nil { + return diag.FromErr(err) + } + + if err := d.Set("status", flattenStaticRouteStatus(resp.Status)); err != nil { + return diag.FromErr(err) + } + + d.SetId(*resp.Metadata.UUID) + return nil +} + +func flattenStaticRouteSpec(stat *v3.StaticRouteSpec) []interface{} { + statList := make([]interface{}, 0) + if stat != nil { + stats := make(map[string]interface{}, 0) + + stats["name"] = stat.Name + stats["resources"] = flattenStaticRouteSpecResources(stat.Resources) + + statList = append(statList, stats) + return statList + } + return nil +} + +func flattenStaticRouteStatus(srs *v3.StaticRouteDefStatus) []interface{} { + srsList := make([]interface{}, 0) + if srs != nil { + sr := make(map[string]interface{}) + + sr["state"] = srs.State + sr["resources"] = flattenStaticRouteStatusResources(srs.Resources) + sr["execution_context"] = flattenExecutionContext(srs.ExecutionContext) + + srsList = append(srsList, sr) + return srsList + } + return nil +} + +func flattenStaticRouteSpecResources(pr *v3.StaticRouteResources) []interface{} { + prList := make([]interface{}, 0) + if pr != nil { + stats := make(map[string]interface{}, 0) + + stats["static_routes_list"] = flattenSpecStaticRouteList(pr.StaticRoutesList) + + prList = append(prList, stats) + return prList + } + return nil +} + +func flattenStaticRouteStatusResources(pr *v3.StaticRouteResources) []interface{} { + prList := make([]interface{}, 0) + if pr != nil { + prs := make(map[string]interface{}) + + prs["static_routes_list"] = flattenStatusStaticRouteList(pr.StaticRoutesList) + prList = append(prList, prs) + return prList + } + return nil +} +func flattenSpecStaticRouteList(sr []*v3.StaticRoutesList) []map[string]interface{} { + srList := make([]map[string]interface{}, len(sr)) + + if len(sr) > 0 { + for k, v := range sr { + srs := make(map[string]interface{}) + + srs["destination"] = v.Destination + srs["nexthop"] = flattenNextHop(v.NextHop) + + srList[k] = srs + } + return srList + } + return nil +} + +func flattenStatusStaticRouteList(sr []*v3.StaticRoutesList) []map[string]interface{} { + srList := make([]map[string]interface{}, len(sr)) + + if len(sr) > 0 { + for k, v := range sr { + srs := make(map[string]interface{}) + + srs["destination"] = v.Destination + srs["nexthop"] = flattenNextHop(v.NextHop) + srs["is_active"] = v.IsActive + srs["priority"] = v.Priority + + srList[k] = srs + } + return srList + } + return nil +} + +func flattenNextHop(nh *v3.NextHop) []interface{} { + nhList := make([]interface{}, 0) + + if nh != nil { + nhs := make(map[string]interface{}) + + nhs["external_subnet_reference"] = flattenReferenceValues(nh.ExternalSubnetReference) + + nhList = append(nhList, nhs) + + return nhList + } return nil } diff --git a/nutanix/resource_nutanix_static_routes.go b/nutanix/resource_nutanix_static_routes.go index 7d3992ee8..e3f6d9062 100644 --- a/nutanix/resource_nutanix_static_routes.go +++ b/nutanix/resource_nutanix_static_routes.go @@ -26,7 +26,7 @@ func resourceNutanixStaticRoute() *schema.Resource { }, "static_routes_list": { Type: schema.TypeList, - Required: true, + Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "destination": { From 258e940c8b99cdd109a523dca079ee8124c016c8 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Tue, 14 Jun 2022 17:30:15 +0530 Subject: [PATCH 4/7] removed print lines --- nutanix/resource_nutanix_static_routes.go | 34 +++++++---------------- 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/nutanix/resource_nutanix_static_routes.go b/nutanix/resource_nutanix_static_routes.go index e3f6d9062..99a9df144 100644 --- a/nutanix/resource_nutanix_static_routes.go +++ b/nutanix/resource_nutanix_static_routes.go @@ -2,9 +2,7 @@ package nutanix import ( "context" - "encoding/json" - "fmt" - "log" + "time" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -13,6 +11,11 @@ import ( "github.com/terraform-providers/terraform-provider-nutanix/utils" ) +const ( + StaticRouteDelayTime = 2 * time.Second + StaticRouteMinTimeout = 5 * time.Second +) + func resourceNutanixStaticRoute() *schema.Resource { return &schema.Resource{ CreateContext: resourceNutanixStaticRouteCreate, @@ -95,21 +98,12 @@ func resourceNutanixStaticRouteCreate(ctx context.Context, d *schema.ResourceDat if stat, ok := d.GetOk("static_routes_list"); ok { res.StaticRoutesList = expandStaticRouteList(stat) } - fmt.Println("heyyyyyy") - aJSON, _ := json.Marshal(res.StaticRoutesList) - fmt.Printf("JSON Print - \n%s\n", string(aJSON)) - fmt.Println(&res.StaticRoutesList) spec.Resources = res request.Spec = spec request.Metadata = metadata // make a request to update the VPC Static Route Table - - fmt.Print("helloooo", &request) - bJSON, _ := json.Marshal(request) - fmt.Printf("JSON Print 22- \n%s\n", string(bJSON)) - fmt.Printf("JSON Print 33- \n%s\n", string(vpcUUID.(string))) response, err := conn.V3.UpdateStaticRoute(ctx, vpcUUID.(string), request) if err != nil { return diag.FromErr(err) @@ -123,8 +117,8 @@ func resourceNutanixStaticRouteCreate(ctx context.Context, d *schema.ResourceDat Target: []string{"SUCCEEDED"}, Refresh: taskStateRefreshFunc(conn, taskUUID), Timeout: d.Timeout(schema.TimeoutCreate), - Delay: VpcDelayTime, - MinTimeout: VpcMinTimeout, + Delay: StaticRouteDelayTime, + MinTimeout: StaticRouteMinTimeout, } if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { @@ -132,9 +126,6 @@ func resourceNutanixStaticRouteCreate(ctx context.Context, d *schema.ResourceDat } d.SetId(vpcUUID.(string)) - - log.Println(response) - return resourceNutanixStaticRouteRead(ctx, d, meta) } @@ -192,10 +183,6 @@ func resourceNutanixStaticRouteUpdate(ctx context.Context, d *schema.ResourceDat if d.HasChange("static_routes_list") { res.StaticRoutesList = expandStaticRouteList(d.Get("static_routes_list")) } - fmt.Println("heyyyyyy") - aJSON, _ := json.Marshal(res.StaticRoutesList) - fmt.Printf("JSON Print - \n%s\n", string(aJSON)) - fmt.Println(&res.StaticRoutesList) spec.Resources = res request.Spec = spec @@ -216,8 +203,8 @@ func resourceNutanixStaticRouteUpdate(ctx context.Context, d *schema.ResourceDat Target: []string{"SUCCEEDED"}, Refresh: taskStateRefreshFunc(conn, taskUUID), Timeout: d.Timeout(schema.TimeoutCreate), - Delay: VpcDelayTime, - MinTimeout: VpcMinTimeout, + Delay: StaticRouteDelayTime, + MinTimeout: StaticRouteMinTimeout, } if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { @@ -249,7 +236,6 @@ func expandStaticRouteList(pr interface{}) []*v3.StaticRoutesList { stat.NextHop = nexthop } - prList[k] = stat } return prList From 96b08314fbca1847df9b8bdd23dab7e3fb14efe9 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Tue, 21 Jun 2022 19:09:05 +0530 Subject: [PATCH 5/7] added examples --- examples/static_routes/main.tf | 48 +++++++++++++++++++++++++ examples/static_routes/terraform.tfvars | 5 +++ examples/static_routes/variables.tf | 13 +++++++ 3 files changed, 66 insertions(+) create mode 100644 examples/static_routes/main.tf create mode 100644 examples/static_routes/terraform.tfvars create mode 100644 examples/static_routes/variables.tf diff --git a/examples/static_routes/main.tf b/examples/static_routes/main.tf new file mode 100644 index 000000000..456799a8c --- /dev/null +++ b/examples/static_routes/main.tf @@ -0,0 +1,48 @@ +terraform{ + required_providers { + nutanix = { + source = "nutanix/nutanix" + version = "1.6.0" + } + } +} + +#definig nutanix configuration +provider "nutanix"{ + username = var.nutanix_username + password = var.nutanix_password + endpoint = var.nutanix_endpoint + port = 9440 + insecure = true +} + + +#create one static route for vpc with external subnet +resource "nutanix_static_routes" "scn" { + vpc_uuid = "{{vpc_uuid}}" + + static_routes_list{ + # destination prefix format 10.x.x.x/x + destination= "10.x.x.x/x" + # required ext subnet uuid for next hop + external_subnet_reference_uuid = "{{ext_subnet_uuid}}" + } +} + + +#create multiple static routes for vpc with external subnet +resource "nutanix_static_routes" "scn" { + vpc_uuid = "{{vpc_uuid}}" + + static_routes_list{ + # destination prefix format 10.x.x.x/x + destination= "10.x.x.x/x" + # required ext subnet uuid for next hop + external_subnet_reference_uuid = "{{ext_subnet_uuid}}" + } + + static_routes_list{ + destination= "10.x.x.x/x" + external_subnet_reference_uuid = "{{ext_subnet_uuid}}" + } +} diff --git a/examples/static_routes/terraform.tfvars b/examples/static_routes/terraform.tfvars new file mode 100644 index 000000000..867888ffc --- /dev/null +++ b/examples/static_routes/terraform.tfvars @@ -0,0 +1,5 @@ +#define values to the variables to be used in terraform file +nutanix_username = "admin" +nutanix_password = "password" +nutanix_endpoint = "10.xx.xx.xx" +nutanix_port = 9440 diff --git a/examples/static_routes/variables.tf b/examples/static_routes/variables.tf new file mode 100644 index 000000000..dcd130ec8 --- /dev/null +++ b/examples/static_routes/variables.tf @@ -0,0 +1,13 @@ +#define the type of variables to be used in terraform file +variable "nutanix_username" { + type = string +} +variable "nutanix_password" { + type = string +} +variable "nutanix_endpoint" { + type = string +} +variable "nutanix_port" { + type = string +} From 1d7c11aa7695ec1bf08b217db65280a5a138b8d4 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Tue, 21 Jun 2022 19:17:36 +0530 Subject: [PATCH 6/7] lint fixes --- nutanix/data_source_nutanix_static_routes.go | 4 ++-- nutanix/resource_nutanix_static_routes.go | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/nutanix/data_source_nutanix_static_routes.go b/nutanix/data_source_nutanix_static_routes.go index e8358e208..c4de62b53 100644 --- a/nutanix/data_source_nutanix_static_routes.go +++ b/nutanix/data_source_nutanix_static_routes.go @@ -188,7 +188,7 @@ func dataSourceNutanixStaticRouteRead(ctx context.Context, d *schema.ResourceDat func flattenStaticRouteSpec(stat *v3.StaticRouteSpec) []interface{} { statList := make([]interface{}, 0) if stat != nil { - stats := make(map[string]interface{}, 0) + stats := make(map[string]interface{}) stats["name"] = stat.Name stats["resources"] = flattenStaticRouteSpecResources(stat.Resources) @@ -217,7 +217,7 @@ func flattenStaticRouteStatus(srs *v3.StaticRouteDefStatus) []interface{} { func flattenStaticRouteSpecResources(pr *v3.StaticRouteResources) []interface{} { prList := make([]interface{}, 0) if pr != nil { - stats := make(map[string]interface{}, 0) + stats := make(map[string]interface{}) stats["static_routes_list"] = flattenSpecStaticRouteList(pr.StaticRoutesList) diff --git a/nutanix/resource_nutanix_static_routes.go b/nutanix/resource_nutanix_static_routes.go index 99a9df144..7af5a59ed 100644 --- a/nutanix/resource_nutanix_static_routes.go +++ b/nutanix/resource_nutanix_static_routes.go @@ -91,8 +91,8 @@ func resourceNutanixStaticRouteCreate(ctx context.Context, d *schema.ResourceDat } } - if err := getMetadataAttributes(d, metadata, "vpc_route_table"); err != nil { - return diag.Errorf("error reading metadata for VPC Route table %s", err) + if er := getMetadataAttributes(d, metadata, "vpc_route_table"); er != nil { + return diag.Errorf("error reading metadata for VPC Route table %s", er) } if stat, ok := d.GetOk("static_routes_list"); ok { @@ -176,8 +176,8 @@ func resourceNutanixStaticRouteUpdate(ctx context.Context, d *schema.ResourceDat } } - if err := getMetadataAttributes(d, metadata, "vpc_route_table"); err != nil { - return diag.Errorf("error reading metadata for VPC Route table %s", err) + if er := getMetadataAttributes(d, metadata, "vpc_route_table"); er != nil { + return diag.Errorf("error reading metadata for VPC Route table %s", er) } if d.HasChange("static_routes_list") { From 74a752c476dd5fdfd687638ad7b0ae7f7ef259ed Mon Sep 17 00:00:00 2001 From: Abhishek Date: Wed, 29 Jun 2022 12:41:46 +0530 Subject: [PATCH 7/7] lint fixes --- client/v3/v3_service.go | 1 - 1 file changed, 1 deletion(-) diff --git a/client/v3/v3_service.go b/client/v3/v3_service.go index e03a9e3e7..850282413 100644 --- a/client/v3/v3_service.go +++ b/client/v3/v3_service.go @@ -2652,7 +2652,6 @@ func (op Operations) ListAllPBR(ctx context.Context, filter string) (*PbrListInt } return resp, nil - } func (op Operations) GetStaticRoute(ctx context.Context, uuid string) (*StaticRouteIntentResponse, error) {