diff --git a/equinix/data_source_fabric_cloud_router_acc_test.go b/equinix/data_source_fabric_cloud_router_acc_test.go index be437389d..396727edc 100644 --- a/equinix/data_source_fabric_cloud_router_acc_test.go +++ b/equinix/data_source_fabric_cloud_router_acc_test.go @@ -24,7 +24,7 @@ func TestAccDataSourceFabricCloudRouter_PFCR(t *testing.T) { resource.TestCheckResourceAttr("data.equinix_fabric_cloud_router.example", "notifications.0.emails.0", "test@equinix.com"), resource.TestCheckResourceAttr("data.equinix_fabric_cloud_router.example", "order.0.purchase_order_number", "1-323292"), resource.TestCheckResourceAttr("data.equinix_fabric_cloud_router.example", "location.0.metro_code", "SV"), - resource.TestCheckResourceAttr("data.equinix_fabric_cloud_router.example", "package.0.code", "LAB"), + resource.TestCheckResourceAttr("data.equinix_fabric_cloud_router.example", "package.0.code", "STANDARD"), resource.TestCheckResourceAttrSet("data.equinix_fabric_cloud_router.example", "project.0.project_id"), resource.TestCheckResourceAttrSet("data.equinix_fabric_cloud_router.example", "account.0.account_number"), resource.TestCheckResourceAttrSet("data.equinix_fabric_cloud_router.example", "href"), @@ -62,7 +62,7 @@ func ConfigCreateCloudRouterResource_PFCR() string { metro_code= "SV" } package { - code="LAB" + code="STANDARD" } project { project_id = "291639000636552" diff --git a/equinix/resource_fabric_cloud_router.go b/equinix/resource_fabric_cloud_router.go index 66f75d77f..8d1c6b857 100644 --- a/equinix/resource_fabric_cloud_router.go +++ b/equinix/resource_fabric_cloud_router.go @@ -189,10 +189,10 @@ func fabricCloudRouterResourceSchema() map[string]*schema.Schema { func resourceFabricCloudRouter() *schema.Resource { return &schema.Resource{ Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(6 * time.Minute), + Create: schema.DefaultTimeout(10 * time.Minute), Update: schema.DefaultTimeout(10 * time.Minute), - Delete: schema.DefaultTimeout(6 * time.Minute), - Read: schema.DefaultTimeout(6 * time.Minute), + Delete: schema.DefaultTimeout(10 * time.Minute), + Read: schema.DefaultTimeout(10 * time.Minute), }, ReadContext: resourceFabricCloudRouterRead, CreateContext: resourceFabricCloudRouterCreate, @@ -278,13 +278,15 @@ func resourceFabricCloudRouterCreate(ctx context.Context, d *schema.ResourceData createRequest.Order = &order } + start := time.Now() fcr, _, err := client.CloudRoutersApi.CreateCloudRouter(ctx, createRequest) if err != nil { return diag.FromErr(equinix_errors.FormatFabricError(err)) } d.SetId(fcr.Uuid) - if _, err = waitUntilCloudRouterIsProvisioned(d.Id(), meta, ctx); err != nil { + createTimeout := d.Timeout(schema.TimeoutCreate) - 30*time.Second - time.Since(start) + if _, err = waitUntilCloudRouterIsProvisioned(d.Id(), meta, ctx, createTimeout); err != nil { return diag.Errorf("error waiting for Cloud Router (%s) to be created: %s", d.Id(), err) } @@ -387,7 +389,9 @@ func getCloudRouterUpdateRequest(conn v4.CloudRouter, d *schema.ResourceData) (v func resourceFabricCloudRouterUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { client := meta.(*config.Config).FabricClient ctx = context.WithValue(ctx, v4.ContextAccessToken, meta.(*config.Config).FabricAuthToken) - dbConn, err := waitUntilCloudRouterIsProvisioned(d.Id(), meta, ctx) + start := time.Now() + updateTimeout := d.Timeout(schema.TimeoutUpdate) - 30*time.Second - time.Since(start) + dbConn, err := waitUntilCloudRouterIsProvisioned(d.Id(), meta, ctx, updateTimeout) if err != nil { if !strings.Contains(err.Error(), "500") { d.SetId("") @@ -405,7 +409,8 @@ func resourceFabricCloudRouterUpdate(ctx context.Context, d *schema.ResourceData return diag.FromErr(equinix_errors.FormatFabricError(err)) } updateFg := v4.CloudRouter{} - updateFg, err = waitForCloudRouterUpdateCompletion(d.Id(), meta, ctx) + updateTimeout = d.Timeout(schema.TimeoutUpdate) - 30*time.Second - time.Since(start) + updateFg, err = waitForCloudRouterUpdateCompletion(d.Id(), meta, ctx, updateTimeout) if err != nil { if !strings.Contains(err.Error(), "500") { @@ -418,7 +423,7 @@ func resourceFabricCloudRouterUpdate(ctx context.Context, d *schema.ResourceData return setCloudRouterMap(d, updateFg) } -func waitForCloudRouterUpdateCompletion(uuid string, meta interface{}, ctx context.Context) (v4.CloudRouter, error) { +func waitForCloudRouterUpdateCompletion(uuid string, meta interface{}, ctx context.Context, timeout time.Duration) (v4.CloudRouter, error) { log.Printf("Waiting for Cloud Router update to complete, uuid %s", uuid) stateConf := &retry.StateChangeConf{ Target: []string{string(v4.PROVISIONED_CloudRouterAccessPointState)}, @@ -430,7 +435,7 @@ func waitForCloudRouterUpdateCompletion(uuid string, meta interface{}, ctx conte } return dbConn, string(*dbConn.State), nil }, - Timeout: 2 * time.Minute, + Timeout: timeout, Delay: 30 * time.Second, MinTimeout: 30 * time.Second, } @@ -444,7 +449,7 @@ func waitForCloudRouterUpdateCompletion(uuid string, meta interface{}, ctx conte return dbConn, err } -func waitUntilCloudRouterIsProvisioned(uuid string, meta interface{}, ctx context.Context) (v4.CloudRouter, error) { +func waitUntilCloudRouterIsProvisioned(uuid string, meta interface{}, ctx context.Context, timeout time.Duration) (v4.CloudRouter, error) { log.Printf("Waiting for Cloud Router to be provisioned, uuid %s", uuid) stateConf := &retry.StateChangeConf{ Pending: []string{ @@ -461,7 +466,7 @@ func waitUntilCloudRouterIsProvisioned(uuid string, meta interface{}, ctx contex } return dbConn, string(*dbConn.State), nil }, - Timeout: 5 * time.Minute, + Timeout: timeout, Delay: 30 * time.Second, MinTimeout: 30 * time.Second, } @@ -479,6 +484,7 @@ func resourceFabricCloudRouterDelete(ctx context.Context, d *schema.ResourceData diags := diag.Diagnostics{} client := meta.(*config.Config).FabricClient ctx = context.WithValue(ctx, v4.ContextAccessToken, meta.(*config.Config).FabricAuthToken) + start := time.Now() _, err := client.CloudRoutersApi.DeleteCloudRouterByUuid(ctx, d.Id()) if err != nil { errors, ok := err.(v4.GenericSwaggerError).Model().([]v4.ModelError) @@ -491,14 +497,15 @@ func resourceFabricCloudRouterDelete(ctx context.Context, d *schema.ResourceData return diag.FromErr(equinix_errors.FormatFabricError(err)) } - err = WaitUntilCloudRouterDeprovisioned(d.Id(), meta, ctx) + deleteTimeout := d.Timeout(schema.TimeoutDelete) - 30*time.Second - time.Since(start) + err = WaitUntilCloudRouterDeprovisioned(d.Id(), meta, ctx, deleteTimeout) if err != nil { return diag.FromErr(fmt.Errorf("API call failed while waiting for resource deletion. Error %v", err)) } return diags } -func WaitUntilCloudRouterDeprovisioned(uuid string, meta interface{}, ctx context.Context) error { +func WaitUntilCloudRouterDeprovisioned(uuid string, meta interface{}, ctx context.Context, timeout time.Duration) error { log.Printf("Waiting for Fabric Cloud Router to be deprovisioned, uuid %s", uuid) stateConf := &retry.StateChangeConf{ Pending: []string{ @@ -515,7 +522,7 @@ func WaitUntilCloudRouterDeprovisioned(uuid string, meta interface{}, ctx contex } return dbConn, string(*dbConn.State), nil }, - Timeout: 5 * time.Minute, + Timeout: timeout, Delay: 30 * time.Second, MinTimeout: 30 * time.Second, } diff --git a/equinix/resource_fabric_cloud_router_acc_test.go b/equinix/resource_fabric_cloud_router_acc_test.go index 9aafde673..43060e9e3 100644 --- a/equinix/resource_fabric_cloud_router_acc_test.go +++ b/equinix/resource_fabric_cloud_router_acc_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "testing" + "time" v4 "github.com/equinix-labs/fabric-go/fabric/v4" @@ -41,7 +42,7 @@ func TestAccCloudRouterCreateOnlyRequiredParameters_PFCR(t *testing.T) { resource.TestCheckResourceAttr("equinix_fabric_cloud_router.test", "notifications.0.emails.0", "test@equinix.com"), resource.TestCheckResourceAttr("equinix_fabric_cloud_router.test", "order.0.purchase_order_number", "1-234567"), resource.TestCheckResourceAttr("equinix_fabric_cloud_router.test", "location.0.metro_code", "SV"), - resource.TestCheckResourceAttr("equinix_fabric_cloud_router.test", "package.0.code", "LAB"), + resource.TestCheckResourceAttr("equinix_fabric_cloud_router.test", "package.0.code", "STANDARD"), resource.TestCheckResourceAttrSet("equinix_fabric_cloud_router.test", "project.0.project_id"), resource.TestCheckResourceAttrSet("equinix_fabric_cloud_router.test", "account.0.account_number"), resource.TestCheckResourceAttrSet("equinix_fabric_cloud_router.test", "href"), @@ -79,7 +80,7 @@ func testAccCloudRouterCreateOnlyRequiredParameterConfig_PFCR(name string) strin metro_code = "SV" } package{ - code = "LAB" + code = "STANDARD" } order{ purchase_order_number = "1-234567" @@ -176,7 +177,7 @@ func checkCloudRouterDelete(s *terraform.State) error { if rs.Type != "equinix_fabric_cloud_router" { continue } - err := equinix.WaitUntilCloudRouterDeprovisioned(rs.Primary.ID, acceptance.TestAccProvider.Meta(), ctx) + err := equinix.WaitUntilCloudRouterDeprovisioned(rs.Primary.ID, acceptance.TestAccProvider.Meta(), ctx, 10*time.Minute) if err != nil { return fmt.Errorf("API call failed while waiting for resource deletion") } diff --git a/equinix/resource_fabric_connection.go b/equinix/resource_fabric_connection.go index a984473b4..281703c8c 100644 --- a/equinix/resource_fabric_connection.go +++ b/equinix/resource_fabric_connection.go @@ -592,10 +592,10 @@ func connectionRedundancySch() map[string]*schema.Schema { func resourceFabricConnection() *schema.Resource { return &schema.Resource{ Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(6 * time.Minute), - Update: schema.DefaultTimeout(10 * time.Minute), - Delete: schema.DefaultTimeout(6 * time.Minute), - Read: schema.DefaultTimeout(6 * time.Minute), + Create: schema.DefaultTimeout(15 * time.Minute), + Update: schema.DefaultTimeout(15 * time.Minute), + Delete: schema.DefaultTimeout(15 * time.Minute), + Read: schema.DefaultTimeout(10 * time.Minute), }, ReadContext: resourceFabricConnectionRead, CreateContext: resourceFabricConnectionCreate, @@ -686,13 +686,15 @@ func resourceFabricConnectionCreate(ctx context.Context, d *schema.ResourceData, Project: project, } + start := time.Now() conn, _, err := client.ConnectionsApi.CreateConnection(ctx, createRequest) if err != nil { return diag.FromErr(equinix_errors.FormatFabricError(err)) } d.SetId(conn.Uuid) - if err = waitUntilConnectionIsCreated(d.Id(), meta, ctx); err != nil { + createTimeout := d.Timeout(schema.TimeoutCreate) - 30*time.Second - time.Since(start) + if err = waitUntilConnectionIsCreated(d.Id(), meta, ctx, createTimeout); err != nil { return diag.Errorf("error waiting for connection (%s) to be created: %s", d.Id(), err) } @@ -711,7 +713,8 @@ func resourceFabricConnectionCreate(ctx context.Context, d *schema.ResourceData, return diag.FromErr(equinix_errors.FormatFabricError(patchErr)) } - if _, statusChangeErr := waitForConnectionProviderStatusChange(d.Id(), meta, ctx); statusChangeErr != nil { + createTimeout := d.Timeout(schema.TimeoutCreate) - 30*time.Second - time.Since(start) + if _, statusChangeErr := waitForConnectionProviderStatusChange(d.Id(), meta, ctx, createTimeout); statusChangeErr != nil { return diag.Errorf("error waiting for AWS Approval for connection %s: %v", d.Id(), statusChangeErr) } } @@ -800,7 +803,9 @@ func setFabricMap(d *schema.ResourceData, conn v4.Connection) diag.Diagnostics { func resourceFabricConnectionUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { client := meta.(*config.Config).FabricClient ctx = context.WithValue(ctx, v4.ContextAccessToken, meta.(*config.Config).FabricAuthToken) - dbConn, err := verifyConnectionCreated(d.Id(), meta, ctx) + start := time.Now() + updateTimeout := d.Timeout(schema.TimeoutUpdate) - 30*time.Second - time.Since(start) + dbConn, err := verifyConnectionCreated(d.Id(), meta, ctx, updateTimeout) if err != nil { if !strings.Contains(err.Error(), "500") { d.SetId("") @@ -823,7 +828,7 @@ func resourceFabricConnectionUpdate(ctx context.Context, d *schema.ResourceData, continue } - var waitFunction func(uuid string, meta interface{}, ctx context.Context) (v4.Connection, error) + var waitFunction func(uuid string, meta interface{}, ctx context.Context, timeout time.Duration) (v4.Connection, error) if update[0].Op == "replace" { // Update type is either name or bandwidth waitFunction = waitForConnectionUpdateCompletion @@ -832,7 +837,8 @@ func resourceFabricConnectionUpdate(ctx context.Context, d *schema.ResourceData, waitFunction = waitForConnectionProviderStatusChange } - conn, err := waitFunction(d.Id(), meta, ctx) + updateTimeout := d.Timeout(schema.TimeoutUpdate) - 30*time.Second - time.Since(start) + conn, err := waitFunction(d.Id(), meta, ctx, updateTimeout) if err != nil { diags = append(diags, diag.Diagnostic{Severity: 0, Summary: fmt.Sprintf("connection property update completion timeout error: %v [update payload: %v] (other updates will be successful if the payload is not shown)", err, update)}) @@ -845,7 +851,7 @@ func resourceFabricConnectionUpdate(ctx context.Context, d *schema.ResourceData, return append(diags, setFabricMap(d, updatedConn)...) } -func waitForConnectionUpdateCompletion(uuid string, meta interface{}, ctx context.Context) (v4.Connection, error) { +func waitForConnectionUpdateCompletion(uuid string, meta interface{}, ctx context.Context, timeout time.Duration) (v4.Connection, error) { log.Printf("[DEBUG] Waiting for connection update to complete, uuid %s", uuid) stateConf := &retry.StateChangeConf{ Target: []string{"COMPLETED"}, @@ -861,7 +867,7 @@ func waitForConnectionUpdateCompletion(uuid string, meta interface{}, ctx contex } return dbConn, updatableState, nil }, - Timeout: 3 * time.Minute, + Timeout: timeout, Delay: 30 * time.Second, MinTimeout: 30 * time.Second, } @@ -875,7 +881,7 @@ func waitForConnectionUpdateCompletion(uuid string, meta interface{}, ctx contex return dbConn, err } -func waitUntilConnectionIsCreated(uuid string, meta interface{}, ctx context.Context) error { +func waitUntilConnectionIsCreated(uuid string, meta interface{}, ctx context.Context, timeout time.Duration) error { log.Printf("Waiting for connection to be created, uuid %s", uuid) stateConf := &retry.StateChangeConf{ Pending: []string{ @@ -894,7 +900,7 @@ func waitUntilConnectionIsCreated(uuid string, meta interface{}, ctx context.Con } return dbConn, string(*dbConn.State), nil }, - Timeout: 5 * time.Minute, + Timeout: timeout, Delay: 30 * time.Second, MinTimeout: 30 * time.Second, } @@ -904,7 +910,7 @@ func waitUntilConnectionIsCreated(uuid string, meta interface{}, ctx context.Con return err } -func waitForConnectionProviderStatusChange(uuid string, meta interface{}, ctx context.Context) (v4.Connection, error) { +func waitForConnectionProviderStatusChange(uuid string, meta interface{}, ctx context.Context, timeout time.Duration) (v4.Connection, error) { log.Printf("DEBUG: wating for provider status to update. Connection uuid: %s", uuid) stateConf := &retry.StateChangeConf{ Pending: []string{ @@ -922,7 +928,7 @@ func waitForConnectionProviderStatusChange(uuid string, meta interface{}, ctx co } return dbConn, string(*dbConn.Operation.ProviderStatus), nil }, - Timeout: 5 * time.Minute, + Timeout: timeout, Delay: 30 * time.Second, MinTimeout: 30 * time.Second, } @@ -936,7 +942,7 @@ func waitForConnectionProviderStatusChange(uuid string, meta interface{}, ctx co return dbConn, err } -func verifyConnectionCreated(uuid string, meta interface{}, ctx context.Context) (v4.Connection, error) { +func verifyConnectionCreated(uuid string, meta interface{}, ctx context.Context, timeout time.Duration) (v4.Connection, error) { log.Printf("Waiting for connection to be in created state, uuid %s", uuid) stateConf := &retry.StateChangeConf{ Target: []string{ @@ -952,7 +958,7 @@ func verifyConnectionCreated(uuid string, meta interface{}, ctx context.Context) } return dbConn, string(*dbConn.State), nil }, - Timeout: 5 * time.Minute, + Timeout: timeout, Delay: 30 * time.Second, MinTimeout: 30 * time.Second, } @@ -970,6 +976,7 @@ func resourceFabricConnectionDelete(ctx context.Context, d *schema.ResourceData, diags := diag.Diagnostics{} client := meta.(*config.Config).FabricClient ctx = context.WithValue(ctx, v4.ContextAccessToken, meta.(*config.Config).FabricAuthToken) + start := time.Now() _, _, err := client.ConnectionsApi.DeleteConnectionByUuid(ctx, d.Id()) if err != nil { errors, ok := err.(v4.GenericSwaggerError).Model().([]v4.ModelError) @@ -982,14 +989,15 @@ func resourceFabricConnectionDelete(ctx context.Context, d *schema.ResourceData, return diag.FromErr(equinix_errors.FormatFabricError(err)) } - err = WaitUntilConnectionDeprovisioned(d.Id(), meta, ctx) + deleteTimeout := d.Timeout(schema.TimeoutDelete) - 30*time.Second - time.Since(start) + err = WaitUntilConnectionDeprovisioned(d.Id(), meta, ctx, deleteTimeout) if err != nil { return diag.FromErr(fmt.Errorf("API call failed while waiting for resource deletion. Error %v", err)) } return diags } -func WaitUntilConnectionDeprovisioned(uuid string, meta interface{}, ctx context.Context) error { +func WaitUntilConnectionDeprovisioned(uuid string, meta interface{}, ctx context.Context, timeout time.Duration) error { log.Printf("Waiting for connection to be deprovisioned, uuid %s", uuid) stateConf := &retry.StateChangeConf{ Pending: []string{ @@ -1006,7 +1014,7 @@ func WaitUntilConnectionDeprovisioned(uuid string, meta interface{}, ctx context } return dbConn, string(*dbConn.State), nil }, - Timeout: 6 * time.Minute, + Timeout: timeout, Delay: 30 * time.Second, MinTimeout: 30 * time.Second, } diff --git a/equinix/resource_fabric_connection_acc_test.go b/equinix/resource_fabric_connection_acc_test.go index 23739f134..fd052fb08 100644 --- a/equinix/resource_fabric_connection_acc_test.go +++ b/equinix/resource_fabric_connection_acc_test.go @@ -8,6 +8,7 @@ import ( "github.com/equinix/terraform-provider-equinix/internal/acceptance" "os" "testing" + "time" "github.com/equinix/terraform-provider-equinix/internal/config" @@ -82,7 +83,7 @@ func TestAccFabricCreatePort2SPConnection_PFCR(t *testing.T) { resource.TestCheckResourceAttr( "equinix_fabric_connection.test", "z_side.0.access_point.0.location.0.metro_code", "SV"), ), - ExpectNonEmptyPlan: true, + ExpectNonEmptyPlan: false, }, }, }) @@ -372,10 +373,9 @@ func testAccFabricCreateCloudRouter2PortConnectionConfig(name, portUuid string) func TestAccFabricCreateVirtualDevice2NetworkConnection_PNFV(t *testing.T) { connectionTestData := GetFabricEnvConnectionTestData(t) - var virtualDevice, network string + var virtualDevice string if len(connectionTestData) > 0 { virtualDevice = connectionTestData["pnfv"]["virtualDevice"] - network = connectionTestData["pnfv"]["network"] } resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.TestAccPreCheck(t) }, @@ -383,7 +383,7 @@ func TestAccFabricCreateVirtualDevice2NetworkConnection_PNFV(t *testing.T) { CheckDestroy: CheckConnectionDelete, Steps: []resource.TestStep{ { - Config: testAccFabricCreateVirtualDevice2NetworkConnectionConfig("vd2network_PNFV", virtualDevice, network), + Config: testAccFabricCreateVirtualDevice2NetworkConnectionConfig("vd2network_PNFV", virtualDevice), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr( "equinix_fabric_connection.test", "name", "vd2network_PNFV"), @@ -404,11 +404,13 @@ func TestAccFabricCreateVirtualDevice2NetworkConnection_PNFV(t *testing.T) { resource.TestCheckResourceAttr( "equinix_fabric_connection.test", "a_side.0.access_point.0.interface.0.type", "CLOUD"), resource.TestCheckResourceAttr( - "equinix_fabric_connection.test", "a_side.0.access_point.0.interface.0.id", "7"), + "equinix_fabric_connection.test", "a_side.0.access_point.0.interface.0.id", "6"), + resource.TestCheckResourceAttrSet( + "equinix_fabric_connection.test", "a_side.0.access_point.0.link_protocol.0.vlan_tag"), resource.TestCheckResourceAttr( "equinix_fabric_connection.test", "z_side.0.access_point.0.type", "NETWORK"), - //resource.TestCheckResourceAttr( - // "equinix_fabric_connection.test", "z_side.0.access_point.0.network.0.uuid", connectionTestData["pnfv"]["network"]), + resource.TestCheckResourceAttrSet( + "equinix_fabric_connection.test", "z_side.0.access_point.0.network.0.uuid"), ), ExpectNonEmptyPlan: true, }, @@ -417,9 +419,25 @@ func TestAccFabricCreateVirtualDevice2NetworkConnection_PNFV(t *testing.T) { } -func testAccFabricCreateVirtualDevice2NetworkConnectionConfig(name, virtualDeviceUuid, networkUuid string) string { +func testAccFabricCreateVirtualDevice2NetworkConnectionConfig(name, virtualDeviceUuid string) string { return fmt.Sprintf(` + resource "equinix_fabric_network" "this" { + type = "EVPLAN" + name = "Tf_Network_PNFV" + scope = "REGIONAL" + notifications { + type = "ALL" + emails = ["test@equinix.com","test1@equinix.com"] + } + location { + region = "AMER" + } + project{ + project_id = "4f855852-eb47-4721-8e40-b386a3676abf" + } + } + resource "equinix_fabric_connection" "test" { type = "EVPLAN_VC" name = "%s" @@ -443,7 +461,7 @@ func testAccFabricCreateVirtualDevice2NetworkConnectionConfig(name, virtualDevic } interface { type = "CLOUD" - id = 7 + id = 6 } } } @@ -451,11 +469,11 @@ func testAccFabricCreateVirtualDevice2NetworkConnectionConfig(name, virtualDevic access_point { type = "NETWORK" network { - uuid = "%s" + uuid = equinix_fabric_network.this.id } } } - }`, name, virtualDeviceUuid, networkUuid) + }`, name, virtualDeviceUuid) } func CheckConnectionDelete(s *terraform.State) error { @@ -465,7 +483,7 @@ func CheckConnectionDelete(s *terraform.State) error { if rs.Type != "equinix_fabric_connection" { continue } - err := equinix.WaitUntilConnectionDeprovisioned(rs.Primary.ID, acceptance.TestAccProvider.Meta(), ctx) + err := equinix.WaitUntilConnectionDeprovisioned(rs.Primary.ID, acceptance.TestAccProvider.Meta(), ctx, 10*time.Minute) if err != nil { return fmt.Errorf("API call failed while waiting for resource deletion") } diff --git a/equinix/resource_fabric_network.go b/equinix/resource_fabric_network.go index 0346d08fd..bd46ab48e 100755 --- a/equinix/resource_fabric_network.go +++ b/equinix/resource_fabric_network.go @@ -148,10 +148,10 @@ func fabricNetworkResourceSchema() map[string]*schema.Schema { func resourceFabricNetwork() *schema.Resource { return &schema.Resource{ Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(6 * time.Minute), + Create: schema.DefaultTimeout(10 * time.Minute), Update: schema.DefaultTimeout(10 * time.Minute), - Delete: schema.DefaultTimeout(6 * time.Minute), - Read: schema.DefaultTimeout(6 * time.Minute), + Delete: schema.DefaultTimeout(10 * time.Minute), + Read: schema.DefaultTimeout(10 * time.Minute), }, ReadContext: resourceFabricNetworkRead, CreateContext: resourceFabricNetworkCreate, @@ -187,13 +187,15 @@ func resourceFabricNetworkCreate(ctx context.Context, d *schema.ResourceData, me Project: project, } + start := time.Now() fabricNetwork, _, err := client.NetworksApi.CreateNetwork(ctx, createRequest) if err != nil { return diag.FromErr(equinix_errors.FormatFabricError(err)) } d.SetId(fabricNetwork.Uuid) - if _, err = waitUntilFabricNetworkIsProvisioned(d.Id(), meta, ctx); err != nil { + createTimeout := d.Timeout(schema.TimeoutCreate) - 30*time.Second - time.Since(start) + if _, err = waitUntilFabricNetworkIsProvisioned(d.Id(), meta, ctx, createTimeout); err != nil { return diag.Errorf("error waiting for Network (%s) to be created: %s", d.Id(), err) } @@ -285,7 +287,9 @@ func getFabricNetworkUpdateRequest(network v4.Network, d *schema.ResourceData) ( func resourceFabricNetworkUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { client := meta.(*config.Config).FabricClient ctx = context.WithValue(ctx, v4.ContextAccessToken, meta.(*config.Config).FabricAuthToken) - dbConn, err := waitUntilFabricNetworkIsProvisioned(d.Id(), meta, ctx) + start := time.Now() + updateTimeout := d.Timeout(schema.TimeoutUpdate) - 30*time.Second - time.Since(start) + dbConn, err := waitUntilFabricNetworkIsProvisioned(d.Id(), meta, ctx, updateTimeout) if err != nil { return diag.Errorf("either timed out or errored out while fetching Fabric Network for uuid %s and error %v", d.Id(), err) } @@ -298,8 +302,10 @@ func resourceFabricNetworkUpdate(ctx context.Context, d *schema.ResourceData, me if err != nil { return diag.FromErr(equinix_errors.FormatFabricError(err)) } + updateFg := v4.Network{} - updateFg, err = waitForFabricNetworkUpdateCompletion(d.Id(), meta, ctx) + updateTimeout = d.Timeout(schema.TimeoutUpdate) - 30*time.Second - time.Since(start) + updateFg, err = waitForFabricNetworkUpdateCompletion(d.Id(), meta, ctx, updateTimeout) if err != nil { return diag.Errorf("errored while waiting for successful Fabric Network update, response %v, error %v", res, err) @@ -309,7 +315,7 @@ func resourceFabricNetworkUpdate(ctx context.Context, d *schema.ResourceData, me return setFabricNetworkMap(d, updateFg) } -func waitForFabricNetworkUpdateCompletion(uuid string, meta interface{}, ctx context.Context) (v4.Network, error) { +func waitForFabricNetworkUpdateCompletion(uuid string, meta interface{}, ctx context.Context, timeout time.Duration) (v4.Network, error) { log.Printf("Waiting for Network update to complete, uuid %s", uuid) stateConf := &resource.StateChangeConf{ Target: []string{string(v4.PROVISIONED_NetworkEquinixStatus)}, @@ -321,7 +327,7 @@ func waitForFabricNetworkUpdateCompletion(uuid string, meta interface{}, ctx con } return dbConn, string(*dbConn.Operation.EquinixStatus), nil }, - Timeout: 2 * time.Minute, + Timeout: timeout, Delay: 30 * time.Second, MinTimeout: 30 * time.Second, } @@ -335,7 +341,7 @@ func waitForFabricNetworkUpdateCompletion(uuid string, meta interface{}, ctx con return dbConn, err } -func waitUntilFabricNetworkIsProvisioned(uuid string, meta interface{}, ctx context.Context) (v4.Network, error) { +func waitUntilFabricNetworkIsProvisioned(uuid string, meta interface{}, ctx context.Context, timeout time.Duration) (v4.Network, error) { log.Printf("Waiting for Fabric Network to be provisioned, uuid %s", uuid) stateConf := &resource.StateChangeConf{ Pending: []string{ @@ -352,7 +358,7 @@ func waitUntilFabricNetworkIsProvisioned(uuid string, meta interface{}, ctx cont } return dbConn, string(*dbConn.Operation.EquinixStatus), nil }, - Timeout: 5 * time.Minute, + Timeout: timeout, Delay: 30 * time.Second, MinTimeout: 30 * time.Second, } @@ -370,6 +376,7 @@ func resourceFabricNetworkDelete(ctx context.Context, d *schema.ResourceData, me diags := diag.Diagnostics{} client := meta.(*config.Config).FabricClient ctx = context.WithValue(ctx, v4.ContextAccessToken, meta.(*config.Config).FabricAuthToken) + start := time.Now() _, _, err := client.NetworksApi.DeleteNetworkByUuid(ctx, d.Id()) if err != nil { errors, ok := err.(v4.GenericSwaggerError).Model().([]v4.ModelError) @@ -382,14 +389,15 @@ func resourceFabricNetworkDelete(ctx context.Context, d *schema.ResourceData, me return diag.FromErr(equinix_errors.FormatFabricError(err)) } - err = WaitUntilFabricNetworkDeprovisioned(d.Id(), meta, ctx) + deleteTimeout := d.Timeout(schema.TimeoutDelete) - 30*time.Second - time.Since(start) + err = WaitUntilFabricNetworkDeprovisioned(d.Id(), meta, ctx, deleteTimeout) if err != nil { return diag.Errorf("API call failed while waiting for resource deletion. Error %v", err) } return diags } -func WaitUntilFabricNetworkDeprovisioned(uuid string, meta interface{}, ctx context.Context) error { +func WaitUntilFabricNetworkDeprovisioned(uuid string, meta interface{}, ctx context.Context, timeout time.Duration) error { log.Printf("Waiting for Fabric Network to be deprovisioned, uuid %s", uuid) stateConf := &resource.StateChangeConf{ Pending: []string{ @@ -406,7 +414,7 @@ func WaitUntilFabricNetworkDeprovisioned(uuid string, meta interface{}, ctx cont } return dbConn, string(*dbConn.Operation.EquinixStatus), nil }, - Timeout: 7 * time.Minute, + Timeout: timeout, Delay: 30 * time.Second, MinTimeout: 30 * time.Second, } diff --git a/equinix/resource_fabric_network_acc_test.go b/equinix/resource_fabric_network_acc_test.go index 54466a303..dc444e0c5 100644 --- a/equinix/resource_fabric_network_acc_test.go +++ b/equinix/resource_fabric_network_acc_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "testing" + "time" "github.com/equinix/terraform-provider-equinix/equinix" "github.com/equinix/terraform-provider-equinix/internal/acceptance" @@ -87,7 +88,7 @@ func checkNetworkDelete(s *terraform.State) error { if rs.Type != "equinix_fabric_network" { continue } - err := equinix.WaitUntilFabricNetworkDeprovisioned(rs.Primary.ID, acceptance.TestAccProvider.Meta(), ctx) + err := equinix.WaitUntilFabricNetworkDeprovisioned(rs.Primary.ID, acceptance.TestAccProvider.Meta(), ctx, 10*time.Minute) if err != nil { return fmt.Errorf("API call failed while waiting for resource deletion") } diff --git a/equinix/resource_fabric_routing_protocol.go b/equinix/resource_fabric_routing_protocol.go index 2d7552342..aa5af4bf2 100644 --- a/equinix/resource_fabric_routing_protocol.go +++ b/equinix/resource_fabric_routing_protocol.go @@ -256,10 +256,10 @@ func createFabricRoutingProtocolResourceSchema() map[string]*schema.Schema { func resourceFabricRoutingProtocol() *schema.Resource { return &schema.Resource{ Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(6 * time.Minute), + Create: schema.DefaultTimeout(10 * time.Minute), Update: schema.DefaultTimeout(10 * time.Minute), - Delete: schema.DefaultTimeout(6 * time.Minute), - Read: schema.DefaultTimeout(6 * time.Minute), + Delete: schema.DefaultTimeout(10 * time.Minute), + Read: schema.DefaultTimeout(10 * time.Minute), }, ReadContext: resourceFabricRoutingProtocolRead, CreateContext: resourceFabricRoutingProtocolCreate, @@ -371,6 +371,8 @@ func resourceFabricRoutingProtocolCreate(ctx context.Context, d *schema.Resource createRequest.DirectIpv6 = nil } } + + start := time.Now() fabricRoutingProtocol, _, err := client.RoutingProtocolsApi.CreateConnectionRoutingProtocol(ctx, createRequest, d.Get("connection_uuid").(string)) if err != nil { return diag.FromErr(equinix_errors.FormatFabricError(err)) @@ -383,7 +385,8 @@ func resourceFabricRoutingProtocolCreate(ctx context.Context, d *schema.Resource d.SetId(fabricRoutingProtocol.RoutingProtocolDirectData.Uuid) } - if _, err = waitUntilRoutingProtocolIsProvisioned(d.Id(), d.Get("connection_uuid").(string), meta, ctx); err != nil { + createTimeout := d.Timeout(schema.TimeoutCreate) - 30*time.Second - time.Since(start) + if _, err = waitUntilRoutingProtocolIsProvisioned(d.Id(), d.Get("connection_uuid").(string), meta, ctx, createTimeout); err != nil { return diag.Errorf("error waiting for RP (%s) to be created: %s", d.Id(), err) } @@ -453,6 +456,7 @@ func resourceFabricRoutingProtocolUpdate(ctx context.Context, d *schema.Resource } } + start := time.Now() updatedRpResp, _, err := client.RoutingProtocolsApi.ReplaceConnectionRoutingProtocolByUuid(ctx, updateRequest, d.Id(), d.Get("connection_uuid").(string)) if err != nil { return diag.FromErr(equinix_errors.FormatFabricError(err)) @@ -467,14 +471,16 @@ func resourceFabricRoutingProtocolUpdate(ctx context.Context, d *schema.Resource changeUuid = updatedRpResp.RoutingProtocolDirectData.Change.Uuid d.SetId(updatedRpResp.RoutingProtocolDirectData.Uuid) } - _, err = waitForRoutingProtocolUpdateCompletion(changeUuid, d.Id(), d.Get("connection_uuid").(string), meta, ctx) + updateTimeout := d.Timeout(schema.TimeoutUpdate) - 30*time.Second - time.Since(start) + _, err = waitForRoutingProtocolUpdateCompletion(changeUuid, d.Id(), d.Get("connection_uuid").(string), meta, ctx, updateTimeout) if err != nil { if !strings.Contains(err.Error(), "500") { d.SetId("") } return diag.FromErr(fmt.Errorf("timeout updating routing protocol: %v", err)) } - updatedProvisionedRpResp, err := waitUntilRoutingProtocolIsProvisioned(d.Id(), d.Get("connection_uuid").(string), meta, ctx) + updateTimeout = d.Timeout(schema.TimeoutUpdate) - 30*time.Second - time.Since(start) + updatedProvisionedRpResp, err := waitUntilRoutingProtocolIsProvisioned(d.Id(), d.Get("connection_uuid").(string), meta, ctx, updateTimeout) if err != nil { return diag.Errorf("error waiting for RP (%s) to be replace updated: %s", d.Id(), err) } @@ -486,6 +492,7 @@ func resourceFabricRoutingProtocolDelete(ctx context.Context, d *schema.Resource diags := diag.Diagnostics{} client := meta.(*config.Config).FabricClient ctx = context.WithValue(ctx, v4.ContextAccessToken, meta.(*config.Config).FabricAuthToken) + start := time.Now() _, _, err := client.RoutingProtocolsApi.DeleteConnectionRoutingProtocolByUuid(ctx, d.Id(), d.Get("connection_uuid").(string)) if err != nil { errors, ok := err.(v4.GenericSwaggerError).Model().([]v4.ModelError) @@ -498,7 +505,8 @@ func resourceFabricRoutingProtocolDelete(ctx context.Context, d *schema.Resource return diag.FromErr(equinix_errors.FormatFabricError(err)) } - err = WaitUntilRoutingProtocolIsDeprovisioned(d.Id(), d.Get("connection_uuid").(string), meta, ctx) + deleteTimeout := d.Timeout(schema.TimeoutDelete) - 30*time.Second - time.Since(start) + err = WaitUntilRoutingProtocolIsDeprovisioned(d.Id(), d.Get("connection_uuid").(string), meta, ctx, deleteTimeout) if err != nil { return diag.FromErr(fmt.Errorf("API call failed while waiting for resource deletion. Error %v", err)) } @@ -546,7 +554,7 @@ func setFabricRoutingProtocolMap(d *schema.ResourceData, rp v4.RoutingProtocolDa return diags } -func waitUntilRoutingProtocolIsProvisioned(uuid string, connUuid string, meta interface{}, ctx context.Context) (v4.RoutingProtocolData, error) { +func waitUntilRoutingProtocolIsProvisioned(uuid string, connUuid string, meta interface{}, ctx context.Context, timeout time.Duration) (v4.RoutingProtocolData, error) { log.Printf("Waiting for routing protocol to be provisioned, uuid %s", uuid) stateConf := &retry.StateChangeConf{ Pending: []string{ @@ -570,7 +578,7 @@ func waitUntilRoutingProtocolIsProvisioned(uuid string, connUuid string, meta in } return dbConn, state, nil }, - Timeout: 5 * time.Minute, + Timeout: timeout, Delay: 30 * time.Second, MinTimeout: 30 * time.Second, } @@ -585,7 +593,7 @@ func waitUntilRoutingProtocolIsProvisioned(uuid string, connUuid string, meta in return dbConn, err } -func WaitUntilRoutingProtocolIsDeprovisioned(uuid string, connUuid string, meta interface{}, ctx context.Context) error { +func WaitUntilRoutingProtocolIsDeprovisioned(uuid string, connUuid string, meta interface{}, ctx context.Context, timeout time.Duration) error { log.Printf("Waiting for routing protocol to be deprovisioned, uuid %s", uuid) /* check if resource is not found */ @@ -601,7 +609,7 @@ func WaitUntilRoutingProtocolIsDeprovisioned(uuid string, connUuid string, meta return dbConn, strconv.Itoa(resp.StatusCode), nil }, - Timeout: 5 * time.Minute, + Timeout: timeout, Delay: 30 * time.Second, MinTimeout: 30 * time.Second, } @@ -610,7 +618,7 @@ func WaitUntilRoutingProtocolIsDeprovisioned(uuid string, connUuid string, meta return err } -func waitForRoutingProtocolUpdateCompletion(rpChangeUuid string, uuid string, connUuid string, meta interface{}, ctx context.Context) (v4.RoutingProtocolChangeData, error) { +func waitForRoutingProtocolUpdateCompletion(rpChangeUuid string, uuid string, connUuid string, meta interface{}, ctx context.Context, timeout time.Duration) (v4.RoutingProtocolChangeData, error) { log.Printf("Waiting for routing protocol update to complete, uuid %s", uuid) stateConf := &retry.StateChangeConf{ Target: []string{"COMPLETED"}, @@ -626,7 +634,7 @@ func waitForRoutingProtocolUpdateCompletion(rpChangeUuid string, uuid string, co } return dbConn, updatableState, nil }, - Timeout: 2 * time.Minute, + Timeout: timeout, Delay: 30 * time.Second, MinTimeout: 30 * time.Second, } diff --git a/equinix/resource_fabric_routing_protocol_acc_test.go b/equinix/resource_fabric_routing_protocol_acc_test.go index cb790aec0..94dcab672 100644 --- a/equinix/resource_fabric_routing_protocol_acc_test.go +++ b/equinix/resource_fabric_routing_protocol_acc_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "testing" + "time" "github.com/equinix/terraform-provider-equinix/equinix" "github.com/equinix/terraform-provider-equinix/internal/acceptance" @@ -20,7 +21,7 @@ import ( // The FCR, Connection and RPs will already be created in the resource test, so the // data_source tests will just leverage the RPs there to retrieve the data and check results -func TestAccFabricCreateDirectRoutingProtocol_PFCR_A(t *testing.T) { +func TestAccFabricCreateRoutingProtocols_PFCR(t *testing.T) { ports := GetFabricEnvPorts(t) var portUuid string @@ -202,7 +203,7 @@ func checkRoutingProtocolDelete(s *terraform.State) error { if rs.Type != "equinix_fabric_routing_protocol" { continue } - err := equinix.WaitUntilRoutingProtocolIsDeprovisioned(rs.Primary.ID, rs.Primary.Attributes["connection_uuid"], acceptance.TestAccProvider.Meta(), ctx) + err := equinix.WaitUntilRoutingProtocolIsDeprovisioned(rs.Primary.ID, rs.Primary.Attributes["connection_uuid"], acceptance.TestAccProvider.Meta(), ctx, 10*time.Minute) if err != nil { return fmt.Errorf("API call failed while waiting for resource deletion") } diff --git a/equinix/resource_fabric_service_profile.go b/equinix/resource_fabric_service_profile.go index 171392859..ed5791283 100644 --- a/equinix/resource_fabric_service_profile.go +++ b/equinix/resource_fabric_service_profile.go @@ -525,10 +525,10 @@ func createLinkProtocolConfigSch() map[string]*schema.Schema { func resourceFabricServiceProfile() *schema.Resource { return &schema.Resource{ Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(6 * time.Minute), + Create: schema.DefaultTimeout(10 * time.Minute), Update: schema.DefaultTimeout(10 * time.Minute), - Delete: schema.DefaultTimeout(6 * time.Minute), - Read: schema.DefaultTimeout(6 * time.Minute), + Delete: schema.DefaultTimeout(10 * time.Minute), + Read: schema.DefaultTimeout(10 * time.Minute), }, ReadContext: resourceFabricServiceProfileRead, CreateContext: resourceFabricServiceProfileCreate, @@ -632,9 +632,11 @@ func resourceFabricServiceProfileUpdate(ctx context.Context, d *schema.ResourceD uuid := d.Id() updateRequest := getServiceProfileRequestPayload(d) + start := time.Now() + updateTimeout := d.Timeout(schema.TimeoutUpdate) - 30*time.Second - time.Since(start) var err error var eTag int64 = 0 - _, err, eTag = waitForActiveServiceProfileAndPopulateETag(uuid, meta, ctx) + _, err, eTag = waitForActiveServiceProfileAndPopulateETag(uuid, meta, ctx, updateTimeout) if err != nil { if !strings.Contains(err.Error(), "500") { d.SetId("") @@ -646,8 +648,10 @@ func resourceFabricServiceProfileUpdate(ctx context.Context, d *schema.ResourceD if err != nil { return diag.FromErr(equinix_errors.FormatFabricError(err)) } + + updateTimeout = d.Timeout(schema.TimeoutUpdate) - 30*time.Second - time.Since(start) updatedServiceProfile := v4.ServiceProfile{} - updatedServiceProfile, err = waitForServiceProfileUpdateCompletion(uuid, meta, ctx) + updatedServiceProfile, err = waitForServiceProfileUpdateCompletion(uuid, meta, ctx, updateTimeout) if err != nil { if !strings.Contains(err.Error(), "500") { d.SetId("") @@ -658,7 +662,7 @@ func resourceFabricServiceProfileUpdate(ctx context.Context, d *schema.ResourceD return setFabricServiceProfileMap(d, updatedServiceProfile) } -func waitForServiceProfileUpdateCompletion(uuid string, meta interface{}, ctx context.Context) (v4.ServiceProfile, error) { +func waitForServiceProfileUpdateCompletion(uuid string, meta interface{}, ctx context.Context, timeout time.Duration) (v4.ServiceProfile, error) { log.Printf("Waiting for service profile update to complete, uuid %s", uuid) stateConf := &retry.StateChangeConf{ Target: []string{"COMPLETED"}, @@ -671,7 +675,7 @@ func waitForServiceProfileUpdateCompletion(uuid string, meta interface{}, ctx co updatableState := "COMPLETED" return dbServiceProfile, updatableState, nil }, - Timeout: 1 * time.Minute, + Timeout: timeout, Delay: 10 * time.Second, MinTimeout: 10 * time.Second, } @@ -685,7 +689,7 @@ func waitForServiceProfileUpdateCompletion(uuid string, meta interface{}, ctx co return dbSp, err } -func waitForActiveServiceProfileAndPopulateETag(uuid string, meta interface{}, ctx context.Context) (v4.ServiceProfile, error, int64) { +func waitForActiveServiceProfileAndPopulateETag(uuid string, meta interface{}, ctx context.Context, timeout time.Duration) (v4.ServiceProfile, error, int64) { log.Printf("Waiting for service profile to be in active state, uuid %s", uuid) var eTag int64 = 0 stateConf := &retry.StateChangeConf{ @@ -709,7 +713,7 @@ func waitForActiveServiceProfileAndPopulateETag(uuid string, meta interface{}, c } return dbServiceProfile, updatableState, nil }, - Timeout: 1 * time.Minute, + Timeout: timeout, Delay: 10 * time.Second, MinTimeout: 10 * time.Second, } @@ -729,12 +733,14 @@ func resourceFabricServiceProfileDelete(ctx context.Context, d *schema.ResourceD if uuid == "" { return diag.Errorf("No uuid found for Service Profile Deletion %v ", uuid) } + start := time.Now() _, _, err := client.ServiceProfilesApi.DeleteServiceProfileByUuid(ctx, uuid) if err != nil { return diag.FromErr(equinix_errors.FormatFabricError(err)) } - waitErr := WaitAndCheckServiceProfileDeleted(uuid, client, ctx) + deleteTimeout := d.Timeout(schema.TimeoutDelete) - 30*time.Second - time.Since(start) + waitErr := WaitAndCheckServiceProfileDeleted(uuid, client, ctx, deleteTimeout) if waitErr != nil { return diag.Errorf("Error while waiting for Service Profile deletion: %v", waitErr) } @@ -742,7 +748,7 @@ func resourceFabricServiceProfileDelete(ctx context.Context, d *schema.ResourceD return diags } -func WaitAndCheckServiceProfileDeleted(uuid string, client *v4.APIClient, ctx context.Context) error { +func WaitAndCheckServiceProfileDeleted(uuid string, client *v4.APIClient, ctx context.Context, timeout time.Duration) error { log.Printf("Waiting for service profile to be in deleted, uuid %s", uuid) stateConf := &retry.StateChangeConf{ Target: []string{string(v4.DELETED_ServiceProfileStateEnum)}, @@ -757,7 +763,7 @@ func WaitAndCheckServiceProfileDeleted(uuid string, client *v4.APIClient, ctx co } return dbConn, updatableState, nil }, - Timeout: 1 * time.Minute, + Timeout: timeout, Delay: 10 * time.Second, MinTimeout: 10 * time.Second, } diff --git a/equinix/resource_fabric_service_profile_acc_test.go b/equinix/resource_fabric_service_profile_acc_test.go index f8774de62..f5def517c 100644 --- a/equinix/resource_fabric_service_profile_acc_test.go +++ b/equinix/resource_fabric_service_profile_acc_test.go @@ -7,6 +7,7 @@ import ( "github.com/equinix/terraform-provider-equinix/internal/acceptance" "github.com/equinix/terraform-provider-equinix/internal/config" "testing" + "time" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -160,7 +161,7 @@ func checkServiceProfileDelete(s *terraform.State) error { if rs.Type != "equinix_fabric_service_profile" { continue } - err := equinix.WaitAndCheckServiceProfileDeleted(rs.Primary.ID, client, ctx) + err := equinix.WaitAndCheckServiceProfileDeleted(rs.Primary.ID, client, ctx, 10*time.Minute) if err != nil { return fmt.Errorf("API call failed while waiting for resource deletion: %v", err) } diff --git a/internal/resources/metal/project/models.go b/internal/resources/metal/project/models.go index f38053958..f50de7118 100644 --- a/internal/resources/metal/project/models.go +++ b/internal/resources/metal/project/models.go @@ -105,10 +105,12 @@ func parseBGPConfig(ctx context.Context, bgpConfig *metalv1.BgpConfig) fwtypes.L bgpConfigResourceModel[0] = BGPConfigModel{ DeploymentType: types.StringValue(string(bgpConfig.GetDeploymentType())), ASN: types.Int64Value(int64(bgpConfig.GetAsn())), - MD5: types.StringValue(bgpConfig.GetMd5()), Status: types.StringValue(string(bgpConfig.GetStatus())), MaxPrefix: types.Int64Value(int64(bgpConfig.GetMaxPrefix())), } + if bgpConfig.Md5.Get() != nil { + bgpConfigResourceModel[0].MD5 = types.StringValue(bgpConfig.GetMd5()) + } return fwtypes.NewListNestedObjectValueOfValueSlice[BGPConfigModel](ctx, bgpConfigResourceModel) } return fwtypes.NewListNestedObjectValueOfNull[BGPConfigModel](ctx) diff --git a/internal/resources/metal/project/resource_test.go b/internal/resources/metal/project/resource_test.go index 69e961678..f0a6c26e0 100644 --- a/internal/resources/metal/project/resource_test.go +++ b/internal/resources/metal/project/resource_test.go @@ -132,6 +132,9 @@ func TestAccMetalProject_BGPBasic(t *testing.T) { resource.TestCheckResourceAttr( "equinix_metal_project.foobar", "bgp_config.0.md5", "2SFsdfsg43"), + resource.TestCheckResourceAttr( + "equinix_metal_project.foobar", "bgp_config.0.asn", + "65000"), ), }, { @@ -139,6 +142,17 @@ func TestAccMetalProject_BGPBasic(t *testing.T) { ImportState: true, ImportStateVerify: true, }, + { + Config: testAccMetalProjectConfig_BGPWithoutMD5(rInt), + Check: resource.ComposeTestCheckFunc( + testAccMetalProjectExists("equinix_metal_project.foobar", &project), + resource.TestCheckNoResourceAttr( + "equinix_metal_project.foobar", "bgp_config.0.md5"), + resource.TestCheckResourceAttr( + "equinix_metal_project.foobar", "bgp_config.0.asn", + "65000"), + ), + }, }, }) } @@ -343,6 +357,17 @@ resource "equinix_metal_project" "foobar" { }`, r) } +func testAccMetalProjectConfig_BGPWithoutMD5(r int) string { + return fmt.Sprintf(` +resource "equinix_metal_project" "foobar" { + name = "tfacc-project-%d" + bgp_config { + deployment_type = "local" + asn = 65000 + } +}`, r) +} + func testAccMetalProjectConfig_BGP(r int, pass string) string { return fmt.Sprintf(` resource "equinix_metal_project" "foobar" {