diff --git a/internal/provider/util/retry.go b/internal/provider/util/retry.go index b54a7fee..1f04f235 100644 --- a/internal/provider/util/retry.go +++ b/internal/provider/util/retry.go @@ -23,20 +23,20 @@ func RetryForTooManyRequests[T any]( return result, httpResponse, err } - waitForSeconds := httpResponse.Header.Get("X-Ratelimit-Reset") + waitForSeconds := httpResponse.Header.Get("X-RateLimit-Reset") if waitForSeconds == "" { return result, httpResponse, errors.Join( err, - errors.New("header X-Ratelimit-Reset is missing or contains non valid value"), + errors.New("header X-RateLimit-Reset is missing or contains non valid value"), ) } - rateLimitedFor, _ := strconv.Atoi(httpResponse.Header.Get("X-Ratelimit-Reset")) + rateLimitedFor, _ := strconv.Atoi(httpResponse.Header.Get("X-RateLimit-Reset")) time.Sleep(time.Duration(rateLimitedFor) * time.Second) } return result, httpResponse, errors.Join( err, - errors.New("number of retries exceeded for 429 retries"), + errors.New("number of retries exceeded"), ) } diff --git a/test/mocked/datasources/sensor_group_assignment_test.go b/test/mocked/datasources/sensor_group_assignment_test.go index b234e836..0bbacca7 100644 --- a/test/mocked/datasources/sensor_group_assignment_test.go +++ b/test/mocked/datasources/sensor_group_assignment_test.go @@ -113,6 +113,7 @@ func TestSensorGroupAssignmentDataSourceTooManyRequestsHandling(t *testing.T) { mockOAuth.Mock.Disable() } + func TestSensorGroupAssignmentDataSourceHttpErrorHandling(t *testing.T) { defer gock.Off() mockOAuth := util.MockOAuth() diff --git a/test/mocked/datasources/service_test_group_assignment_test.go b/test/mocked/datasources/service_test_group_assignment_test.go index a0984356..d6556402 100644 --- a/test/mocked/datasources/service_test_group_assignment_test.go +++ b/test/mocked/datasources/service_test_group_assignment_test.go @@ -113,6 +113,7 @@ func TestServiceTestGroupAssignmentDataSourceTooManyRequestsHandling(t *testing. mockOAuth.Mock.Disable() } + func TestServiceTestGroupAssignmentDataSourceHttpErrorHandling(t *testing.T) { defer gock.Off() mockOAuth := util.MockOAuth() diff --git a/test/mocked/resources/service_test.go b/test/mocked/resources/service_test.go index 8b6ea998..b4ee8cf7 100644 --- a/test/mocked/resources/service_test.go +++ b/test/mocked/resources/service_test.go @@ -1,13 +1,17 @@ package resource_test import ( - "github.com/aruba-uxi/terraform-provider-hpeuxi/test/mocked/provider" - "github.com/aruba-uxi/terraform-provider-hpeuxi/test/mocked/util" + "net/http" "regexp" "testing" + "github.com/aruba-uxi/terraform-provider-hpeuxi/test/mocked/provider" + "github.com/aruba-uxi/terraform-provider-hpeuxi/test/mocked/util" + "github.com/stretchr/testify/assert" + "github.com/h2non/gock" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-plugin-testing/tfversion" ) @@ -137,3 +141,128 @@ func TestServiceTestResource(t *testing.T) { mockOAuth.Mock.Disable() } + +func TestServiceTestResourceTooManyRequestsHandling(t *testing.T) { + defer gock.Off() + mockOAuth := util.MockOAuth() + var mockTooManyRequests *gock.Response + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: provider.TestAccProtoV6ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + // we required terraform 1.7.0 and above for the `removed` block + tfversion.RequireAbove(tfversion.Version1_7_0), + }, + Steps: []resource.TestStep{ + // Importing a service_test + { + PreConfig: func() { + mockTooManyRequests = gock.New("https://test.api.capenetworks.com"). + Get("/networking-uxi/v1alpha1/service-tests"). + Reply(http.StatusTooManyRequests). + SetHeaders(util.RateLimitingHeaders) + util.MockGetServiceTest( + "id", + util.GeneratePaginatedResponse( + []map[string]interface{}{ + util.GenerateServiceTestResponseModel("id", ""), + }, + ), + 2, + ) + }, + Config: provider.ProviderConfig + ` + resource "uxi_service_test" "my_service_test" { + name = "name" + } + + import { + to = uxi_service_test.my_service_test + id = "id" + }`, + + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("uxi_service_test.my_service_test", "id", "id"), + func(s *terraform.State) error { + assert.Equal(t, mockTooManyRequests.Mock.Request().Counter, 0) + return nil + }, + ), + }, + // Remove service_test from state + { + Config: provider.ProviderConfig + ` + removed { + from = uxi_service_test.my_service_test + + lifecycle { + destroy = false + } + }`, + }, + }, + }) + + mockOAuth.Mock.Disable() +} + +func TestServiceTestResourceHttpErrorHandling(t *testing.T) { + defer gock.Off() + mockOAuth := util.MockOAuth() + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: provider.TestAccProtoV6ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + // we required terraform 1.7.0 and above for the `removed` block + tfversion.RequireAbove(tfversion.Version1_7_0), + }, + Steps: []resource.TestStep{ + { + PreConfig: func() { + util.MockGetServiceTest( + "id", + util.GeneratePaginatedResponse([]map[string]interface{}{}), + 1, + ) + }, + Config: provider.ProviderConfig + ` + resource "uxi_service_test" "my_service_test" { + name = "name" + } + + import { + to = uxi_service_test.my_service_test + id = "id" + }`, + ExpectError: regexp.MustCompile(`Error: Cannot import non-existent remote object`), + }, + { + PreConfig: func() { + gock.New("https://test.api.capenetworks.com"). + Get("/networking-uxi/v1alpha1/service-tests"). + Reply(http.StatusInternalServerError). + JSON(map[string]interface{}{ + "httpStatusCode": http.StatusInternalServerError, + "errorCode": "HPE_GL_ERROR_INTERNAL_SERVER_ERROR", + "message": "Current request cannot be processed due to unknown issue", + "debugId": "12312-123123-123123-1231212", + }) + }, + Config: provider.ProviderConfig + ` + resource "uxi_service_test" "my_service_test" { + name = "name" + } + + import { + to = uxi_service_test.my_service_test + id = "id" + }`, + ExpectError: regexp.MustCompile( + `(?s)Current request cannot be processed due to unknown issue\s*DebugID: 12312-123123-123123-1231212`, + ), + }, + }, + }) + + mockOAuth.Mock.Disable() +} diff --git a/test/mocked/resources/wired_network_test.go b/test/mocked/resources/wired_network_test.go index d7a6984b..c17d30c3 100644 --- a/test/mocked/resources/wired_network_test.go +++ b/test/mocked/resources/wired_network_test.go @@ -7,9 +7,11 @@ import ( "github.com/aruba-uxi/terraform-provider-hpeuxi/test/mocked/provider" "github.com/aruba-uxi/terraform-provider-hpeuxi/test/mocked/util" + "github.com/stretchr/testify/assert" "github.com/h2non/gock" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-plugin-testing/tfversion" ) @@ -136,6 +138,74 @@ func TestWiredNetworkResource(t *testing.T) { mockOAuth.Mock.Disable() } +func TestWiredNetworkResourceTooManyRequestsHandling(t *testing.T) { + defer gock.Off() + mockOAuth := util.MockOAuth() + var mockTooManyRequests *gock.Response + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: provider.TestAccProtoV6ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + // we required terraform 1.7.0 and above for the `removed` block + tfversion.RequireAbove(tfversion.Version1_7_0), + }, + Steps: []resource.TestStep{ + // Importing a service_test + { + PreConfig: func() { + mockTooManyRequests = gock.New("https://test.api.capenetworks.com"). + Get("/networking-uxi/v1alpha1/wired-networks"). + Reply(http.StatusTooManyRequests). + SetHeaders(util.RateLimitingHeaders) + util.MockGetWiredNetwork( + "id", + util.GeneratePaginatedResponse( + []map[string]interface{}{ + util.GenerateWiredNetworkResponse("id", ""), + }, + ), + 2, + ) + }, + Config: provider.ProviderConfig + ` + resource "uxi_wired_network" "my_wired_network" { + name = "name" + } + + import { + to = uxi_wired_network.my_wired_network + id = "id" + }`, + + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr( + "uxi_wired_network.my_wired_network", + "id", + "id", + ), + func(s *terraform.State) error { + assert.Equal(t, mockTooManyRequests.Mock.Request().Counter, 0) + return nil + }, + ), + }, + // Remove service_test from state + { + Config: provider.ProviderConfig + ` + removed { + from = uxi_wired_network.my_wired_network + + lifecycle { + destroy = false + } + }`, + }, + }, + }) + + mockOAuth.Mock.Disable() +} + func TestWiredNetworkResourceHttpErrorHandling(t *testing.T) { defer gock.Off() mockOAuth := util.MockOAuth() diff --git a/test/mocked/resources/wireless_network_test.go b/test/mocked/resources/wireless_network_test.go index eefee9a8..c85e5a6d 100644 --- a/test/mocked/resources/wireless_network_test.go +++ b/test/mocked/resources/wireless_network_test.go @@ -7,9 +7,11 @@ import ( "github.com/aruba-uxi/terraform-provider-hpeuxi/test/mocked/provider" "github.com/aruba-uxi/terraform-provider-hpeuxi/test/mocked/util" + "github.com/stretchr/testify/assert" "github.com/h2non/gock" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-plugin-testing/tfversion" ) @@ -155,6 +157,74 @@ func TestWirelessNetworkResource(t *testing.T) { mockOAuth.Mock.Disable() } +func TestWirelessNetworkResourceTooManyRequestsHandling(t *testing.T) { + defer gock.Off() + mockOAuth := util.MockOAuth() + var mockTooManyRequests *gock.Response + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: provider.TestAccProtoV6ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + // we required terraform 1.7.0 and above for the `removed` block + tfversion.RequireAbove(tfversion.Version1_7_0), + }, + Steps: []resource.TestStep{ + // Importing a service_test + { + PreConfig: func() { + mockTooManyRequests = gock.New("https://test.api.capenetworks.com"). + Get("/networking-uxi/v1alpha1/wireless-networks"). + Reply(http.StatusTooManyRequests). + SetHeaders(util.RateLimitingHeaders) + util.MockGetWirelessNetwork( + "id", + util.GeneratePaginatedResponse( + []map[string]interface{}{ + util.GenerateWirelessNetworkResponse("id", ""), + }, + ), + 2, + ) + }, + Config: provider.ProviderConfig + ` + resource "uxi_wireless_network" "my_wireless_network" { + name = "name" + } + + import { + to = uxi_wireless_network.my_wireless_network + id = "id" + }`, + + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr( + "uxi_wireless_network.my_wireless_network", + "id", + "id", + ), + func(s *terraform.State) error { + assert.Equal(t, mockTooManyRequests.Mock.Request().Counter, 0) + return nil + }, + ), + }, + // Remove service_test from state + { + Config: provider.ProviderConfig + ` + removed { + from = uxi_wireless_network.my_wireless_network + + lifecycle { + destroy = false + } + }`, + }, + }, + }) + + mockOAuth.Mock.Disable() +} + func TestWirelessNetworkResourceHttpErrorHandling(t *testing.T) { defer gock.Off() mockOAuth := util.MockOAuth() diff --git a/test/mocked/util/utils.go b/test/mocked/util/utils.go index ad23d7a0..588563e4 100644 --- a/test/mocked/util/utils.go +++ b/test/mocked/util/utils.go @@ -490,5 +490,5 @@ func MockDeleteServiceTestGroupAssignment(id string, times int) { var RateLimitingHeaders = map[string]string{ "X-RateLimit-Limit": "100", "X-RateLimit-Remaining": "0", - "X-RateLimit-Reset": "1", + "X-RateLimit-Reset": "0.01", }