Skip to content

Commit

Permalink
Merge branch 'main' into chore-manual-approval-#723
Browse files Browse the repository at this point in the history
  • Loading branch information
TomerHeber authored Oct 18, 2023
2 parents 6ec7f3a + c4da1d5 commit 52e1e1f
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 5 deletions.
9 changes: 9 additions & 0 deletions client/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ type Template struct {
UpdatedAt string `json:"updatedAt"`
TerraformVersion string `json:"terraformVersion" tfschema:",omitempty"`
TerragruntVersion string `json:"terragruntVersion,omitempty" tfschema:",omitempty"`
OpentofuVersion string `json:"opentofuVersion,omitempty" tfschema:",omitempty"`
IsDeleted bool `json:"isDeleted,omitempty"`
BitbucketClientKey string `json:"bitbucketClientKey" tfschema:",omitempty"`
IsGithubEnterprise bool `json:"isGitHubEnterprise"`
Expand Down Expand Up @@ -80,6 +81,7 @@ type TemplateCreatePayload struct {
OrganizationId string `json:"organizationId"`
TerraformVersion string `json:"terraformVersion,omitempty"`
TerragruntVersion string `json:"terragruntVersion,omitempty"`
OpentofuVersion string `json:"opentofuVersion,omitempty"`
IsGitlabEnterprise bool `json:"isGitLabEnterprise"`
BitbucketClientKey string `json:"bitbucketClientKey,omitempty"`
IsGithubEnterprise bool `json:"isGitHubEnterprise"`
Expand Down Expand Up @@ -122,6 +124,9 @@ func (payload *TemplateCreatePayload) Invalidate() error {
if payload.Type == "terragrunt" && payload.TerragruntVersion == "" {
return errors.New("must supply terragrunt version")
}
if payload.Type == "opentofu" && payload.OpentofuVersion == "" {
return errors.New("must supply opentofu version")
}

if payload.IsTerragruntRunAll {
if payload.Type != "terragrunt" {
Expand Down Expand Up @@ -163,6 +168,10 @@ func (payload *TemplateCreatePayload) Invalidate() error {
payload.TerraformVersion = ""
}

if payload.Type != "opentofu" {
payload.OpentofuVersion = ""
}

return nil
}

Expand Down
2 changes: 1 addition & 1 deletion docs/data-sources/template.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ data "env0_template" "example" {
- `retry_on_destroy_only_when_matches_regex` (String) if specified, will only retry (on destroy) if error matches specified regex
- `revision` (String) source code revision (branch / tag) to use
- `terraform_version` (String) terraform version to use
- `type` (String) template type (allowed values: terraform, terragrunt, pulumi, k8s, workflow, cloudformation, helm)
- `type` (String) template type (allowed values: terraform, terragrunt, pulumi, k8s, workflow, cloudformation, helm, opentofu)

<a id="nestedblock--ssh_keys"></a>
### Nested Schema for `ssh_keys`
Expand Down
3 changes: 2 additions & 1 deletion docs/resources/environment.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ Optional:
- `is_gitlab_enterprise` (Boolean) true if this template uses gitlab enterprise repository
- `is_helm_repository` (Boolean) true if this template integrates with a helm repository
- `is_terragrunt_run_all` (Boolean) true if this template should execute run-all commands on multiple modules (check https://terragrunt.gruntwork.io/docs/features/execute-terraform-commands-on-multiple-modules-at-once/#the-run-all-command for additional details). Can only be true with "terragrunt" template type and terragrunt version 0.28.1 and above
- `opentofu_version` (String) the Opentofu version to use (example: 0.36.5)
- `path` (String) terraform / terragrunt file folder inside source code
- `retries_on_deploy` (Number) number of times to retry when deploying an environment based on this template
- `retries_on_destroy` (Number) number of times to retry when destroying an environment based on this template
Expand All @@ -178,7 +179,7 @@ Optional:
- `terraform_version` (String) the Terraform version to use (example: 0.15.1). Setting to `RESOLVE_FROM_TERRAFORM_CODE` defaults to the version of `terraform.required_version` during run-time (resolve from terraform code). Setting to `latest`, the version used will be the most recent one available for Terraform.
- `terragrunt_version` (String) the Terragrunt version to use (example: 0.36.5)
- `token_id` (String) the git token id to be used
- `type` (String) template type (allowed values: terraform, terragrunt, pulumi, k8s, workflow, cloudformation, helm)
- `type` (String) template type (allowed values: terraform, terragrunt, pulumi, k8s, workflow, cloudformation, helm, opentofu)

Read-Only:

Expand Down
3 changes: 2 additions & 1 deletion docs/resources/template.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ resource "env0_template_project_assignment" "assignment" {
- `is_gitlab_enterprise` (Boolean) true if this template uses gitlab enterprise repository
- `is_helm_repository` (Boolean) true if this template integrates with a helm repository
- `is_terragrunt_run_all` (Boolean) true if this template should execute run-all commands on multiple modules (check https://terragrunt.gruntwork.io/docs/features/execute-terraform-commands-on-multiple-modules-at-once/#the-run-all-command for additional details). Can only be true with "terragrunt" template type and terragrunt version 0.28.1 and above
- `opentofu_version` (String) the Opentofu version to use (example: 0.36.5)
- `path` (String) terraform / terragrunt file folder inside source code
- `retries_on_deploy` (Number) number of times to retry when deploying an environment based on this template
- `retries_on_destroy` (Number) number of times to retry when destroying an environment based on this template
Expand All @@ -85,7 +86,7 @@ resource "env0_template_project_assignment" "assignment" {
- `terraform_version` (String) the Terraform version to use (example: 0.15.1). Setting to `RESOLVE_FROM_TERRAFORM_CODE` defaults to the version of `terraform.required_version` during run-time (resolve from terraform code). Setting to `latest`, the version used will be the most recent one available for Terraform.
- `terragrunt_version` (String) the Terragrunt version to use (example: 0.36.5)
- `token_id` (String) the git token id to be used
- `type` (String) template type (allowed values: terraform, terragrunt, pulumi, k8s, workflow, cloudformation, helm)
- `type` (String) template type (allowed values: terraform, terragrunt, pulumi, k8s, workflow, cloudformation, helm, opentofu)

### Read-Only

Expand Down
7 changes: 7 additions & 0 deletions env0/resource_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ var allowedTemplateTypes = []string{
"workflow",
"cloudformation",
"helm",
"opentofu",
}

func getTemplateSchema(prefix string) map[string]*schema.Schema {
Expand Down Expand Up @@ -172,6 +173,12 @@ func getTemplateSchema(prefix string) map[string]*schema.Schema {
ValidateDiagFunc: NewRegexValidator(`^[0-9]\.[0-9]{1,2}\.[0-9]{1,2}$`),
Optional: true,
},
"opentofu_version": {
Type: schema.TypeString,
Description: "the Opentofu version to use (example: 0.36.5)",
ValidateDiagFunc: NewRegexValidator(`^(?:[0-9]\.[0-9]{1,2}\.[0-9]{1,2})|1\.6\.0-alpha$`),
Optional: true,
},
"is_gitlab_enterprise": {
Type: schema.TypeBool,
Description: "true if this template uses gitlab enterprise repository",
Expand Down
94 changes: 92 additions & 2 deletions env0/resource_template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,45 @@ func TestUnitTemplateResource(t *testing.T) {
TerraformVersion: "0.12.24",
}

opentofuTemplate := client.Template{
Id: "opentofu",
Name: "template0",
Description: "description0",
Repository: "env0/repo",
Type: "opentofu",
OpentofuVersion: "1.6.0-alpha",
TerraformVersion: "0.15.1",
Retry: client.TemplateRetry{
OnDeploy: &client.TemplateRetryOn{
Times: 2,
ErrorRegex: "RetryMeForDeploy.*",
},
OnDestroy: &client.TemplateRetryOn{
Times: 1,
ErrorRegex: "RetryMeForDestroy.*",
},
},
}
opentofuUpdatedTemplate := client.Template{
Id: opentofuTemplate.Id,
Name: "new-name",
Description: "new-description",
Repository: "env0/repo-new",
Type: "opentofu",
OpentofuVersion: "1.7.0",
TerraformVersion: "0.15.1",
Retry: client.TemplateRetry{
OnDeploy: &client.TemplateRetryOn{
Times: 2,
ErrorRegex: "RetryMeForDeploy.*",
},
OnDestroy: &client.TemplateRetryOn{
Times: 1,
ErrorRegex: "RetryMeForDestroy.*",
},
},
}

fullTemplateResourceConfig := func(resourceType string, resourceName string, template client.Template) string {
templateAsDictionary := map[string]interface{}{
"name": template.Name,
Expand Down Expand Up @@ -440,6 +479,9 @@ func TestUnitTemplateResource(t *testing.T) {
if template.TerraformVersion != "" {
templateAsDictionary["terraform_version"] = template.TerraformVersion
}
if template.OpentofuVersion != "" {
templateAsDictionary["opentofu_version"] = template.OpentofuVersion
}
if template.TokenId != "" {
templateAsDictionary["token_id"] = template.TokenId
}
Expand Down Expand Up @@ -516,6 +558,11 @@ func TestUnitTemplateResource(t *testing.T) {
terragruntVersionAssertion = resource.TestCheckNoResourceAttr(resourceFullName, "terragrunt_version")
}

opentofuVersionAssertion := resource.TestCheckResourceAttr(resourceFullName, "opentofu_version", template.OpentofuVersion)
if template.OpentofuVersion == "" {
opentofuVersionAssertion = resource.TestCheckNoResourceAttr(resourceFullName, "opentofu_version")
}

githubInstallationIdAssertion := resource.TestCheckResourceAttr(resourceFullName, "github_installation_id", strconv.Itoa(template.GithubInstallationId))
if template.GithubInstallationId == 0 {
githubInstallationIdAssertion = resource.TestCheckNoResourceAttr(resourceFullName, "github_installation_id")
Expand Down Expand Up @@ -544,6 +591,7 @@ func TestUnitTemplateResource(t *testing.T) {
githubInstallationIdAssertion,
helmChartNameAssertion,
pathAssertion,
opentofuVersionAssertion,
resource.TestCheckResourceAttr(resourceFullName, "terraform_version", template.TerraformVersion),
resource.TestCheckResourceAttr(resourceFullName, "is_terragrunt_run_all", strconv.FormatBool(template.IsTerragruntRunAll)),
resource.TestCheckResourceAttr(resourceFullName, "is_azure_devops", strconv.FormatBool(template.IsAzureDevOps)),
Expand All @@ -565,6 +613,7 @@ func TestUnitTemplateResource(t *testing.T) {
{"Cloudformation", cloudformationTemplate, cloudformationUpdatedTemplate},
{"Azure DevOps", azureDevOpsTemplate, azureDevOpsUpdatedTemplate},
{"Helm Chart", helmTemplate, helmUpdatedTemplate},
{"Opentofu", opentofuTemplate, opentofuUpdatedTemplate},
}
for _, templateUseCase := range templateUseCases {
t.Run("Full "+templateUseCase.vcs+" template (without SSH keys)", func(t *testing.T) {
Expand Down Expand Up @@ -599,6 +648,7 @@ func TestUnitTemplateResource(t *testing.T) {
IsAzureDevOps: templateUseCase.template.IsAzureDevOps,
IsHelmRepository: templateUseCase.template.IsHelmRepository,
HelmChartName: templateUseCase.template.HelmChartName,
OpentofuVersion: templateUseCase.template.OpentofuVersion,
}

updateTemplateCreateTemplate := client.TemplateCreatePayload{
Expand All @@ -622,8 +672,9 @@ func TestUnitTemplateResource(t *testing.T) {
TerragruntVersion: templateUseCase.updatedTemplate.TerragruntVersion,
IsTerragruntRunAll: templateUseCase.updatedTemplate.IsTerragruntRunAll,
IsAzureDevOps: templateUseCase.updatedTemplate.IsAzureDevOps,
IsHelmRepository: templateUseCase.template.IsHelmRepository,
HelmChartName: templateUseCase.template.HelmChartName,
IsHelmRepository: templateUseCase.updatedTemplate.IsHelmRepository,
HelmChartName: templateUseCase.updatedTemplate.HelmChartName,
OpentofuVersion: templateUseCase.updatedTemplate.OpentofuVersion,
}

if templateUseCase.template.Type != "terraform" && templateUseCase.template.Type != "terragrunt" {
Expand Down Expand Up @@ -1110,6 +1161,45 @@ func TestUnitTemplateResource(t *testing.T) {
runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) {})
})

t.Run("Invalid Opentofu Version", func(t *testing.T) {
testCase := resource.TestCase{
Steps: []resource.TestStep{
{
Config: resourceConfigCreate(resourceType, resourceName, map[string]interface{}{
"name": "template0",
"repository": "env0/repo",
"type": "opentofu",
"gitlab_project_id": 123456,
"token_id": "abcdefg",
"opentofu_version": "v0.20.1",
}),
ExpectError: regexp.MustCompile("must match pattern"),
},
},
}

runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) {})
})

t.Run("Opentofu type with no Opentofu version", func(t *testing.T) {
testCase := resource.TestCase{
Steps: []resource.TestStep{
{
Config: resourceConfigCreate(resourceType, resourceName, map[string]interface{}{
"name": "template0",
"repository": "env0/repo",
"type": "opentofu",
"gitlab_project_id": 123456,
"token_id": "abcdefg",
}),
ExpectError: regexp.MustCompile("must supply opentofu version"),
},
},
}

runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) {})
})

t.Run("Cloudformation type with no file_name", func(t *testing.T) {
testCase := resource.TestCase{
Steps: []resource.TestStep{
Expand Down
13 changes: 13 additions & 0 deletions tests/integration/004_template/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,19 @@ resource "env0_template" "template_tg" {
terragrunt_version = "0.35.0"
}

resource "env0_template" "template_opentofu" {
name = "Opentofu-${random_string.random.result}"
description = "Template description - OpenTofu and GitHub"
type = "opentofu"
repository = data.env0_template.github_template.repository
github_installation_id = data.env0_template.github_template.github_installation_id
path = "/misc/null-resource"
retries_on_deploy = 3
retry_on_deploy_only_when_matches_regex = "abc"
retries_on_destroy = 1
opentofu_version = "1.6.0"
}

resource "env0_configuration_variable" "in_a_template" {
name = "fake_key"
value = "fake value"
Expand Down

0 comments on commit 52e1e1f

Please sign in to comment.