-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat: Add support for Environment Discovery API #802
Changes from all commits
63811fd
5d181f4
c0abfa7
e7d386a
62e0636
f9fc792
42fd769
7c28959
9c211dc
781ad18
23eca20
2dbab89
d751d3e
efb9aec
f304b40
2ae73d6
bac319d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ env: | |
ENV0_API_ENDPOINT: ${{ secrets.ENV0_API_ENDPOINT }} | ||
ENV0_API_KEY: ${{ secrets.TF_PROVIDER_INTEGRATION_TEST_API_KEY }} # API Key for organization 'TF-provider-integration-tests' @ dev | ||
ENV0_API_SECRET: ${{ secrets.TF_PROVIDER_INTEGRATION_TEST_API_SECRET }} | ||
GO_VERSION: "1.20" | ||
GO_VERSION: "1.21" | ||
TERRAFORM_VERSION: 1.1.7 | ||
|
||
jobs: | ||
|
@@ -33,19 +33,14 @@ jobs: | |
- name: Go vet | ||
run: | | ||
! go vet ./... | read | ||
- name: Go staticcheck | ||
uses: dominikh/[email protected] | ||
with: | ||
version: "2023.1.3" | ||
install-go: false | ||
- name: Go Test | ||
run: go test -v ./... | ||
|
||
# See terraform-provider-env0 README for integration tests prerequisites | ||
integration-tests: | ||
name: Integration Tests | ||
runs-on: ubuntu-20.04 | ||
container: golang:1.20-alpine3.18 | ||
container: golang:1.21-alpine3.18 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FYI - alpine newer than 3.18 do not support terraform (due to hashicorp licensing change). Consider switching to opentofu. |
||
timeout-minutes: 20 | ||
steps: | ||
- name: Install Terraform | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,7 @@ on: | |
- main | ||
|
||
env: | ||
GO_VERSION: "1.20" | ||
GO_VERSION: "1.21" | ||
|
||
jobs: | ||
generate-docs: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,7 +16,7 @@ on: | |
- "v*.*.*" | ||
|
||
env: | ||
GO_VERSION: "1.20" | ||
GO_VERSION: "1.21" | ||
|
||
jobs: | ||
goreleaser: | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package client | ||
|
||
type EnvironmentDiscoveryPutPayload struct { | ||
GlobPattern string `json:"globPattern"` | ||
EnvironmentPlacement string `json:"environmentPlacement"` | ||
WorkspaceNaming string `json:"workspaceNaming"` | ||
AutoDeployByCustomGlob string `json:"autoDeployByCustomGlob,omitempty"` | ||
Repository string `json:"repository"` | ||
TerraformVersion string `json:"terraformVersion,omitempty"` | ||
OpentofuVersion string `json:"opentofuVersion,omitempty"` | ||
TerragruntVersion string `json:"terragruntVersion,omitempty"` | ||
TerragruntTfBinary string `json:"terragruntTfBinary,omitempty"` | ||
IsTerragruntRunAll bool `json:"is_terragrunt_run_all"` | ||
Type string `json:"type"` | ||
GitlabProjectId int `json:"gitlabProjectId,omitempty"` | ||
TokenId string `json:"tokenId,omitempty"` | ||
SshKeys []TemplateSshKey `json:"sshKeys,omitempty"` | ||
GithubInstallationId int `json:"githubInstallationId,omitempty"` | ||
BitbucketClientKey string `json:"bitbucketClientKey,omitempty"` | ||
IsAzureDevops bool `json:"isAzureDevOps"` | ||
Retry TemplateRetry `json:"retry"` | ||
} | ||
|
||
type EnvironmentDiscoveryPayload struct { | ||
Id string `json:"id"` | ||
GlobPattern string `json:"globPattern"` | ||
EnvironmentPlacement string `json:"environmentPlacement"` | ||
WorkspaceNaming string `json:"workspaceNaming"` | ||
AutoDeployByCustomGlob string `json:"autoDeployByCustomGlob"` | ||
Repository string `json:"repository"` | ||
TerraformVersion string `json:"terraformVersion"` | ||
OpentofuVersion string `json:"opentofuVersion"` | ||
TerragruntVersion string `json:"terragruntVersion"` | ||
TerragruntTfBinary string `json:"terragruntTfBinary" tfschema:",omitempty"` | ||
IsTerragruntRunAll bool `json:"is_terragrunt_run_all"` | ||
Type string `json:"type"` | ||
GitlabProjectId int `json:"gitlabProjectId"` | ||
TokenId string `json:"tokenId"` | ||
SshKeys []TemplateSshKey `json:"sshKeys" tfschema:"-"` | ||
GithubInstallationId int `json:"githubInstallationId"` | ||
BitbucketClientKey string `json:"bitbucketClientKey"` | ||
IsAzureDevops bool `json:"isAzureDevOps"` | ||
Retry TemplateRetry `json:"retry" tfschema:"-"` | ||
} | ||
|
||
func (client *ApiClient) PutEnvironmentDiscovery(projectId string, payload *EnvironmentDiscoveryPutPayload) (*EnvironmentDiscoveryPayload, error) { | ||
var result EnvironmentDiscoveryPayload | ||
|
||
if err := client.http.Put("/environment-discovery/projects/"+projectId, payload, &result); err != nil { | ||
return nil, err | ||
} | ||
|
||
return &result, nil | ||
} | ||
|
||
func (client *ApiClient) GetEnvironmentDiscovery(projectId string) (*EnvironmentDiscoveryPayload, error) { | ||
var result EnvironmentDiscoveryPayload | ||
|
||
if err := client.http.Get("/environment-discovery/projects/"+projectId, nil, &result); err != nil { | ||
return nil, err | ||
} | ||
|
||
return &result, nil | ||
} | ||
|
||
func (client *ApiClient) DeleteEnvironmentDiscovery(projectId string) error { | ||
return client.http.Delete("/environment-discovery/projects/"+projectId, nil) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
package client_test | ||
|
||
import ( | ||
"errors" | ||
|
||
. "github.com/env0/terraform-provider-env0/client" | ||
. "github.com/onsi/ginkgo" | ||
. "github.com/onsi/gomega" | ||
"go.uber.org/mock/gomock" | ||
) | ||
|
||
var _ = Describe("Environment Discovery", func() { | ||
mockError := errors.New("error") | ||
|
||
projectId := "pid" | ||
|
||
mockEnvironmentDiscovery := EnvironmentDiscoveryPayload{ | ||
Id: "id", | ||
GlobPattern: "**", | ||
EnvironmentPlacement: "topProject", | ||
WorkspaceNaming: "default", | ||
AutoDeployByCustomGlob: "**", | ||
Repository: "https://re.po", | ||
TerraformVersion: "1.5.6", | ||
Type: "terraform", | ||
GithubInstallationId: 1000, | ||
} | ||
|
||
Describe("PUT", func() { | ||
putPayload := EnvironmentDiscoveryPutPayload{ | ||
GlobPattern: mockEnvironmentDiscovery.GlobPattern, | ||
EnvironmentPlacement: mockEnvironmentDiscovery.EnvironmentPlacement, | ||
WorkspaceNaming: mockEnvironmentDiscovery.WorkspaceNaming, | ||
AutoDeployByCustomGlob: mockEnvironmentDiscovery.AutoDeployByCustomGlob, | ||
Repository: mockEnvironmentDiscovery.Repository, | ||
TerraformVersion: mockEnvironmentDiscovery.TerraformVersion, | ||
Type: mockEnvironmentDiscovery.Type, | ||
GithubInstallationId: mockEnvironmentDiscovery.GithubInstallationId, | ||
} | ||
|
||
Describe("success", func() { | ||
var ret *EnvironmentDiscoveryPayload | ||
|
||
BeforeEach(func() { | ||
httpCall = mockHttpClient.EXPECT(). | ||
Put("/environment-discovery/projects/"+projectId, &putPayload, gomock.Any()). | ||
Do(func(path string, request interface{}, response *EnvironmentDiscoveryPayload) { | ||
*response = mockEnvironmentDiscovery | ||
}).Times(1) | ||
ret, _ = apiClient.PutEnvironmentDiscovery(projectId, &putPayload) | ||
}) | ||
|
||
It("Should return environment discovery", func() { | ||
Expect(*ret).To(Equal(mockEnvironmentDiscovery)) | ||
}) | ||
}) | ||
|
||
Describe("failure", func() { | ||
var err error | ||
|
||
BeforeEach(func() { | ||
httpCall = mockHttpClient.EXPECT(). | ||
Put("/environment-discovery/projects/"+projectId, &putPayload, gomock.Any()).Return(mockError).Times(1) | ||
_, err = apiClient.PutEnvironmentDiscovery(projectId, &putPayload) | ||
}) | ||
|
||
It("Should return error", func() { | ||
Expect(err).To(Equal(mockError)) | ||
}) | ||
}) | ||
}) | ||
|
||
Describe("GET", func() { | ||
Describe("success", func() { | ||
var ret *EnvironmentDiscoveryPayload | ||
|
||
BeforeEach(func() { | ||
httpCall = mockHttpClient.EXPECT(). | ||
Get("/environment-discovery/projects/"+projectId, nil, gomock.Any()). | ||
Do(func(path string, request interface{}, response *EnvironmentDiscoveryPayload) { | ||
*response = mockEnvironmentDiscovery | ||
}).Times(1) | ||
ret, _ = apiClient.GetEnvironmentDiscovery(projectId) | ||
}) | ||
|
||
It("Should return environment discovery", func() { | ||
Expect(*ret).To(Equal(mockEnvironmentDiscovery)) | ||
}) | ||
}) | ||
|
||
Describe("failure", func() { | ||
var err error | ||
|
||
BeforeEach(func() { | ||
httpCall = mockHttpClient.EXPECT(). | ||
Get("/environment-discovery/projects/"+projectId, nil, gomock.Any()).Return(mockError).Times(1) | ||
_, err = apiClient.GetEnvironmentDiscovery(projectId) | ||
}) | ||
|
||
It("Should return error", func() { | ||
Expect(err).To(Equal(mockError)) | ||
}) | ||
}) | ||
}) | ||
|
||
Describe("DELETE", func() { | ||
Describe("success", func() { | ||
BeforeEach(func() { | ||
httpCall = mockHttpClient.EXPECT().Delete("/environment-discovery/projects/"+projectId, nil).Times(1) | ||
apiClient.DeleteEnvironmentDiscovery(projectId) | ||
}) | ||
|
||
It("Should send DELETE request", func() {}) | ||
}) | ||
|
||
Describe("failure", func() { | ||
var err error | ||
|
||
BeforeEach(func() { | ||
httpCall = mockHttpClient.EXPECT(). | ||
Delete("/environment-discovery/projects/"+projectId, nil).Return(mockError).Times(1) | ||
err = apiClient.DeleteEnvironmentDiscovery(projectId) | ||
}) | ||
|
||
It("Should return error", func() { | ||
Expect(err).To(Equal(mockError)) | ||
}) | ||
}) | ||
}) | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -92,7 +92,7 @@ func dataProjectRead(ctx context.Context, d *schema.ResourceData, meta interface | |
return nil | ||
} | ||
|
||
func filterByParentProjectId(name string, parentId string, projects []client.Project) ([]client.Project, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unrelated - but name is not used so removed it... |
||
func filterByParentProjectId(parentId string, projects []client.Project) ([]client.Project, error) { | ||
filteredProjects := make([]client.Project, 0) | ||
for _, project := range projects { | ||
if len(project.ParentProjectId) == 0 { | ||
|
@@ -107,7 +107,7 @@ func filterByParentProjectId(name string, parentId string, projects []client.Pro | |
return filteredProjects, nil | ||
} | ||
|
||
func filterByParentProjectName(name string, parentName string, projects []client.Project, meta interface{}) ([]client.Project, error) { | ||
func filterByParentProjectName(parentName string, projects []client.Project, meta interface{}) ([]client.Project, error) { | ||
filteredProjects := make([]client.Project, 0) | ||
for _, project := range projects { | ||
if len(project.ParentProjectId) == 0 { | ||
|
@@ -142,13 +142,13 @@ func getProjectByName(name string, parentId string, parentName string, meta inte | |
} | ||
if len(parentId) > 0 { | ||
// Use parentId filter to reduce the results. | ||
projectsByName, err = filterByParentProjectId(name, parentId, projectsByName) | ||
projectsByName, err = filterByParentProjectId(parentId, projectsByName) | ||
if err != nil { | ||
return client.Project{}, err | ||
} | ||
} else if len(parentName) > 0 { | ||
// Use parentName filter to reduce the results. | ||
projectsByName, err = filterByParentProjectName(name, parentName, projectsByName, meta) | ||
projectsByName, err = filterByParentProjectName(parentName, projectsByName, meta) | ||
if err != nil { | ||
return client.Project{}, err | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,7 +29,7 @@ func TestPolicyDataSource(t *testing.T) { | |
resourceName := "test_policy" | ||
accessor := dataSourceAccessor(resourceType, resourceName) | ||
|
||
getValidTestCase := func(input map[string]interface{}) resource.TestCase { | ||
getValidTestCase := func() resource.TestCase { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unrelated - another unused variable. |
||
return resource.TestCase{ | ||
Steps: []resource.TestStep{ | ||
{ | ||
|
@@ -57,7 +57,7 @@ func TestPolicyDataSource(t *testing.T) { | |
} | ||
|
||
t.Run("valid", func(t *testing.T) { | ||
runUnitTest(t, getValidTestCase(map[string]interface{}{}), func(mock *client.MockApiClientInterface) { | ||
runUnitTest(t, getValidTestCase(), func(mock *client.MockApiClientInterface) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unused... |
||
mock.EXPECT().Policy(policy.ProjectId).AnyTimes().Return(policy, nil) | ||
}) | ||
}) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed an CVE and also updated the golang version.
This will now be considered a major release.