Skip to content

Commit

Permalink
Feat: use new approval policy API instead of blueprint api (#809)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomerHeber authored Mar 17, 2024
1 parent 6525c17 commit 12a7ea7
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 33 deletions.
2 changes: 2 additions & 0 deletions client/api_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ type ApiClientInterface interface {
ApprovalPolicyAssign(assignment *ApprovalPolicyAssignment) (*ApprovalPolicyAssignment, error)
ApprovalPolicyUnassign(scope string, scopeId string) error
ApprovalPolicyByScope(scope string, scopeId string) ([]ApprovalPolicyByScope, error)
ApprovalPolicyCreate(payload *ApprovalPolicyCreatePayload) (*ApprovalPolicy, error)
ApprovalPolicyUpdate(payload *ApprovalPolicyUpdatePayload) (*ApprovalPolicy, error)
ProjectBudget(projectId string) (*ProjectBudget, error)
ProjectBudgetUpdate(projectId string, payload *ProjectBudgetUpdatePayload) (*ProjectBudget, error)
ProjectBudgetDelete(projectId string) error
Expand Down
30 changes: 30 additions & 0 deletions client/api_client_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

62 changes: 62 additions & 0 deletions client/approval_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,37 @@ type ApprovalPolicyByScope struct {
ApprovalPolicy *ApprovalPolicy `json:"blueprint"`
}

type ApprovalPolicyCreatePayload struct {
Name string `json:"name"`
Repository string `json:"repository"`
Revision string `json:"revision,omitempty"`
Path string `json:"path,omitempty"`
TokenId string `json:"tokenId,omitempty"`
GithubInstallationId int `json:"githubInstallationId,omitempty"`
BitbucketClientKey string `json:"bitbucketClientKey,omitempty"`
IsBitbucketServer bool `json:"isBitbucketServer,omitempty"`
IsGitlabEnterprise bool `json:"isGitLabEnterprise"`
IsGithubEnterprise bool `json:"isGitHubEnterprise"`
IsGitLab bool `json:"isGitLab" tfschema:"is_gitlab"`
IsAzureDevOps bool `json:"isAzureDevOps" tfschema:"is_azure_devops"`
}

type ApprovalPolicyUpdatePayload struct {
Id string `json:"id"`
Name string `json:"name"`
Repository string `json:"repository"`
Revision string `json:"revision,omitempty"`
Path string `json:"path,omitempty"`
TokenId string `json:"tokenId,omitempty"`
GithubInstallationId int `json:"githubInstallationId,omitempty"`
BitbucketClientKey string `json:"bitbucketClientKey,omitempty"`
IsBitbucketServer bool `json:"isBitbucketServer,omitempty"`
IsGitlabEnterprise bool `json:"isGitLabEnterprise"`
IsGithubEnterprise bool `json:"isGitHubEnterprise"`
IsGitLab bool `json:"isGitLab" tfschema:"is_gitlab"`
IsAzureDevOps bool `json:"isAzureDevOps" tfschema:"is_azure_devops"`
}

type ApprovalPolicyAssignmentScope string

const (
Expand All @@ -38,6 +69,37 @@ type ApprovalPolicyAssignment struct {
BlueprintId string `json:"blueprintId"`
}

func (client *ApiClient) ApprovalPolicyCreate(payload *ApprovalPolicyCreatePayload) (*ApprovalPolicy, error) {
organizationId, err := client.OrganizationId()
if err != nil {
return nil, err
}

payloadWithOrganizationId := struct {
ApprovalPolicyCreatePayload
OrganizationId string `json:"organizationId"`
}{
*payload,
organizationId,
}

var result ApprovalPolicy
if err := client.http.Post("/approval-policy", &payloadWithOrganizationId, &result); err != nil {
return nil, err
}

return &result, nil
}

func (client *ApiClient) ApprovalPolicyUpdate(payload *ApprovalPolicyUpdatePayload) (*ApprovalPolicy, error) {
var result ApprovalPolicy
if err := client.http.Put("/approval-policy", payload, &result); err != nil {
return nil, err
}

return &result, nil
}

func (client *ApiClient) ApprovalPolicies(name string) ([]ApprovalPolicy, error) {
organizationId, err := client.OrganizationId()
if err != nil {
Expand Down
63 changes: 63 additions & 0 deletions client/approval_policy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"

. "github.com/env0/terraform-provider-env0/client"
"github.com/jinzhu/copier"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"go.uber.org/mock/gomock"
Expand Down Expand Up @@ -117,4 +118,66 @@ var _ = Describe("Approval Policy Client", func() {
Expect(ret).To(Equal(mockApprovalPolicyByScopeArr))
})
})

Describe("Create ApprovalPolicy", func() {
var result *ApprovalPolicy
var err error

BeforeEach(func() {
mockOrganizationIdCall(organizationId).Times(1)

createApprovalPolicyPayload := ApprovalPolicyCreatePayload{}
copier.Copy(&createApprovalPolicyPayload, &mockApprovalPolicy)

expectedCreateRequest := struct {
ApprovalPolicyCreatePayload
OrganizationId string `json:"organizationId"`
}{
createApprovalPolicyPayload,
organizationId,
}

httpCall = mockHttpClient.EXPECT().
Post("/approval-policy", &expectedCreateRequest, gomock.Any()).
Do(func(path string, request interface{}, response *ApprovalPolicy) {
*response = mockApprovalPolicy
}).Times(1)

result, err = apiClient.ApprovalPolicyCreate(&createApprovalPolicyPayload)
})

It("Should not return error", func() {
Expect(err).To(BeNil())
})

It("Should return created Approval Policy", func() {
Expect(*result).To(Equal(mockApprovalPolicy))
})
})

Describe("Update ApprovalPolicy", func() {
var result *ApprovalPolicy
var err error

BeforeEach(func() {
updateApprovalPolicyPayload := ApprovalPolicyUpdatePayload{}
copier.Copy(&updateApprovalPolicyPayload, &mockApprovalPolicy)

httpCall = mockHttpClient.EXPECT().
Put("/approval-policy", &updateApprovalPolicyPayload, gomock.Any()).
Do(func(path string, request interface{}, response *ApprovalPolicy) {
*response = mockApprovalPolicy
}).Times(1)

result, err = apiClient.ApprovalPolicyUpdate(&updateApprovalPolicyPayload)
})

It("Should not return error", func() {
Expect(err).To(BeNil())
})

It("Should return updated Approval Policy", func() {
Expect(*result).To(Equal(mockApprovalPolicy))
})
})
})
23 changes: 9 additions & 14 deletions env0/resource_approval_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,17 @@ func resourceApprovalPolicy() *schema.Resource {
func resourceApprovalPolicyCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
apiClient := meta.(client.ApiClientInterface)

var payload client.TemplateCreatePayload
var payload client.ApprovalPolicyCreatePayload
if err := readResourceData(&payload, d); err != nil {
return diag.Errorf("schema resource data deserialization failed: %v", err)
}

payload.Type = string(ApprovalPolicy)

template, err := apiClient.TemplateCreate(payload)
approvalPolicy, err := apiClient.ApprovalPolicyCreate(&payload)
if err != nil {
return diag.Errorf("could not create approval policy template: %v", err)
return diag.Errorf("failed to create approval policy: %v", err)
}

d.SetId(template.Id)
d.SetId(approvalPolicy.Id)

return nil
}
Expand Down Expand Up @@ -68,16 +66,13 @@ func resourceApprovalPolicyRead(ctx context.Context, d *schema.ResourceData, met
func resourceApprovalPolicyUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
apiClient := meta.(client.ApiClientInterface)

request, problem := templateCreatePayloadFromParameters("", d)
if problem != nil {
return problem
var payload client.ApprovalPolicyUpdatePayload
if err := readResourceData(&payload, d); err != nil {
return diag.Errorf("schema resource data deserialization failed: %v", err)
}

request.Type = string(ApprovalPolicy)

_, err := apiClient.TemplateUpdate(d.Id(), request)
if err != nil {
return diag.Errorf("could not update approval policy template: %v", err)
if _, err := apiClient.ApprovalPolicyUpdate(&payload); err != nil {
return diag.Errorf("failed to update approval policy: %v", err)
}

return nil
Expand Down
37 changes: 18 additions & 19 deletions env0/resource_approval_policy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,27 +54,26 @@ func TestUnitApprovalPolicyResource(t *testing.T) {

var updatedTemplate client.Template
copier.Copy(&updatedTemplate, &updatedApprovalPolicy)
template.Type = string(ApprovalPolicy)
updatedTemplate.Type = string(ApprovalPolicy)

createPayload := client.TemplateCreatePayload{
createPayload := client.ApprovalPolicyCreatePayload{
Name: approvalPolicy.Name,
Repository: approvalPolicy.Repository,
Path: approvalPolicy.Path,
Revision: approvalPolicy.Revision,
TokenId: approvalPolicy.TokenId,
GithubInstallationId: approvalPolicy.GithubInstallationId,
IsGithubEnterprise: approvalPolicy.IsGithubEnterprise,
Type: string(ApprovalPolicy),
}

updatePayload := client.TemplateCreatePayload{
updatePayload := client.ApprovalPolicyUpdatePayload{
Name: updatedApprovalPolicy.Name,
Repository: updatedApprovalPolicy.Repository,
Path: updatedApprovalPolicy.Path,
Revision: updatedApprovalPolicy.Revision,
TokenId: updatedApprovalPolicy.TokenId,
IsAzureDevOps: updatedApprovalPolicy.IsAzureDevOps,
Type: string(ApprovalPolicy),
Id: approvalPolicy.Id,
}

t.Run("Success", func(t *testing.T) {
Expand Down Expand Up @@ -127,9 +126,9 @@ func TestUnitApprovalPolicyResource(t *testing.T) {

runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) {
gomock.InOrder(
mock.EXPECT().TemplateCreate(createPayload).Times(1).Return(template, nil),
mock.EXPECT().ApprovalPolicyCreate(&createPayload).Times(1).Return(&approvalPolicy, nil),
mock.EXPECT().Template(approvalPolicy.Id).Times(2).Return(template, nil),
mock.EXPECT().TemplateUpdate(approvalPolicy.Id, updatePayload).Times(1).Return(updatedTemplate, nil),
mock.EXPECT().ApprovalPolicyUpdate(&updatePayload).Times(1).Return(&updatedApprovalPolicy, nil),
mock.EXPECT().Template(approvalPolicy.Id).Times(1).Return(updatedTemplate, nil),
mock.EXPECT().TemplateDelete(approvalPolicy.Id).Times(1).Return(nil),
)
Expand Down Expand Up @@ -189,7 +188,7 @@ func TestUnitApprovalPolicyResource(t *testing.T) {

runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) {
gomock.InOrder(
mock.EXPECT().TemplateCreate(createPayload).Times(1).Return(template, nil),
mock.EXPECT().ApprovalPolicyCreate(&createPayload).Times(1).Return(&approvalPolicy, nil),
mock.EXPECT().Template(template.Id).Times(2).Return(deletedTemplate, nil),
)
})
Expand Down Expand Up @@ -248,7 +247,7 @@ func TestUnitApprovalPolicyResource(t *testing.T) {

runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) {
gomock.InOrder(
mock.EXPECT().TemplateCreate(createPayload).Times(1).Return(template, nil),
mock.EXPECT().ApprovalPolicyCreate(&createPayload).Times(1).Return(&approvalPolicy, nil),
mock.EXPECT().Template(template.Id).Times(2).Return(client.Template{}, http.NewMockFailedResponseError(404)),
)
})
Expand All @@ -267,13 +266,13 @@ func TestUnitApprovalPolicyResource(t *testing.T) {
"github_installation_id": approvalPolicy.GithubInstallationId,
"is_github_enterprise": "true",
}),
ExpectError: regexp.MustCompile("could not create approval policy template: error"),
ExpectError: regexp.MustCompile("failed to create approval policy: error"),
},
},
}

runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) {
mock.EXPECT().TemplateCreate(createPayload).Times(1).Return(client.Template{}, errors.New("error"))
mock.EXPECT().ApprovalPolicyCreate(&createPayload).Times(1).Return(nil, errors.New("error"))
})
})

Expand All @@ -300,16 +299,16 @@ func TestUnitApprovalPolicyResource(t *testing.T) {
"token_id": updatedApprovalPolicy.TokenId,
"is_azure_devops": "true",
}),
ExpectError: regexp.MustCompile("could not update approval policy template: error"),
ExpectError: regexp.MustCompile("failed to update approval policy: error"),
},
},
}

runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) {
gomock.InOrder(
mock.EXPECT().TemplateCreate(createPayload).Times(1).Return(template, nil),
mock.EXPECT().ApprovalPolicyCreate(&createPayload).Times(1).Return(&approvalPolicy, nil),
mock.EXPECT().Template(approvalPolicy.Id).Times(2).Return(template, nil),
mock.EXPECT().TemplateUpdate(approvalPolicy.Id, updatePayload).Times(1).Return(client.Template{}, errors.New("error")),
mock.EXPECT().ApprovalPolicyUpdate(&updatePayload).Times(1).Return(nil, errors.New("error")),
mock.EXPECT().TemplateDelete(approvalPolicy.Id).Times(1).Return(nil),
)
})
Expand Down Expand Up @@ -340,7 +339,7 @@ func TestUnitApprovalPolicyResource(t *testing.T) {

runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) {
gomock.InOrder(
mock.EXPECT().TemplateCreate(createPayload).Times(1).Return(template, nil),
mock.EXPECT().ApprovalPolicyCreate(&createPayload).Times(1).Return(&approvalPolicy, nil),
mock.EXPECT().Template(approvalPolicy.Id).Times(3).Return(template, nil),
mock.EXPECT().TemplateDelete(approvalPolicy.Id).Times(1).Return(nil),
)
Expand Down Expand Up @@ -373,7 +372,7 @@ func TestUnitApprovalPolicyResource(t *testing.T) {

runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) {
gomock.InOrder(
mock.EXPECT().TemplateCreate(createPayload).Times(1).Return(template, nil),
mock.EXPECT().ApprovalPolicyCreate(&createPayload).Times(1).Return(&approvalPolicy, nil),
mock.EXPECT().Template(approvalPolicy.Id).Times(1).Return(template, nil),
mock.EXPECT().Template(approvalPolicy.Id).Times(1).Return(notApprovalPolicyTemplate, nil),
mock.EXPECT().TemplateDelete(approvalPolicy.Id).Times(1).Return(nil),
Expand Down Expand Up @@ -406,7 +405,7 @@ func TestUnitApprovalPolicyResource(t *testing.T) {

runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) {
gomock.InOrder(
mock.EXPECT().TemplateCreate(createPayload).Times(1).Return(template, nil),
mock.EXPECT().ApprovalPolicyCreate(&createPayload).Times(1).Return(&approvalPolicy, nil),
mock.EXPECT().Template(approvalPolicy.Id).Times(1).Return(template, nil),
mock.EXPECT().ApprovalPolicies(approvalPolicy.Name).Times(1).Return([]client.ApprovalPolicy{approvalPolicy}, nil),
mock.EXPECT().Template(approvalPolicy.Id).Times(1).Return(template, nil),
Expand Down Expand Up @@ -441,7 +440,7 @@ func TestUnitApprovalPolicyResource(t *testing.T) {

runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) {
gomock.InOrder(
mock.EXPECT().TemplateCreate(createPayload).Times(1).Return(template, nil),
mock.EXPECT().ApprovalPolicyCreate(&createPayload).Times(1).Return(&approvalPolicy, nil),
mock.EXPECT().Template(approvalPolicy.Id).Times(1).Return(template, nil),
mock.EXPECT().ApprovalPolicies(approvalPolicy.Name).Times(1).Return([]client.ApprovalPolicy{}, nil),
mock.EXPECT().TemplateDelete(approvalPolicy.Id).Times(1).Return(nil),
Expand Down Expand Up @@ -475,7 +474,7 @@ func TestUnitApprovalPolicyResource(t *testing.T) {

runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) {
gomock.InOrder(
mock.EXPECT().TemplateCreate(createPayload).Times(1).Return(template, nil),
mock.EXPECT().ApprovalPolicyCreate(&createPayload).Times(1).Return(&approvalPolicy, nil),
mock.EXPECT().Template(approvalPolicy.Id).Times(1).Return(template, nil),
mock.EXPECT().ApprovalPolicies(approvalPolicy.Name).Times(1).Return([]client.ApprovalPolicy{approvalPolicy, approvalPolicy}, nil),
mock.EXPECT().TemplateDelete(approvalPolicy.Id).Times(1).Return(nil),
Expand Down

0 comments on commit 12a7ea7

Please sign in to comment.