Skip to content

Commit

Permalink
fix gitlab_project_id changes every apply (#145)
Browse files Browse the repository at this point in the history
* fix gitlab_project_id changes every apply
* fix broken test
* add test
* fix docs
  • Loading branch information
razbensimon committed Sep 22, 2021
1 parent b9eaf7c commit a399839
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 41 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ provider "env0" {
### Run local version of the provider
- Build - `./build.sh`
- Create the plugins folder - `mkdir -p ~/.terraform.d/plugins/terraform.env0.com/local/env0/6.6.6/darwin_amd64`
- Copy the built binary - `cp ~/env0/terraform-provider-env0/terraform-provider-env0 ~/.terraform.d/plugins/terraform.env0.com/local/env0/6.6.6/darwin_amd64` (Replace `darwin` with `linux` on Linux)
- Copy the built binary - `cp ./terraform-provider-env0 ~/.terraform.d/plugins/terraform.env0.com/local/env0/6.6.6/darwin_amd64` (Replace `darwin` with `linux` on Linux)
- Require the local provider in your `main.tf` -
```
terraform {
Expand Down Expand Up @@ -132,12 +132,12 @@ go generate ./...

## Documentation
- Docs are generated using github.com/hashicorp/terraform-plugin-docs
- Run `./generate-docs` to generate docs
- Run `./generate-docs.sh` to generate docs
- Must be run manually before releasing a version

## Release
To release a version to the [Terraform Public Registry](https://registry.terraform.io/providers/env0/env0/latest?pollNotifications=true) -
1. Docs must be generated manually and committed to the repo before release. (`./generate-docs`)
1. Docs must be generated manually and committed to the repo before release. (`./generate-docs.sh`)
2. Create and push a tag locally, in semver format - `git tag v0.0.9 && git push origin --tags`
3. Goto [Github Releases](https://github.com/env0/terraform-provider-env0/releases) and edit the draft created by Release Drafter Bot - it should contain the change log for the release. Make sure it's pointing at the tag you created in the previous step and publish the release.
4. Binaries will be automatically generated by the Github action defined in `.github/workflows/release.yml`
Expand Down
2 changes: 1 addition & 1 deletion env0/resource_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,12 +243,12 @@ func resourceTemplateRead(ctx context.Context, d *schema.ResourceData, meta inte
d.Set("description", template.Description)
d.Set("github_installation_id", template.GithubInstallationId)
d.Set("token_id", template.TokenId)
d.Set("gitlab_project_id", template.GitlabProjectId)
d.Set("repository", template.Repository)
d.Set("path", template.Path)
d.Set("revision", template.Revision)
d.Set("type", template.Type)
d.Set("terraform_version", template.TerraformVersion)
// 'gitlab_project_id' should not be set because it doesn't exist on 'template'

var rawSshKeys []map[string]string
for _, sshKey := range template.SshKeys {
Expand Down
126 changes: 89 additions & 37 deletions env0/resource_template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,52 @@ func TestUnitTemplateResource(t *testing.T) {

var resourceFullName = resourceAccessor(resourceType, resourceName)

fullTemplateResourceConfig := func(resourceType string, resourceName string, template client.Template) string {
templateAsDictionary := map[string]interface{}{
"name": template.Name,
"repository": template.Repository,
}

if template.Type != "" {
templateAsDictionary["type"] = template.Type
}
if template.Description != "" {
templateAsDictionary["description"] = template.Description
}
if template.Revision != "" {
templateAsDictionary["revision"] = template.Revision
}
if template.Path != "" {
templateAsDictionary["path"] = template.Path
}
if template.Retry != (client.TemplateRetry{}) && template.Retry.OnDeploy != nil {
templateAsDictionary["retries_on_deploy"] = template.Retry.OnDeploy.Times
if template.Retry.OnDeploy.ErrorRegex != "" {
templateAsDictionary["retry_on_deploy_only_when_matches_regex"] = template.Retry.OnDeploy.ErrorRegex
}
}
if template.Retry != (client.TemplateRetry{}) && template.Retry.OnDestroy != nil {
templateAsDictionary["retries_on_destroy"] = template.Retry.OnDestroy.Times
if template.Retry.OnDestroy.ErrorRegex != "" {
templateAsDictionary["retry_on_destroy_only_when_matches_regex"] = template.Retry.OnDestroy.ErrorRegex
}
}
if template.TerraformVersion != "" {
templateAsDictionary["terraform_version"] = template.TerraformVersion
}
if template.TokenId != "" {
templateAsDictionary["token_id"] = template.TokenId
}
if template.GitlabProjectId != 0 {
templateAsDictionary["gitlab_project_id"] = template.GitlabProjectId
}
if template.GithubInstallationId != 0 {
templateAsDictionary["github_installation_id"] = template.GithubInstallationId
}

return resourceConfigCreate(resourceType, resourceName, templateAsDictionary)
}

t.Run("Full Github template (without SSH keys)", func(t *testing.T) {
template := client.Template{
Id: "id0",
Expand Down Expand Up @@ -80,23 +126,6 @@ func TestUnitTemplateResource(t *testing.T) {
)
}

fullTemplateResourceConfig := func(resourceType string, resourceName string, template client.Template) string {
return resourceConfigCreate(resourceType, resourceName, map[string]interface{}{
"name": template.Name,
"description": template.Description,
"repository": template.Repository,
"path": template.Path,
"revision": template.Revision,
"type": template.Type,
"retries_on_deploy": template.Retry.OnDeploy.Times,
"retry_on_deploy_only_when_matches_regex": template.Retry.OnDeploy.ErrorRegex,
"retries_on_destroy": template.Retry.OnDestroy.Times,
"retry_on_destroy_only_when_matches_regex": template.Retry.OnDestroy.ErrorRegex,
"github_installation_id": template.GithubInstallationId,
"terraform_version": template.TerraformVersion,
})
}

testCase := resource.TestCase{
Steps: []resource.TestStep{
{
Expand Down Expand Up @@ -208,24 +237,6 @@ func TestUnitTemplateResource(t *testing.T) {
)
}

fullTemplateResourceConfig := func(resourceType string, resourceName string, template client.Template) string {
return resourceConfigCreate(resourceType, resourceName, map[string]interface{}{
"name": template.Name,
"description": template.Description,
"repository": template.Repository,
"path": template.Path,
"revision": template.Revision,
"type": template.Type,
"retries_on_deploy": template.Retry.OnDeploy.Times,
"retry_on_deploy_only_when_matches_regex": template.Retry.OnDeploy.ErrorRegex,
"retries_on_destroy": template.Retry.OnDestroy.Times,
"retry_on_destroy_only_when_matches_regex": template.Retry.OnDestroy.ErrorRegex,
"token_id": template.TokenId,
"gitlab_project_id": template.GitlabProjectId,
"terraform_version": template.TerraformVersion,
})
}

testCase := resource.TestCase{
Steps: []resource.TestStep{
{
Expand Down Expand Up @@ -483,15 +494,18 @@ func TestUnitTemplateResource(t *testing.T) {
Steps: []resource.TestStep{
{
Config: resourceConfigCreate(resourceType, resourceName, map[string]interface{}{"name": "test", "repository": "env0/test", regexAttribute: "bla"}),
ExpectError: regexp.MustCompile(fmt.Sprintf("`%s,%s` must be specified", timesAttribute, regexAttribute)),
ExpectError: regexp.MustCompile(fmt.Sprintf("`%s,%s`\\s+must\\s+be\\s+specified", timesAttribute, regexAttribute)),
},
},
})
}

for _, testCase := range testCases {
runUnitTest(t, testCase, func(mockFunc *client.MockApiClientInterface) {})
}
})

t.Run("Gitlab and Github template", func(t *testing.T) {
t.Run("Mixed Gitlab and Github template", func(t *testing.T) {
var testCases []resource.TestCase

testCases = append(testCases, resource.TestCase{
Expand All @@ -507,4 +521,42 @@ func TestUnitTemplateResource(t *testing.T) {
runUnitTest(t, testCase, func(mockFunc *client.MockApiClientInterface) {})
}
})

t.Run("Should not trigger terraform changes when gitlab_project_id is provided", func(t *testing.T) {
template := client.Template{
Id: "id0",
Name: "template0",
Repository: "env0/repo",
Type: "terraform",
GitlabProjectId: 123456,
TokenId: "abcdefg",
TerraformVersion: defaultVersion,
}

tfConfig := fullTemplateResourceConfig(resourceType, resourceName, template)
var testCase = resource.TestCase{
Steps: []resource.TestStep{
{
Config: tfConfig,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceFullName, "gitlab_project_id", strconv.Itoa(template.GitlabProjectId)),
),
},
{
PlanOnly: true,
ExpectNonEmptyPlan: false,
Config: tfConfig,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceFullName, "gitlab_project_id", strconv.Itoa(template.GitlabProjectId)),
),
},
},
}

runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) {
mock.EXPECT().Template(template.Id).Times(3).Return(template, nil) // 1 after create, 1 before update, 1 after update
mock.EXPECT().TemplateCreate(gomock.Any()).Times(1).Return(template, nil)
mock.EXPECT().TemplateDelete(template.Id).Times(1).Return(nil)
})
})
}

0 comments on commit a399839

Please sign in to comment.