diff --git a/client/api_client.go b/client/api_client.go index 01fca048..5200fba4 100644 --- a/client/api_client.go +++ b/client/api_client.go @@ -7,8 +7,9 @@ import ( ) type ApiClient struct { - http http.HttpClientInterface - cachedOrganizationId string + http http.HttpClientInterface + cachedOrganizationId string + defaultOrganizationId string } type ApiClientInterface interface { @@ -117,9 +118,10 @@ type ApiClientInterface interface { CustomFlowGetAssignments(assignments []CustomFlowAssignment) ([]CustomFlowAssignment, error) } -func NewApiClient(client http.HttpClientInterface) ApiClientInterface { +func NewApiClient(client http.HttpClientInterface, defaultOrganizationId string) ApiClientInterface { return &ApiClient{ - http: client, - cachedOrganizationId: "", + http: client, + cachedOrganizationId: "", + defaultOrganizationId: defaultOrganizationId, } } diff --git a/client/client_test.go b/client/client_test.go index 3898a112..4b818892 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -13,7 +13,8 @@ import ( // This file wraps the test suite for the entire client folder const ( - organizationId = "organization0" + organizationId = "organization0" + defaultOrganizationId = "organization1" ) var ( @@ -31,7 +32,7 @@ var _ = BeforeSuite(func() { var _ = BeforeEach(func() { mockHttpClient = http.NewMockHttpClientInterface(ctrl) - apiClient = NewApiClient(mockHttpClient) + apiClient = NewApiClient(mockHttpClient, defaultOrganizationId) }) var _ = AfterSuite(func() { diff --git a/client/notification_test.go b/client/notification_test.go index 9762b013..b7659e78 100644 --- a/client/notification_test.go +++ b/client/notification_test.go @@ -1,8 +1,6 @@ package client_test import ( - "errors" - . "github.com/env0/terraform-provider-env0/client" gomock "github.com/golang/mock/gomock" "github.com/jinzhu/copier" @@ -87,29 +85,6 @@ var _ = Describe("Notification Client", func() { Expect(*createdNotification).To(Equal(mockNotification)) }) }) - - // NotificationCreate calls "organizationId()"" - // The test was "randomly" added here to test organizationId failure (when there are multiple organizations). - // Ideally should be tested in organization. Unfortunatly, organizationId is private and cannot be tested directly. - // (test package name varies from package name). - Describe("Failure - Multiple Organizations", func() { - var err error - - BeforeEach(func() { - organizationsResult := []Organization{{}, {}} - mockHttpClient.EXPECT(). - Get("/organizations", nil, gomock.Any()). - Do(func(path string, request interface{}, response *[]Organization) { - *response = organizationsResult - }) - _, err = apiClient.NotificationCreate(NotificationCreatePayload{}) - - }) - - It("Should return error", func() { - Expect(err).To(BeEquivalentTo(errors.New("server responded with too many organizations"))) - }) - }) }) Describe("NotificationDelete", func() { diff --git a/client/organization.go b/client/organization.go index a190ae8c..4327b9f3 100644 --- a/client/organization.go +++ b/client/organization.go @@ -2,6 +2,7 @@ package client import ( "errors" + "fmt" ) type Organization struct { @@ -36,7 +37,17 @@ func (client *ApiClient) Organization() (Organization, error) { return Organization{}, err } if len(result) != 1 { - return Organization{}, errors.New("server responded with too many organizations") + if client.defaultOrganizationId != "" { + for _, organization := range result { + if organization.Id == client.defaultOrganizationId { + return organization, nil + } + } + + return Organization{}, fmt.Errorf("the api key is not assigned to organization id: %s", client.defaultOrganizationId) + } + + return Organization{}, errors.New("server responded with too many organizations (set a default organization id in the provider settings)") } return result[0], nil } diff --git a/client/organization_test.go b/client/organization_test.go index fc3c29c0..b60f6185 100644 --- a/client/organization_test.go +++ b/client/organization_test.go @@ -15,6 +15,11 @@ var _ = Describe("Organization", func() { Name: "env0 🦄", } + mockDefaultOrganization := Organization{ + Id: defaultOrganizationId, + Name: "default", + } + Describe("Organization", func() { var organization Organization var err error @@ -41,6 +46,28 @@ var _ = Describe("Organization", func() { }) }) + Describe("Default Organization", func() { + BeforeEach(func() { + organizationsResult := []Organization{mockOrganization, mockDefaultOrganization} + httpCall = mockHttpClient.EXPECT(). + Get("/organizations", nil, gomock.Any()). + Do(func(path string, request interface{}, response *[]Organization) { + *response = organizationsResult + }) + + organization, err = apiClient.Organization() + }) + + It("Should send GET request once", func() { + httpCall.Times(1) + }) + + It("Should return organization", func() { + Expect(organization).Should(Equal(mockDefaultOrganization)) + Expect(err).Should(BeNil()) + }) + }) + Describe("Failure", func() { It("On error from server return the error", func() { expectedErr := errors.New("some error") @@ -62,7 +89,7 @@ var _ = Describe("Organization", func() { _, err = apiClient.Organization() Expect(err).ShouldNot(BeNil()) - Expect(err.Error()).Should(Equal("server responded with too many organizations")) + Expect(err.Error()).Should(Equal("the api key is not assigned to organization id: " + defaultOrganizationId)) }) }) }) diff --git a/env0/provider.go b/env0/provider.go index 30e3bfec..aa46c2c7 100644 --- a/env0/provider.go +++ b/env0/provider.go @@ -49,6 +49,11 @@ func Provider(version string) plugin.ProviderFunc { Required: true, Sensitive: true, }, + "organization_id": { + Type: schema.TypeString, + Description: "when the API key is associated with multiple organizations, this field is required. If an API key has one organization, this field is ignored.", + Optional: true, + }, }, DataSourcesMap: map[string]*schema.Resource{ "env0_organization": dataOrganization(), @@ -174,7 +179,7 @@ func configureProvider(version string, p *schema.Provider) schema.ConfigureConte return nil, diag.Diagnostics{diag.Diagnostic{Severity: diag.Error, Summary: err.Error()}} } - apiClient := client.NewApiClient(httpClient) + apiClient := client.NewApiClient(httpClient, d.Get("organization_id").(string)) // organizations fetched to cache Auth0 API response. if _, err := apiClient.OrganizationId(); err != nil {