diff --git a/.changelog/19722.txt b/.changelog/19722.txt new file mode 100644 index 00000000000..c92a5a36e58 --- /dev/null +++ b/.changelog/19722.txt @@ -0,0 +1,7 @@ +```release-note:bug +data-source/aws_servicequotas_service_quota: Correctly handle errors embedded in API struct +``` + +```release-note:bug +resource/aws_servicequotas_service_quota: Correctly handle errors embedded in API struct +``` diff --git a/aws/data_source_aws_servicequotas_service_quota.go b/aws/data_source_aws_servicequotas_service_quota.go index eb621f04b31..6f8b011e3c3 100644 --- a/aws/data_source_aws_servicequotas_service_quota.go +++ b/aws/data_source_aws_servicequotas_service_quota.go @@ -105,13 +105,21 @@ func dataSourceAwsServiceQuotasServiceQuotaRead(d *schema.ResourceData, meta int return fmt.Errorf("error getting Service (%s) Quota (%s): %w", serviceCode, quotaCode, err) } - if output == nil { + if output == nil || output.Quota == nil { return fmt.Errorf("error getting Service (%s) Quota (%s): empty result", serviceCode, quotaCode) } serviceQuota = output.Quota } + if serviceQuota.ErrorReason != nil { + return fmt.Errorf("error getting Service (%s) Quota (%s): %s: %s", serviceCode, quotaCode, aws.StringValue(serviceQuota.ErrorReason.ErrorCode), aws.StringValue(serviceQuota.ErrorReason.ErrorMessage)) + } + + if serviceQuota.Value == nil { + return fmt.Errorf("error getting Service (%s) Quota (%s): empty value", serviceCode, quotaCode) + } + input := &servicequotas.GetAWSDefaultServiceQuotaInput{ QuotaCode: serviceQuota.QuotaCode, ServiceCode: serviceQuota.ServiceCode, diff --git a/aws/data_source_aws_servicequotas_service_quota_test.go b/aws/data_source_aws_servicequotas_service_quota_test.go index d1fa2ad2d21..ece9f2ee619 100644 --- a/aws/data_source_aws_servicequotas_service_quota_test.go +++ b/aws/data_source_aws_servicequotas_service_quota_test.go @@ -35,6 +35,21 @@ func TestAccAwsServiceQuotasServiceQuotaDataSource_QuotaCode(t *testing.T) { }) } +func TestAccAwsServiceQuotasServiceQuotaDataSource_PermissionError_QuotaCode(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSServiceQuotas(t); testAccAssumeRoleARNPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, servicequotas.EndpointsID), + Providers: testAccProviders, + CheckDestroy: nil, + Steps: []resource.TestStep{ + { + Config: testAccAwsServiceQuotasServiceQuotaDataSourceConfig_PermissionError_QuotaCode("elasticloadbalancing", "L-53DA6B97"), + ExpectError: regexp.MustCompile(`DEPENDENCY_ACCESS_DENIED_ERROR`), + }, + }, + }) +} + func TestAccAwsServiceQuotasServiceQuotaDataSource_QuotaName(t *testing.T) { dataSourceName := "data.aws_servicequotas_service_quota.test" @@ -61,6 +76,21 @@ func TestAccAwsServiceQuotasServiceQuotaDataSource_QuotaName(t *testing.T) { }) } +func TestAccAwsServiceQuotasServiceQuotaDataSource_PermissionError_QuotaName(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSServiceQuotas(t); testAccAssumeRoleARNPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, servicequotas.EndpointsID), + Providers: testAccProviders, + CheckDestroy: nil, + Steps: []resource.TestStep{ + { + Config: testAccAwsServiceQuotasServiceQuotaDataSourceConfig_PermissionError_QuotaName("elasticloadbalancing", "Application Load Balancers per Region"), + ExpectError: regexp.MustCompile(`DEPENDENCY_ACCESS_DENIED_ERROR`), + }, + }, + }) +} + func testAccAwsServiceQuotasServiceQuotaDataSourceConfigQuotaCode(serviceCode, quotaCode string) string { return fmt.Sprintf(` data "aws_servicequotas_service_quota" "test" { @@ -70,6 +100,37 @@ data "aws_servicequotas_service_quota" "test" { `, quotaCode, serviceCode) } +func testAccAwsServiceQuotasServiceQuotaDataSourceConfig_PermissionError_QuotaCode(serviceCode, quotaCode string) string { + policy := `{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "servicequotas:GetServiceQuota" + ], + "Resource": "*" + }, + { + "Effect": "Deny", + "Action": [ + "elasticloadbalancing:*" + ], + "Resource": "*" + } + ] +}` + + return composeConfig( + testAccProviderConfigAssumeRolePolicy(policy), + fmt.Sprintf(` +data "aws_servicequotas_service_quota" "test" { + service_code = %[1]q + quota_code = %[2]q +} +`, serviceCode, quotaCode)) +} + func testAccAwsServiceQuotasServiceQuotaDataSourceConfigQuotaName(serviceCode, quotaName string) string { return fmt.Sprintf(` data "aws_servicequotas_service_quota" "test" { @@ -78,3 +139,34 @@ data "aws_servicequotas_service_quota" "test" { } `, quotaName, serviceCode) } + +func testAccAwsServiceQuotasServiceQuotaDataSourceConfig_PermissionError_QuotaName(serviceCode, quotaName string) string { + policy := `{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "servicequotas:ListServiceQuotas" + ], + "Resource": "*" + }, + { + "Effect": "Deny", + "Action": [ + "elasticloadbalancing:*" + ], + "Resource": "*" + } + ] +}` + + return composeConfig( + testAccProviderConfigAssumeRolePolicy(policy), + fmt.Sprintf(` +data "aws_servicequotas_service_quota" "test" { + service_code = %[1]q + quota_name = %[2]q +} +`, serviceCode, quotaName)) +} diff --git a/aws/resource_aws_servicequotas_service_quota.go b/aws/resource_aws_servicequotas_service_quota.go index bc9ed142a7d..9a5f181c032 100644 --- a/aws/resource_aws_servicequotas_service_quota.go +++ b/aws/resource_aws_servicequotas_service_quota.go @@ -99,10 +99,18 @@ func resourceAwsServiceQuotasServiceQuotaCreate(d *schema.ResourceData, meta int return fmt.Errorf("error getting Service Quotas Service Quota (%s): %s", d.Id(), err) } - if output == nil { + if output == nil || output.Quota == nil { return fmt.Errorf("error getting Service Quotas Service Quota (%s): empty result", d.Id()) } + if output.Quota.ErrorReason != nil { + return fmt.Errorf("error getting Service Quotas Service Quota (%s): %s: %s", d.Id(), aws.StringValue(output.Quota.ErrorReason.ErrorCode), aws.StringValue(output.Quota.ErrorReason.ErrorMessage)) + } + + if output.Quota.Value == nil { + return fmt.Errorf("error getting Service Quotas Service Quota (%s): empty value", d.Id()) + } + if value > aws.Float64Value(output.Quota.Value) { input := &servicequotas.RequestServiceQuotaIncreaseInput{ DesiredValue: aws.Float64(value), @@ -152,10 +160,18 @@ func resourceAwsServiceQuotasServiceQuotaRead(d *schema.ResourceData, meta inter return fmt.Errorf("error getting Service Quotas Service Quota (%s): %s", d.Id(), err) } - if output == nil { + if output == nil || output.Quota == nil { return fmt.Errorf("error getting Service Quotas Service Quota (%s): empty result", d.Id()) } + if output.Quota.ErrorReason != nil { + return fmt.Errorf("error getting Service Quotas Service Quota (%s): %s: %s", d.Id(), aws.StringValue(output.Quota.ErrorReason.ErrorCode), aws.StringValue(output.Quota.ErrorReason.ErrorMessage)) + } + + if output.Quota.Value == nil { + return fmt.Errorf("error getting Service Quotas Service Quota (%s): empty value", d.Id()) + } + defaultInput := &servicequotas.GetAWSDefaultServiceQuotaInput{ QuotaCode: aws.String(quotaCode), ServiceCode: aws.String(serviceCode), diff --git a/aws/resource_aws_servicequotas_service_quota_test.go b/aws/resource_aws_servicequotas_service_quota_test.go index e0737b3cc9e..ba9c1e0c149 100644 --- a/aws/resource_aws_servicequotas_service_quota_test.go +++ b/aws/resource_aws_servicequotas_service_quota_test.go @@ -3,6 +3,7 @@ package aws import ( "fmt" "os" + "regexp" "testing" "github.com/aws/aws-sdk-go/service/servicequotas" @@ -138,6 +139,21 @@ func TestAccAwsServiceQuotasServiceQuota_Value_IncreaseOnUpdate(t *testing.T) { }) } +func TestAccAwsServiceQuotasServiceQuota_PermissionError(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSServiceQuotas(t); testAccAssumeRoleARNPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, servicequotas.EndpointsID), + Providers: testAccProviders, + CheckDestroy: nil, + Steps: []resource.TestStep{ + { + Config: testAccAwsServiceQuotasServiceQuotaConfig_PermissionError("elasticloadbalancing", "L-53DA6B97"), + ExpectError: regexp.MustCompile(`DEPENDENCY_ACCESS_DENIED_ERROR`), + }, + }, + }) +} + func testAccPreCheckAWSServiceQuotas(t *testing.T) { conn := testAccProvider.Meta().(*AWSClient).servicequotasconn @@ -178,3 +194,35 @@ resource "aws_servicequotas_service_quota" "test" { } `, quotaCode, serviceCode, value) } + +func testAccAwsServiceQuotasServiceQuotaConfig_PermissionError(serviceCode, quotaCode string) string { + policy := `{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "servicequotas:GetServiceQuota" + ], + "Resource": "*" + }, + { + "Effect": "Deny", + "Action": [ + "elasticloadbalancing:*" + ], + "Resource": "*" + } + ] +}` + + return composeConfig( + testAccProviderConfigAssumeRolePolicy(policy), + fmt.Sprintf(` +resource "aws_servicequotas_service_quota" "test" { + service_code = %[1]q + quota_code = %[2]q + value = 1 +} +`, serviceCode, quotaCode)) +}