From cd508287a0ad22445a5c877e865c378f227f2535 Mon Sep 17 00:00:00 2001 From: Tomer Heber Date: Sun, 29 May 2022 09:44:09 -0500 Subject: [PATCH] Chore: refactor credentials and cost (#395) * Chore: refactor credentials and cost * fix unit tests --- env0/credentials.go | 20 +++- env0/data_aws_credentials.go | 98 ----------------- env0/data_aws_credentials_test.go | 112 ------------------- env0/data_azure_credentials.go | 94 ---------------- env0/data_azure_credentials_test.go | 98 ----------------- env0/data_credentials.go | 63 +++++++++++ env0/data_credentials_test.go | 138 ++++++++++++++++++++++++ env0/data_gcp_credentials.go | 94 ---------------- env0/data_gcp_credentials_test.go | 98 ----------------- env0/provider.go | 6 +- env0/resource_aws_credentials_test.go | 2 +- env0/resource_azure_credentials_test.go | 2 +- env0/resource_gcp_credentials_test.go | 2 +- 13 files changed, 226 insertions(+), 601 deletions(-) delete mode 100644 env0/data_aws_credentials.go delete mode 100644 env0/data_aws_credentials_test.go delete mode 100644 env0/data_azure_credentials.go delete mode 100644 env0/data_azure_credentials_test.go create mode 100644 env0/data_credentials.go create mode 100644 env0/data_credentials_test.go delete mode 100644 env0/data_gcp_credentials.go delete mode 100644 env0/data_gcp_credentials_test.go diff --git a/env0/credentials.go b/env0/credentials.go index 19d5bad1..c582c24d 100644 --- a/env0/credentials.go +++ b/env0/credentials.go @@ -1,6 +1,7 @@ package env0 import ( + "errors" "fmt" "log" "strings" @@ -35,11 +36,28 @@ func getCredentialsByName(name string, prefix string, meta interface{}) (client. return foundCredentials[0], nil } +func getCredentialsById(id string, prefix string, meta interface{}) (client.Credentials, error) { + apiClient := meta.(client.ApiClientInterface) + credentials, err := apiClient.CloudCredentials(id) + if err != nil { + if _, ok := err.(*client.NotFoundError); ok { + return client.Credentials{}, errors.New("credentials not found") + } + return client.Credentials{}, err + } + + if !strings.HasPrefix(credentials.Type, prefix) { + return client.Credentials{}, fmt.Errorf("credentials type mistmatch %s", credentials.Type) + } + + return credentials, nil +} + func getCredentials(id string, prefix string, meta interface{}) (client.Credentials, error) { _, err := uuid.Parse(id) if err == nil { log.Println("[INFO] Resolving credentials by id: ", id) - return meta.(client.ApiClientInterface).CloudCredentials(id) + return getCredentialsById(id, prefix, meta) } else { log.Println("[INFO] Resolving credentials by name: ", id) return getCredentialsByName(id, prefix, meta) diff --git a/env0/data_aws_credentials.go b/env0/data_aws_credentials.go deleted file mode 100644 index 9a025c3a..00000000 --- a/env0/data_aws_credentials.go +++ /dev/null @@ -1,98 +0,0 @@ -package env0 - -import ( - "context" - - "github.com/env0/terraform-provider-env0/client" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" -) - -func dataAwsCredentials() *schema.Resource { - return &schema.Resource{ - ReadContext: dataAwsCredentialsRead, - - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Description: "the name of the credential", - Optional: true, - ExactlyOneOf: []string{"name", "id"}, - }, - "id": { - Type: schema.TypeString, - Description: "the id of the credential", - Optional: true, - ExactlyOneOf: []string{"name", "id"}, - }, - }, - } -} - -func dataAwsCredentialsRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - var err diag.Diagnostics - var credentials client.Credentials - - id, ok := d.GetOk("id") - if ok { - credentials, err = getAwsCredentialsById(id.(string), meta) - if err != nil { - return err - } - } else { - name, ok := d.GetOk("name") - if !ok { - return diag.Errorf("Either 'name' or 'id' must be specified") - } - credentials, err = getAwsCredentialsByName(name.(string), meta) - if err != nil { - return err - } - } - - if err := writeResourceData(&credentials, d); err != nil { - return diag.Errorf("schema resource data serialization failed: %v", err) - } - - return nil -} - -func getAwsCredentialsByName(name interface{}, meta interface{}) (client.Credentials, diag.Diagnostics) { - apiClient := meta.(client.ApiClientInterface) - credentialsList, err := apiClient.CloudCredentialsList() - if err != nil { - return client.Credentials{}, diag.Errorf("Could not query AWS Credentials by name: %v", err) - } - - credentialsByNameAndType := make([]client.Credentials, 0) - for _, candidate := range credentialsList { - if candidate.Name == name.(string) && isValidAwsCredentialsType(candidate.Type) { - credentialsByNameAndType = append(credentialsByNameAndType, candidate) - } - } - - if len(credentialsByNameAndType) > 1 { - return client.Credentials{}, diag.Errorf("Found multiple AWS Credentials for name: %s", name) - } - if len(credentialsByNameAndType) == 0 { - return client.Credentials{}, diag.Errorf("Could not find AWS Credentials with name: %s", name) - } - return credentialsByNameAndType[0], nil -} - -func getAwsCredentialsById(id string, meta interface{}) (client.Credentials, diag.Diagnostics) { - apiClient := meta.(client.ApiClientInterface) - credentials, err := apiClient.CloudCredentials(id) - if !isValidAwsCredentialsType(credentials.Type) { - return client.Credentials{}, diag.Errorf("Found credentials which are not AWS Credentials: %v", credentials) - } - if err != nil { - return client.Credentials{}, diag.Errorf("Could not query AWS Credentials: %v", err) - } - return credentials, nil -} - -func isValidAwsCredentialsType(credentialsType string) bool { - return client.AwsCredentialsType(credentialsType) == client.AwsAccessKeysCredentialsType || - client.AwsCredentialsType(credentialsType) == client.AwsAssumedRoleCredentialsType -} diff --git a/env0/data_aws_credentials_test.go b/env0/data_aws_credentials_test.go deleted file mode 100644 index 28c26404..00000000 --- a/env0/data_aws_credentials_test.go +++ /dev/null @@ -1,112 +0,0 @@ -package env0 - -import ( - "regexp" - "testing" - - "github.com/env0/terraform-provider-env0/client" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" -) - -func TestAwsCredDataSource(t *testing.T) { - awsCred := client.Credentials{ - Id: "11111", - Name: "testdata", - OrganizationId: "id", - Type: "AWS_ASSUMED_ROLE_FOR_DEPLOYMENT", - } - - credWithInvalidType := client.Credentials{ - Id: awsCred.Id, - Name: awsCred.Name, - OrganizationId: awsCred.OrganizationId, - Type: "Invalid-type", - } - - otherAwsCred := client.Credentials{ - Id: "22222", - Name: "notTestdata", - OrganizationId: "OtherId", - Type: "AWS_ACCESS_KEYS_FOR_DEPLOYMENT", - } - - AwsCredFieldsByName := map[string]interface{}{"name": awsCred.Name} - AwsCredFieldsById := map[string]interface{}{"id": awsCred.Id} - - resourceType := "env0_aws_credentials" - resourceName := "testdata" - accessor := dataSourceAccessor(resourceType, resourceName) - - getValidTestCase := func(input map[string]interface{}) resource.TestCase { - return resource.TestCase{ - Steps: []resource.TestStep{ - { - Config: dataSourceConfigCreate(resourceType, resourceName, input), - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(accessor, "id", awsCred.Id), - resource.TestCheckResourceAttr(accessor, "name", awsCred.Name), - ), - }, - }, - } - } - - getErrorTestCase := func(input map[string]interface{}, expectedError string) resource.TestCase { - return resource.TestCase{ - Steps: []resource.TestStep{ - { - Config: dataSourceConfigCreate(resourceType, resourceName, input), - ExpectError: regexp.MustCompile(expectedError), - }, - }, - } - } - - mockGetAwsCredCall := func(returnValue client.Credentials) func(mockFunc *client.MockApiClientInterface) { - return func(mock *client.MockApiClientInterface) { - mock.EXPECT().CloudCredentials(awsCred.Id).AnyTimes().Return(returnValue, nil) - } - } - - mockListAwsCredCall := func(returnValue []client.Credentials) func(mockFunc *client.MockApiClientInterface) { - return func(mock *client.MockApiClientInterface) { - mock.EXPECT().CloudCredentialsList().AnyTimes().Return(returnValue, nil) - } - } - - t.Run("By ID", func(t *testing.T) { - runUnitTest(t, - getValidTestCase(AwsCredFieldsById), - mockGetAwsCredCall(awsCred), - ) - }) - - t.Run("By Name", func(t *testing.T) { - runUnitTest(t, - getValidTestCase(AwsCredFieldsByName), - mockListAwsCredCall([]client.Credentials{awsCred, otherAwsCred, credWithInvalidType}), - ) - }) - - t.Run("Throw error when no name or id is supplied", func(t *testing.T) { - runUnitTest(t, - getErrorTestCase(map[string]interface{}{}, "one of `id,name` must be specified"), - func(mock *client.MockApiClientInterface) {}, - ) - }) - - t.Run("Throw error when by name and more than one aws-credential exists with the relevant name", func(t *testing.T) { - runUnitTest(t, - getErrorTestCase(AwsCredFieldsByName, "Found multiple AWS Credentials for name: testdata"), - mockListAwsCredCall([]client.Credentials{awsCred, awsCred, awsCred}), - ) - }) - - t.Run("Throw error when by name and no aws-credential found with that name", func(t *testing.T) { - runUnitTest(t, - getErrorTestCase(AwsCredFieldsByName, "Could not find AWS Credentials with name: testdata"), - mockListAwsCredCall([]client.Credentials{otherAwsCred, credWithInvalidType}), - ) - }) - -} diff --git a/env0/data_azure_credentials.go b/env0/data_azure_credentials.go deleted file mode 100644 index d438ab27..00000000 --- a/env0/data_azure_credentials.go +++ /dev/null @@ -1,94 +0,0 @@ -package env0 - -import ( - "context" - - "github.com/env0/terraform-provider-env0/client" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" -) - -func dataAzureCredentials() *schema.Resource { - return &schema.Resource{ - ReadContext: dataAzureCredentialsRead, - - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Description: "the name of the credential", - Optional: true, - ExactlyOneOf: []string{"name", "id"}, - }, - "id": { - Type: schema.TypeString, - Description: "the id of the credential", - Optional: true, - ExactlyOneOf: []string{"name", "id"}, - }, - }, - } -} - -func dataAzureCredentialsRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - var err diag.Diagnostics - var credentials client.Credentials - - id, ok := d.GetOk("id") - if ok { - credentials, err = getAzureCredentialsById(id.(string), meta) - if err != nil { - return err - } - } else { - name, _ := d.Get("name").(string) // name must be specified here - credentials, err = getAzureCredentialsByName(name, meta) - if err != nil { - return err - } - } - - if err := writeResourceData(&credentials, d); err != nil { - return diag.Errorf("schema resource data serialization failed: %v", err) - } - - return nil -} - -func getAzureCredentialsByName(name interface{}, meta interface{}) (client.Credentials, diag.Diagnostics) { - apiClient := meta.(client.ApiClientInterface) - credentialsList, err := apiClient.CloudCredentialsList() - if err != nil { - return client.Credentials{}, diag.Errorf("Could not query Azure Credentials by name: %v", err) - } - - credentialsByNameAndType := make([]client.Credentials, 0) - for _, candidate := range credentialsList { - if candidate.Name == name.(string) && isValidAzureCredentialsType(candidate.Type) { - credentialsByNameAndType = append(credentialsByNameAndType, candidate) - } - } - - if len(credentialsByNameAndType) > 1 { - return client.Credentials{}, diag.Errorf("Found multiple Azure Credentials for name: %s", name) - } - if len(credentialsByNameAndType) == 0 { - return client.Credentials{}, diag.Errorf("Could not find Azure Credentials with name: %s", name) - } - return credentialsByNameAndType[0], nil -} - -func getAzureCredentialsById(id string, meta interface{}) (client.Credentials, diag.Diagnostics) { - apiClient := meta.(client.ApiClientInterface) - credentials, err := apiClient.CloudCredentials(id) - if !isValidAzureCredentialsType(credentials.Type) { - return client.Credentials{}, diag.Errorf("Found credentials which are not Azure Credentials: %v", credentials) - } - if err != nil { - return client.Credentials{}, diag.Errorf("Could not query Azure Credentials: %v", err) - } - return credentials, nil -} - -func isValidAzureCredentialsType(credentialsType string) bool { - return client.AzureCredentialsType(credentialsType) == client.AzureServicePrincipalCredentialsType -} diff --git a/env0/data_azure_credentials_test.go b/env0/data_azure_credentials_test.go deleted file mode 100644 index db00cab0..00000000 --- a/env0/data_azure_credentials_test.go +++ /dev/null @@ -1,98 +0,0 @@ -package env0 - -import ( - "regexp" - "testing" - - "github.com/env0/terraform-provider-env0/client" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" -) - -func TestAzureCredDataSource(t *testing.T) { - azureCred := client.Credentials{ - Id: "11111", - Name: "testdata", - OrganizationId: "id", - Type: "AZURE_SERVICE_PRINCIPAL_FOR_DEPLOYMENT", - } - - credWithInvalidType := client.Credentials{ - Id: azureCred.Id, - Name: azureCred.Name, - OrganizationId: azureCred.OrganizationId, - Type: "Invalid-type", - } - - AzureCredFieldsByName := map[string]interface{}{"name": azureCred.Name} - AzureCredFieldsById := map[string]interface{}{"id": azureCred.Id} - - resourceType := "env0_azure_credentials" - resourceName := "testdata" - accessor := dataSourceAccessor(resourceType, resourceName) - - getValidTestCase := func(input map[string]interface{}) resource.TestCase { - return resource.TestCase{ - Steps: []resource.TestStep{ - { - Config: dataSourceConfigCreate(resourceType, resourceName, input), - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(accessor, "id", azureCred.Id), - resource.TestCheckResourceAttr(accessor, "name", azureCred.Name), - ), - }, - }, - } - } - - getErrorTestCase := func(input map[string]interface{}, expectedError string) resource.TestCase { - return resource.TestCase{ - Steps: []resource.TestStep{ - { - Config: dataSourceConfigCreate(resourceType, resourceName, input), - ExpectError: regexp.MustCompile(expectedError), - }, - }, - } - } - - mockGetAzureCredCall := func(returnValue client.Credentials) func(mockFunc *client.MockApiClientInterface) { - return func(mock *client.MockApiClientInterface) { - mock.EXPECT().CloudCredentials(azureCred.Id).AnyTimes().Return(returnValue, nil) - } - } - - mockListAzureCredCall := func(returnValue []client.Credentials) func(mockFunc *client.MockApiClientInterface) { - return func(mock *client.MockApiClientInterface) { - mock.EXPECT().CloudCredentialsList().AnyTimes().Return(returnValue, nil) - } - } - - t.Run("By ID", func(t *testing.T) { - runUnitTest(t, - getValidTestCase(AzureCredFieldsById), - mockGetAzureCredCall(azureCred), - ) - }) - - t.Run("By Name", func(t *testing.T) { - runUnitTest(t, - getValidTestCase(AzureCredFieldsByName), - mockListAzureCredCall([]client.Credentials{azureCred, credWithInvalidType}), - ) - }) - - t.Run("Throw error when no name or id is supplied", func(t *testing.T) { - runUnitTest(t, - getErrorTestCase(map[string]interface{}{}, "one of `id,name` must be specified"), - func(mock *client.MockApiClientInterface) {}, - ) - }) - - t.Run("Throw error when by name and more than one azure-credential exists with the relevant name", func(t *testing.T) { - runUnitTest(t, - getErrorTestCase(AzureCredFieldsByName, "Found multiple Azure Credentials for name: testdata"), - mockListAzureCredCall([]client.Credentials{azureCred, azureCred, azureCred}), - ) - }) - -} diff --git a/env0/data_credentials.go b/env0/data_credentials.go new file mode 100644 index 00000000..90e29f64 --- /dev/null +++ b/env0/data_credentials.go @@ -0,0 +1,63 @@ +package env0 + +import ( + "context" + "strings" + + "github.com/env0/terraform-provider-env0/client" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func dataCredentials(cloudType string) *schema.Resource { + return &schema.Resource{ + ReadContext: dataCredentialsRead(cloudType), + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Description: "the name of the credentials", + Optional: true, + ExactlyOneOf: []string{"name", "id"}, + }, + "id": { + Type: schema.TypeString, + Description: "the id of the credentials", + Optional: true, + ExactlyOneOf: []string{"name", "id"}, + }, + }, + } +} + +func dataCredentialsRead(cloudType string) schema.ReadContextFunc { + return func(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var err error + var credentials client.Credentials + + prefix := strings.ToUpper(cloudType) + "_" + + id, ok := d.GetOk("id") + if ok { + credentials, err = getCredentialsById(id.(string), prefix, meta) + if err != nil { + return diag.Errorf("could not query %s credentials by id: %v", cloudType, err) + } + } else { + name, ok := d.GetOk("name") + if !ok { + return diag.Errorf("either 'name' or 'id' must be specified") + } + credentials, err = getCredentialsByName(name.(string), prefix, meta) + if err != nil { + return diag.Errorf("could not query %s credentials by name: %v", cloudType, err) + } + } + + if err := writeResourceData(&credentials, d); err != nil { + return diag.Errorf("schema resource data serialization failed: %v", err) + } + + return nil + } +} diff --git a/env0/data_credentials_test.go b/env0/data_credentials_test.go new file mode 100644 index 00000000..f830ae2d --- /dev/null +++ b/env0/data_credentials_test.go @@ -0,0 +1,138 @@ +package env0 + +import ( + "regexp" + "testing" + + "github.com/env0/terraform-provider-env0/client" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +type TestCredentialsCase struct { + credentialsType string + cloudType string +} + +func TestCredentialsDataSource(t *testing.T) { + testCases := []TestCredentialsCase{ + { + credentialsType: "AWS_ASSUMED_ROLE_FOR_DEPLOYMENT", + cloudType: "aws", + }, + { + credentialsType: "GCP_SERVICE_ACCOUNT_FOR_DEPLOYMENT", + cloudType: "gcp", + }, + { + credentialsType: "AZURE_SERVICE_PRINCIPAL_FOR_DEPLOYMENT", + cloudType: "azure", + }, + } + + for _, testCase := range testCases { + tc := testCase + + name := "name" + tc.cloudType + byName := map[string]interface{}{"name": name} + id := "id" + tc.cloudType + byId := map[string]interface{}{"id": id} + + resourceType := "env0_" + tc.cloudType + "_credentials" + resourceName := "testdata" + accessor := dataSourceAccessor(resourceType, resourceName) + + credentials := client.Credentials{ + Id: id, + Name: name, + OrganizationId: "id", + Type: tc.credentialsType, + } + + otherCredentials := client.Credentials{ + Id: "22222", + Name: "notname", + OrganizationId: "id", + Type: tc.credentialsType, + } + + invalidCredentials := client.Credentials{ + Id: credentials.Id, + Name: credentials.Name, + OrganizationId: credentials.OrganizationId, + Type: "Invalid-type", + } + + getValidTestCase := func(input map[string]interface{}) resource.TestCase { + return resource.TestCase{ + Steps: []resource.TestStep{ + { + Config: dataSourceConfigCreate(resourceType, resourceName, input), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(accessor, "id", credentials.Id), + resource.TestCheckResourceAttr(accessor, "name", credentials.Name), + ), + }, + }, + } + } + + getErrorTestCase := func(input map[string]interface{}, expectedError string) resource.TestCase { + return resource.TestCase{ + Steps: []resource.TestStep{ + { + Config: dataSourceConfigCreate(resourceType, resourceName, input), + ExpectError: regexp.MustCompile(expectedError), + }, + }, + } + } + + mockGetCredentials := func(returnValue client.Credentials) func(mockFunc *client.MockApiClientInterface) { + return func(mock *client.MockApiClientInterface) { + mock.EXPECT().CloudCredentials(credentials.Id).AnyTimes().Return(returnValue, nil) + } + } + + mockListCredentials := func(returnValue []client.Credentials) func(mockFunc *client.MockApiClientInterface) { + return func(mock *client.MockApiClientInterface) { + mock.EXPECT().CloudCredentialsList().AnyTimes().Return(returnValue, nil) + } + } + + t.Run(tc.cloudType+" by ID", func(t *testing.T) { + runUnitTest(t, + getValidTestCase(byId), + mockGetCredentials(credentials), + ) + }) + + t.Run(tc.cloudType+" by Name", func(t *testing.T) { + runUnitTest(t, + getValidTestCase(byName), + mockListCredentials([]client.Credentials{credentials, otherCredentials, invalidCredentials}), + ) + }) + + t.Run(tc.cloudType+" throw error when no name or id is supplied", func(t *testing.T) { + runUnitTest(t, + getErrorTestCase(map[string]interface{}{}, "one of `id,name` must be specified"), + func(mock *client.MockApiClientInterface) {}, + ) + }) + + t.Run(tc.cloudType+" throw error when by name and more than one aws-credential exists with the relevant name", func(t *testing.T) { + runUnitTest(t, + getErrorTestCase(byName, "found multiple credentials with name: name"+tc.cloudType), + mockListCredentials([]client.Credentials{credentials, credentials}), + ) + }) + + t.Run(tc.cloudType+" throw error when by name and no aws-credential found with that name", func(t *testing.T) { + runUnitTest(t, + getErrorTestCase(byName, "credentials with name name"+tc.cloudType+" not found"), + mockListCredentials([]client.Credentials{otherCredentials, invalidCredentials}), + ) + }) + } + +} diff --git a/env0/data_gcp_credentials.go b/env0/data_gcp_credentials.go deleted file mode 100644 index 5bda9f9a..00000000 --- a/env0/data_gcp_credentials.go +++ /dev/null @@ -1,94 +0,0 @@ -package env0 - -import ( - "context" - - "github.com/env0/terraform-provider-env0/client" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" -) - -func dataGcpCredentials() *schema.Resource { - return &schema.Resource{ - ReadContext: dataGcpCredentialsRead, - - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Description: "the name of the credential", - Optional: true, - ExactlyOneOf: []string{"name", "id"}, - }, - "id": { - Type: schema.TypeString, - Description: "the id of the credential", - Optional: true, - ExactlyOneOf: []string{"name", "id"}, - }, - }, - } -} - -func dataGcpCredentialsRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - var err diag.Diagnostics - var credentials client.Credentials - - id, ok := d.GetOk("id") - if ok { - credentials, err = getGcpCredentialsById(id.(string), meta) - if err != nil { - return err - } - } else { - name, _ := d.Get("name").(string) // name must be specified here - credentials, err = getGcpCredentialsByName(name, meta) - if err != nil { - return err - } - } - - if err := writeResourceData(&credentials, d); err != nil { - return diag.Errorf("schema resource data serialization failed: %v", err) - } - - return nil -} - -func getGcpCredentialsByName(name interface{}, meta interface{}) (client.Credentials, diag.Diagnostics) { - apiClient := meta.(client.ApiClientInterface) - credentialsList, err := apiClient.CloudCredentialsList() - if err != nil { - return client.Credentials{}, diag.Errorf("Could not query GCP Credentials by name: %v", err) - } - - credentialsByNameAndType := make([]client.Credentials, 0) - for _, candidate := range credentialsList { - if candidate.Name == name.(string) && isValidGcpCredentialsType(candidate.Type) { - credentialsByNameAndType = append(credentialsByNameAndType, candidate) - } - } - - if len(credentialsByNameAndType) > 1 { - return client.Credentials{}, diag.Errorf("Found multiple GCP Credentials for name: %s", name) - } - if len(credentialsByNameAndType) == 0 { - return client.Credentials{}, diag.Errorf("Could not find GCP Credentials with name: %s", name) - } - return credentialsByNameAndType[0], nil -} - -func getGcpCredentialsById(id string, meta interface{}) (client.Credentials, diag.Diagnostics) { - apiClient := meta.(client.ApiClientInterface) - credentials, err := apiClient.CloudCredentials(id) - if !isValidGcpCredentialsType(credentials.Type) { - return client.Credentials{}, diag.Errorf("Found credentials which are not GCP Credentials: %v", credentials) - } - if err != nil { - return client.Credentials{}, diag.Errorf("Could not query GCP Credentials: %v", err) - } - return credentials, nil -} - -func isValidGcpCredentialsType(credentialsType string) bool { - return client.GcpCredentialsType(credentialsType) == client.GcpServiceAccountCredentialsType -} diff --git a/env0/data_gcp_credentials_test.go b/env0/data_gcp_credentials_test.go deleted file mode 100644 index 74c5a9fd..00000000 --- a/env0/data_gcp_credentials_test.go +++ /dev/null @@ -1,98 +0,0 @@ -package env0 - -import ( - "regexp" - "testing" - - "github.com/env0/terraform-provider-env0/client" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" -) - -func TestGcpCredDataSource(t *testing.T) { - gcpCred := client.Credentials{ - Id: "11111", - Name: "testdata", - OrganizationId: "id", - Type: "GCP_SERVICE_ACCOUNT_FOR_DEPLOYMENT", - } - - credWithInvalidType := client.Credentials{ - Id: gcpCred.Id, - Name: gcpCred.Name, - OrganizationId: gcpCred.OrganizationId, - Type: "Invalid-type", - } - - GcpCredFieldsByName := map[string]interface{}{"name": gcpCred.Name} - GcpCredFieldsById := map[string]interface{}{"id": gcpCred.Id} - - resourceType := "env0_gcp_credentials" - resourceName := "testdata" - accessor := dataSourceAccessor(resourceType, resourceName) - - getValidTestCase := func(input map[string]interface{}) resource.TestCase { - return resource.TestCase{ - Steps: []resource.TestStep{ - { - Config: dataSourceConfigCreate(resourceType, resourceName, input), - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(accessor, "id", gcpCred.Id), - resource.TestCheckResourceAttr(accessor, "name", gcpCred.Name), - ), - }, - }, - } - } - - getErrorTestCase := func(input map[string]interface{}, expectedError string) resource.TestCase { - return resource.TestCase{ - Steps: []resource.TestStep{ - { - Config: dataSourceConfigCreate(resourceType, resourceName, input), - ExpectError: regexp.MustCompile(expectedError), - }, - }, - } - } - - mockGetGcpCredCall := func(returnValue client.Credentials) func(mockFunc *client.MockApiClientInterface) { - return func(mock *client.MockApiClientInterface) { - mock.EXPECT().CloudCredentials(gcpCred.Id).AnyTimes().Return(returnValue, nil) - } - } - - mockListGcpCredCall := func(returnValue []client.Credentials) func(mockFunc *client.MockApiClientInterface) { - return func(mock *client.MockApiClientInterface) { - mock.EXPECT().CloudCredentialsList().AnyTimes().Return(returnValue, nil) - } - } - - t.Run("By ID", func(t *testing.T) { - runUnitTest(t, - getValidTestCase(GcpCredFieldsById), - mockGetGcpCredCall(gcpCred), - ) - }) - - t.Run("By Name", func(t *testing.T) { - runUnitTest(t, - getValidTestCase(GcpCredFieldsByName), - mockListGcpCredCall([]client.Credentials{gcpCred, credWithInvalidType}), - ) - }) - - t.Run("Throw error when no name or id is supplied", func(t *testing.T) { - runUnitTest(t, - getErrorTestCase(map[string]interface{}{}, "one of `id,name` must be specified"), - func(mock *client.MockApiClientInterface) {}, - ) - }) - - t.Run("Throw error when by name and more than one gcp-credential exists with the relevant name", func(t *testing.T) { - runUnitTest(t, - getErrorTestCase(GcpCredFieldsByName, "Found multiple GCP Credentials for name: testdata"), - mockListGcpCredCall([]client.Credentials{gcpCred, gcpCred, gcpCred}), - ) - }) - -} diff --git a/env0/provider.go b/env0/provider.go index 9ddbd10f..4834c79e 100644 --- a/env0/provider.go +++ b/env0/provider.go @@ -58,9 +58,9 @@ func Provider(version string) plugin.ProviderFunc { "env0_aws_cost_credentials": dataCostCredentials(string(client.AwsCostCredentialsType)), "env0_azure_cost_credentials": dataCostCredentials(string(client.AzureCostCredentialsType)), "env0_google_cost_credentials": dataCostCredentials(string(client.GoogleCostCredentialsType)), - "env0_aws_credentials": dataAwsCredentials(), - "env0_gcp_credentials": dataGcpCredentials(), - "env0_azure_credentials": dataAzureCredentials(), + "env0_aws_credentials": dataCredentials("aws"), + "env0_gcp_credentials": dataCredentials("gcp"), + "env0_azure_credentials": dataCredentials("azure"), "env0_team": dataTeam(), "env0_teams": dataTeams(), "env0_environment": dataEnvironment(), diff --git a/env0/resource_aws_credentials_test.go b/env0/resource_aws_credentials_test.go index 1ed786f1..f35ef793 100644 --- a/env0/resource_aws_credentials_test.go +++ b/env0/resource_aws_credentials_test.go @@ -248,7 +248,7 @@ func TestUnitAwsCredentialsResource(t *testing.T) { ImportState: true, ImportStateId: otherTypeReturnValues.Id, ImportStateVerify: true, - ExpectError: regexp.MustCompile(fmt.Sprintf("aws credentials resource with id %v not found", otherTypeReturnValues.Id)), + ExpectError: regexp.MustCompile("credentials not found"), }, }, } diff --git a/env0/resource_azure_credentials_test.go b/env0/resource_azure_credentials_test.go index 6f94ac12..42edf1f6 100644 --- a/env0/resource_azure_credentials_test.go +++ b/env0/resource_azure_credentials_test.go @@ -243,7 +243,7 @@ func TestUnitAzureCredentialsResource(t *testing.T) { ImportState: true, ImportStateId: otherTypeReturnValues.Id, ImportStateVerify: true, - ExpectError: regexp.MustCompile(fmt.Sprintf("azure credentials resource with id %v not found", otherTypeReturnValues.Id)), + ExpectError: regexp.MustCompile("credentials not found"), }, }, } diff --git a/env0/resource_gcp_credentials_test.go b/env0/resource_gcp_credentials_test.go index 20e1f7df..fea90bae 100644 --- a/env0/resource_gcp_credentials_test.go +++ b/env0/resource_gcp_credentials_test.go @@ -232,7 +232,7 @@ func TestUnitGcpCredentialsResource(t *testing.T) { ImportState: true, ImportStateId: otherTypeReturnValues.Id, ImportStateVerify: true, - ExpectError: regexp.MustCompile(fmt.Sprintf("gcp credentials resource with id %v not found", otherTypeReturnValues.Id)), + ExpectError: regexp.MustCompile("credentials not found"), }, }, }