-
Notifications
You must be signed in to change notification settings - Fork 14
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 running terragrunt with opentofu #785
Changes from all commits
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 |
---|---|---|
|
@@ -1899,9 +1899,11 @@ func TestUnitEnvironmentWithoutTemplateResource(t *testing.T) { | |
ErrorRegex: "RetryMeForDestroy.*", | ||
}, | ||
}, | ||
Type: "terraform", | ||
Type: "terragrunt", | ||
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. This impacts an environment with a template. |
||
GithubInstallationId: 2, | ||
TerraformVersion: "0.12.25", | ||
TerragruntVersion: "0.26.1", | ||
TerragruntTfBinary: "terraform", | ||
} | ||
|
||
environmentCreatePayload := client.EnvironmentCreate{ | ||
|
@@ -1946,7 +1948,7 @@ func TestUnitEnvironmentWithoutTemplateResource(t *testing.T) { | |
TokenId: updatedTemplate.TokenId, | ||
Path: updatedTemplate.Path, | ||
Revision: updatedTemplate.Revision, | ||
Type: "terraform", | ||
Type: "terragrunt", | ||
Retry: updatedTemplate.Retry, | ||
TerraformVersion: updatedTemplate.TerraformVersion, | ||
BitbucketClientKey: updatedTemplate.BitbucketClientKey, | ||
|
@@ -1956,6 +1958,7 @@ func TestUnitEnvironmentWithoutTemplateResource(t *testing.T) { | |
TerragruntVersion: updatedTemplate.TerragruntVersion, | ||
IsTerragruntRunAll: updatedTemplate.IsTerragruntRunAll, | ||
OrganizationId: updatedTemplate.OrganizationId, | ||
TerragruntTfBinary: updatedTemplate.TerragruntTfBinary, | ||
} | ||
|
||
createPayload := client.EnvironmentCreateWithoutTemplate{ | ||
|
@@ -1964,6 +1967,16 @@ func TestUnitEnvironmentWithoutTemplateResource(t *testing.T) { | |
} | ||
|
||
createEnvironmentResourceConfig := func(environment client.Environment, template client.Template) string { | ||
terragruntVersion := "" | ||
if template.TerragruntVersion != "" { | ||
terragruntVersion = "terragrunt_version = \"" + template.TerragruntVersion + "\"" | ||
} | ||
|
||
terragruntTfBinary := "" | ||
if template.TerragruntTfBinary != "" { | ||
terragruntTfBinary = "terragrunt_tf_binary = \"" + template.TerragruntTfBinary + "\"" | ||
} | ||
|
||
return fmt.Sprintf(` | ||
resource "%s" "%s" { | ||
name = "%s" | ||
|
@@ -1984,6 +1997,8 @@ func TestUnitEnvironmentWithoutTemplateResource(t *testing.T) { | |
retry_on_destroy_only_when_matches_regex = "%s" | ||
description = "%s" | ||
github_installation_id = %d | ||
%s | ||
%s | ||
} | ||
}`, | ||
resourceType, resourceName, | ||
|
@@ -2003,6 +2018,8 @@ func TestUnitEnvironmentWithoutTemplateResource(t *testing.T) { | |
template.Retry.OnDestroy.ErrorRegex, | ||
template.Description, | ||
template.GithubInstallationId, | ||
terragruntVersion, | ||
terragruntTfBinary, | ||
) | ||
} | ||
|
||
|
@@ -2047,6 +2064,8 @@ func TestUnitEnvironmentWithoutTemplateResource(t *testing.T) { | |
resource.TestCheckResourceAttr(accessor, "without_template_settings.0.terraform_version", updatedTemplate.TerraformVersion), | ||
resource.TestCheckResourceAttr(accessor, "without_template_settings.0.type", updatedTemplate.Type), | ||
resource.TestCheckResourceAttr(accessor, "without_template_settings.0.path", updatedTemplate.Path), | ||
resource.TestCheckResourceAttr(accessor, "without_template_settings.0.terragrunt_version", updatedTemplate.TerragruntVersion), | ||
resource.TestCheckResourceAttr(accessor, "without_template_settings.0.terragrunt_tf_binary", updatedTemplate.TerragruntTfBinary), | ||
resource.TestCheckResourceAttr(accessor, "without_template_settings.0.revision", updatedTemplate.Revision), | ||
resource.TestCheckResourceAttr(accessor, "without_template_settings.0.retries_on_deploy", strconv.Itoa(updatedTemplate.Retry.OnDeploy.Times)), | ||
resource.TestCheckResourceAttr(accessor, "without_template_settings.0.retry_on_deploy_only_when_matches_regex", updatedTemplate.Retry.OnDeploy.ErrorRegex), | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -239,6 +239,12 @@ func getTemplateSchema(prefix string) map[string]*schema.Schema { | |
ConflictsWith: allVCSAttributesBut("helm_chart_name", "is_helm_repository"), | ||
RequiredWith: requiredWith("helm_chart_name"), | ||
}, | ||
"terragrunt_tf_binary": { | ||
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. Could not set a deault value to "OpenTofu". I tried a few options. At the end I had to manually handle this unique use-case. |
||
Type: schema.TypeString, | ||
Optional: true, | ||
Description: "the binary to use if the template type is 'terragrunt'. Valid values 'opentofu' and 'terraform'. For new templates defaults to 'opentofu'", | ||
ValidateDiagFunc: NewStringInValidator([]string{"opentofu", "terraform"}), | ||
}, | ||
} | ||
|
||
if prefix == "" { | ||
|
@@ -373,12 +379,30 @@ func templateCreatePayloadFromParameters(prefix string, d *schema.ResourceData) | |
return payload, diag.Errorf("schema resource data serialization failed: %v", err) | ||
} | ||
|
||
isNew := d.IsNewResource() | ||
|
||
tokenIdKey := "token_id" | ||
isAzureDevOpsKey := "is_azure_devops" | ||
terragruntTfBinaryKey := "terragrunt_tf_binary" | ||
templateTypeKey := "type" | ||
|
||
if prefix != "" { | ||
tokenIdKey = prefix + "." + tokenIdKey | ||
isAzureDevOpsKey = prefix + "." + isAzureDevOpsKey | ||
terragruntTfBinaryKey = prefix + "." + terragruntTfBinaryKey | ||
templateTypeKey = prefix + "." + templateTypeKey | ||
} | ||
|
||
if templateType, ok := d.GetOk(templateTypeKey); ok { | ||
// If the user has set a value - use it. | ||
if terragruntTfBinary := d.Get(terragruntTfBinaryKey).(string); terragruntTfBinary != "" { | ||
payload.TerragruntTfBinary = terragruntTfBinary | ||
} else { | ||
// No value was set - if it's a new template resource of type 'terragrunt' - default to 'opentofu' | ||
if templateType.(string) == "terragrunt" && isNew { | ||
payload.TerragruntTfBinary = "opentofu" | ||
} | ||
} | ||
} | ||
|
||
// IsGitLab is implicitly assumed to be true if tokenId is non-empty. Unless AzureDevOps is explicitly used. | ||
|
@@ -401,11 +425,22 @@ func templateCreatePayloadFromParameters(prefix string, d *schema.ResourceData) | |
// Reads template and writes to the resource data. | ||
func templateRead(prefix string, template client.Template, d *schema.ResourceData) error { | ||
pathPrefix := "path" | ||
terragruntTfBinaryPrefix := "terragrunt_tf_binary" | ||
|
||
if prefix != "" { | ||
pathPrefix = prefix + ".0.path" | ||
pathPrefix = prefix + ".0." + pathPrefix | ||
terragruntTfBinaryPrefix = prefix + ".0." + terragruntTfBinaryPrefix | ||
} | ||
|
||
path, pathOk := d.GetOk(pathPrefix) | ||
terragruntTfBinary := d.Get(terragruntTfBinaryPrefix).(string) | ||
|
||
// If this value isn't set, ignore whatever is returned from the response. | ||
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. Added a long explanation here. Hopefully it's clear enough. |
||
// This helps avoid drifts when defaulting to 'opentofu' for new 'terragrunt' templates, and 'terraform' for existing 'terragrunt' templates. | ||
// 'template.TerragruntTfBinary' field is set to 'omitempty'. Therefore, the state isn't modified if `template.TerragruntTfBinary` is an empty string. | ||
if terragruntTfBinary == "" { | ||
template.TerragruntTfBinary = "" | ||
} | ||
|
||
if err := writeResourceDataEx(prefix, &template, d); err != nil { | ||
return fmt.Errorf("schema resource data serialization failed: %v", err) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,9 +35,11 @@ func TestUnitTemplateResource(t *testing.T) { | |
ErrorRegex: "RetryMeForDestroy.*", | ||
}, | ||
}, | ||
Type: "terraform", | ||
Type: "terragrunt", | ||
IsGitlabEnterprise: true, | ||
TerraformVersion: "0.12.24", | ||
TerragruntVersion: "0.35.1", | ||
TerragruntTfBinary: "opentofu", | ||
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. In this case, user has set nothing. Defaults to opentofu when the template is created. |
||
} | ||
gleeUpdatedTemplate := client.Template{ | ||
Id: gleeTemplate.Id, | ||
|
@@ -677,6 +679,10 @@ func TestUnitTemplateResource(t *testing.T) { | |
OpentofuVersion: templateUseCase.updatedTemplate.OpentofuVersion, | ||
} | ||
|
||
if templateUseCase.template.Type == "terragrunt" { | ||
templateCreatePayload.TerragruntTfBinary = templateUseCase.template.TerragruntTfBinary | ||
} | ||
|
||
if templateUseCase.template.Type != "terraform" && templateUseCase.template.Type != "terragrunt" { | ||
templateCreatePayload.TerraformVersion = "" | ||
updateTemplateCreateTemplate.TerraformVersion = "" | ||
|
@@ -1293,4 +1299,23 @@ func TestUnitTemplateResource(t *testing.T) { | |
|
||
runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) {}) | ||
}) | ||
|
||
t.Run("terragrunt_tf_binary set with a non terragrunt template type", func(t *testing.T) { | ||
testCase := resource.TestCase{ | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: resourceConfigCreate(resourceType, resourceName, map[string]interface{}{ | ||
"name": "template0", | ||
"repository": "env0/repo", | ||
"type": "terraform", | ||
"terraform_version": "0.15.1", | ||
"terragrunt_tf_binary": "opentofu", | ||
}), | ||
ExpectError: regexp.MustCompile(`terragrunt_tf_binary should only be used when the template type is 'terragrunt', but type is 'terraform'`), | ||
}, | ||
}, | ||
} | ||
|
||
runUnitTest(t, testCase, func(mock *client.MockApiClientInterface) {}) | ||
}) | ||
} |
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.
This is to avoid setting
TerragruntTfBinary
without a template of typeterragrunt
.