From e949259dddea030d1eb2035058fdeb5e3c33cb82 Mon Sep 17 00:00:00 2001 From: Ayush Rangwala Date: Thu, 24 Aug 2023 18:49:13 +0530 Subject: [PATCH] Timeouts tests to be unit test to be able to run without TF_ACC --- equinix/resource_metal_device.go | 6 +- equinix/resource_metal_device_acc_test.go | 121 +++++++++------------- equinix/resource_network_bgp_test.go | 15 --- 3 files changed, 54 insertions(+), 88 deletions(-) diff --git a/equinix/resource_metal_device.go b/equinix/resource_metal_device.go index a9953e5ed..e104334da 100644 --- a/equinix/resource_metal_device.go +++ b/equinix/resource_metal_device.go @@ -597,7 +597,7 @@ func resourceMetalDeviceCreate(ctx context.Context, d *schema.ResourceData, meta d.SetId(newDevice.ID) - createTimeout := d.Timeout(schema.TimeoutCreate) - time.Minute - time.Since(start) + createTimeout := d.Timeout(schema.TimeoutCreate) - 30*time.Second - time.Since(start) if err = waitForActiveDevice(ctx, d, meta, createTimeout); err != nil { return err } @@ -806,7 +806,7 @@ func doReinstall(ctx context.Context, client *packngo.Client, d *schema.Resource return friendlyError(err) } - deleteTimeout := d.Timeout(schema.TimeoutUpdate) - time.Minute - time.Since(start) + deleteTimeout := d.Timeout(schema.TimeoutUpdate) - 30*time.Second - time.Since(start) if err := waitForActiveDevice(ctx, d, meta, deleteTimeout); err != nil { return err } @@ -837,7 +837,7 @@ func resourceMetalDeviceDelete(ctx context.Context, d *schema.ResourceData, meta wfrd, wfrdOK := d.GetOk("wait_for_reservation_deprovision") if wfrdOK && wfrd.(bool) { // avoid "context: deadline exceeded" - timeout := d.Timeout(schema.TimeoutDelete) - time.Minute - time.Since(start) + timeout := d.Timeout(schema.TimeoutDelete) - 30*time.Second - time.Since(start) err := waitUntilReservationProvisionable(ctx, client, resId.(string), d.Id(), 10*time.Second, timeout, 3*time.Second) if err != nil { diff --git a/equinix/resource_metal_device_acc_test.go b/equinix/resource_metal_device_acc_test.go index 9404dbfc2..78963c061 100644 --- a/equinix/resource_metal_device_acc_test.go +++ b/equinix/resource_metal_device_acc_test.go @@ -2,7 +2,6 @@ package equinix import ( "context" - "errors" "fmt" "log" "net" @@ -12,7 +11,6 @@ import ( "testing" "time" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -559,23 +557,6 @@ func testAccMetalDeviceExists(n string, device *packngo.Device) resource.TestChe } } -func testAccWaitForMetalDeviceActive(n string) resource.TestCheckFunc { - return func(s *terraform.State) error { - defaultTimeout := 20 * time.Minute - - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s", n) - } - if rs.Primary.ID == "" { - return fmt.Errorf("No Record ID is set") - } - rd := new(schema.ResourceData) - rd.SetId(rs.Primary.ID) - return waitForActiveDevice(context.Background(), rd, testAccProvider.Meta(), defaultTimeout) - } -} - func testAccMetalSameDevice(t *testing.T, before, after *packngo.Device) resource.TestCheckFunc { return func(s *terraform.State) error { if before.ID != after.ID { @@ -949,6 +930,7 @@ resource "equinix_metal_device" "test" { operating_system = "ubuntu_20_04" project_id = "${equinix_metal_project.test.id}" termination_time = "%s" + depends_on = [equinix_metal_project.test] timeouts { create = "10s" @@ -1151,68 +1133,67 @@ func TestAccMetalDevice_readErrorHandling(t *testing.T) { } } -func TestAccMetalDevice_timeouts(t *testing.T) { - d1 := &packngo.Device{ - State: "active", - } - projSuffix := acctest.RandString(10) +func testAccWaitForMetalDeviceActive(project, deviceHostName string) resource.ImportStateIdFunc { + return func(state *terraform.State) (string, error) { + defaultTimeout := 20 * time.Minute - mockMetalDeviceService := &mockDeviceService{ - CreateFn: func(device *packngo.DeviceCreateRequest) (*packngo.Device, *packngo.Response, error) { - return d1, &packngo.Response{Response: &http.Response{Status: matchErrDeviceReadyTimeout.String(), StatusCode: 500}}, - errors.New(matchErrDeviceReadyTimeout.String()) - }, - GetFn: func(deviceID string, opts *packngo.GetOptions) (*packngo.Device, *packngo.Response, error) { - return d1, &packngo.Response{Response: &http.Response{Status: "Success", StatusCode: 200}}, nil - }, - } - mockMetalProjectService := &mockProjectService{ - GetFn: func(projectID string, opts *packngo.GetOptions) (*packngo.Project, *packngo.Response, error) { - project := &packngo.Project{ID: "test"} - httpResp := &http.Response{Status: "Success", StatusCode: 200} - return project, &packngo.Response{Response: httpResp}, nil - }, - CreateFn: func(pcr *packngo.ProjectCreateRequest) (*packngo.Project, *packngo.Response, error) { - project := &packngo.Project{ID: "test"} - httpResp := &http.Response{Status: "Success", StatusCode: 200} - return project, &packngo.Response{Response: httpResp}, nil - }, - DeleteFn: func(projectID string) (*packngo.Response, error) { - httpResp := &http.Response{Status: "Success", StatusCode: 200} - return &packngo.Response{Response: httpResp}, nil - }, - } - mockBgpsvc := &mockBgpConfigService{ - GetFn: func(projectID string, getOpt *packngo.GetOptions) (*packngo.BGPConfig, *packngo.Response, error) { - return nil, nil, nil - }, - } + rs, ok := state.RootModule().Resources[project] + if !ok { + return "", fmt.Errorf("Project Not found in the state: %s", project) + } + if rs.Primary.ID == "" { + return "", fmt.Errorf("No Record ID is set") + } - mockEquinix := Provider() - mockEquinix.ConfigureContextFunc = func(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) { - config := Config{ - metal: &packngo.Client{ - Devices: mockMetalDeviceService, - Projects: mockMetalProjectService, - BGPConfig: mockBgpsvc, - }, + meta := testAccProvider.Meta() + rd := new(schema.ResourceData) + meta.(*Config).addModuleToMetalUserAgent(rd) + client := meta.(*Config).metal + devices, _, err := client.Devices.List(rs.Primary.ID, &packngo.ListOptions{Search: deviceHostName}) + if err != nil { + return "", fmt.Errorf("error while fetching devices for project [%s], error: %w", rs.Primary.ID, err) + } + if len(devices) == 0 { + return "", fmt.Errorf("Not able to find devices in project [%s]", rs.Primary.ID) + } + if len(devices) > 1 { + return "", fmt.Errorf("Found more than one device with the hostname in project [%s]", rs.Primary.ID) } - return &config, nil - } - mockProviders := map[string]func() (*schema.Provider, error){ - "equinix": func() (*schema.Provider, error) { - return mockEquinix, nil - }, + rd.SetId(devices[0].ID) + return devices[0].ID, waitForActiveDevice(context.Background(), rd, testAccProvider.Meta(), defaultTimeout) } +} + +func TestAccMetalDevice_importBasicTimeout(t *testing.T) { + rs := acctest.RandString(10) + r := "equinix_metal_device.test" + hostname := "tfacc-test-device" + project := "equinix_metal_project.test" + resource.ParallelTest(t, resource.TestCase{ - ProviderFactories: mockProviders, + PreCheck: func() { testAccPreCheck(t) }, ExternalProviders: testExternalProviders, + ProviderFactories: testAccProviderFactories, + CheckDestroy: testAccMetalDeviceCheckDestroyed, Steps: []resource.TestStep{ { - Config: testAccMetalDeviceConfig_timeout(projSuffix), + Config: testAccMetalDeviceConfig_timeout(rs), ExpectError: matchErrDeviceReadyTimeout, }, + { + /** + Step 1 errors out, state doesnt have device, need to import that in the state before deleting + */ + ResourceName: r, + ImportState: true, + ImportStateIdFunc: testAccWaitForMetalDeviceActive(project, hostname), + ImportStatePersist: true, + }, + { + Config: testAccMetalDeviceConfig_timeout(rs), + Destroy: true, + }, }, }) } diff --git a/equinix/resource_network_bgp_test.go b/equinix/resource_network_bgp_test.go index f40bafb6b..b4131f3c1 100644 --- a/equinix/resource_network_bgp_test.go +++ b/equinix/resource_network_bgp_test.go @@ -2,7 +2,6 @@ package equinix import ( "context" - "github.com/packethost/packngo" "testing" "time" @@ -101,20 +100,6 @@ func (r *mockedBGPUpdateRequest) Execute() error { return nil } -var _ packngo.BGPConfigService = &mockBgpConfigService{} - -type mockBgpConfigService struct { - GetFn func(projectID string, getOpt *packngo.GetOptions) (*packngo.BGPConfig, *packngo.Response, error) - CreateFn func(projectID string, request packngo.CreateBGPConfigRequest) (*packngo.Response, error) -} - -func (s *mockBgpConfigService) Get(projectID string, getOpt *packngo.GetOptions) (*packngo.BGPConfig, *packngo.Response, error) { - return s.GetFn(projectID, getOpt) -} -func (s *mockBgpConfigService) Create(projectID string, request packngo.CreateBGPConfigRequest) (*packngo.Response, error) { - return s.CreateFn(projectID, request) -} - func TestNetworkBGP_createUpdateRequest(t *testing.T) { // given req := &mockedBGPUpdateRequest{data: make(map[string]interface{})}