Skip to content

Commit

Permalink
Add handling of multi line variables description (#3269)
Browse files Browse the repository at this point in the history
* Fix for scaffold execution

* Template update

* Multiline description handling and tests
  • Loading branch information
denis256 authored Jul 16, 2024
1 parent a2f630e commit 081fce5
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 69 deletions.
14 changes: 14 additions & 0 deletions cli/commands/scaffold/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,14 @@ inputs = {
# Required input variables
# --------------------------------------------------------------------------------------------------------------------
{{ range .requiredVariables }}
{{- if eq 1 (regexSplit "\n" .Description -1 | len ) }}
# Description: {{ .Description }}
{{- else }}
# Description:
{{- range $line := regexSplit "\n" .Description -1 }}
# {{ $line | indent 2 }}
{{- end }}
{{- end }}
# Type: {{ .Type }}
{{ .Name }} = {{ .DefaultValuePlaceholder }} # TODO: fill in value
{{ end }}
Expand All @@ -71,7 +78,14 @@ inputs = {
# Uncomment the ones you wish to set
# --------------------------------------------------------------------------------------------------------------------
{{ range .optionalVariables }}
{{- if eq 1 (regexSplit "\n" .Description -1 | len ) }}
# Description: {{ .Description }}
{{- else }}
# Description:
{{- range $line := regexSplit "\n" .Description -1 }}
# {{ $line | indent 2 }}
{{- end }}
{{- end }}
# Type: {{ .Type }}
# {{ .Name }} = {{ .DefaultValue }}
{{ end }}
Expand Down
5 changes: 4 additions & 1 deletion test/fixture-scaffold/scaffold-module/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ variable "enabled" {

variable "open_port" {
type = number
description = "Port to open"
description = <<-EOF
Port to be opened in the security group
Can be a single port or a range
EOF
}

variable "enable_backups" {
Expand Down
147 changes: 79 additions & 68 deletions test/integration_scaffold_test.go
Original file line number Diff line number Diff line change
@@ -1,168 +1,144 @@
package test

import (
"bytes"
"fmt"
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"

"github.com/gruntwork-io/terragrunt/util"

"github.com/stretchr/testify/require"
)

const (
TEST_SCAFOLD_MODULE = "https://github.com/gruntwork-io/terragrunt.git//test/fixture-scaffold/scaffold-module"
TEST_SCAFOLD_MODULE_GIT = "[email protected]:gruntwork-io/terragrunt.git//test/fixture-scaffold/scaffold-module"
TEST_SCAFOLD_MODULE_SHORT = "github.com/gruntwork-io/terragrunt.git//test/fixture-inputs"
TEST_SCAFOLD_TEMPLATE_MODULE = "[email protected]:gruntwork-io/terragrunt.git//test/fixture-scaffold/module-with-template"
TEST_SCAFOLD_EXTERNAL_TEMPLATE_MODULE = "[email protected]:gruntwork-io/terragrunt.git//test/fixture-scaffold/external-template"
TEST_SCAFFOLD_MODULE = "https://github.com/gruntwork-io/terragrunt.git//test/fixture-scaffold/scaffold-module"
TEST_SCAFFOLD_MODULE_GIT = "[email protected]:gruntwork-io/terragrunt.git//test/fixture-scaffold/scaffold-module"
TEST_SCAFFOLD_MODULE_SHORT = "github.com/gruntwork-io/terragrunt.git//test/fixture-inputs"
TEST_SCAFFOLD_TEMPLATE_MODULE = "[email protected]:gruntwork-io/terragrunt.git//test/fixture-scaffold/module-with-template"
TEST_SCAFFOLD_EXTERNAL_TEMPLATE_MODULE = "[email protected]:gruntwork-io/terragrunt.git//test/fixture-scaffold/external-template"
TEST_SCAFFOLD_LOCAL_MODULE = "fixture-scaffold/scaffold-module"
TEST_SCAFFOLD_3RD_PARTY_MODULE = "git::https://github.com/Azure/terraform-azurerm-avm-res-compute-virtualmachine.git//.?ref=v0.15.0"
)

func TestTerragruntScaffoldModule(t *testing.T) {
func TestScaffoldModule(t *testing.T) {
t.Parallel()

tmpEnvPath, err := os.MkdirTemp("", "terragrunt-scaffold-test")
require.NoError(t, err)

stdout := bytes.Buffer{}
stderr := bytes.Buffer{}

err = runTerragruntCommand(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold %s", tmpEnvPath, TEST_SCAFOLD_MODULE), &stdout, &stderr)
_, stderr, err := runTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold %s", tmpEnvPath, TEST_SCAFFOLD_MODULE))
require.NoError(t, err)
require.Contains(t, stderr.String(), "Scaffolding completed")
require.Contains(t, stderr, "Scaffolding completed")
require.FileExists(t, fmt.Sprintf("%s/terragrunt.hcl", tmpEnvPath))
}

func TestTerragruntScaffoldModuleShortUrl(t *testing.T) {
func TestScaffoldModuleShortUrl(t *testing.T) {
t.Parallel()

tmpEnvPath, err := os.MkdirTemp("", "terragrunt-scaffold-test")
require.NoError(t, err)

stdout := bytes.Buffer{}
stderr := bytes.Buffer{}

err = runTerragruntCommand(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold %s", tmpEnvPath, TEST_SCAFOLD_MODULE_SHORT), &stdout, &stderr)
_, stderr, err := runTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold %s", tmpEnvPath, TEST_SCAFFOLD_MODULE_SHORT))
require.NoError(t, err)
require.Contains(t, stderr.String(), "Scaffolding completed")
require.Contains(t, stderr, "Scaffolding completed")
// check that find_in_parent_folders is generated in terragrunt.hcl
content, err := util.ReadFileAsString(fmt.Sprintf("%s/terragrunt.hcl", tmpEnvPath))
require.NoError(t, err)
require.Contains(t, content, "find_in_parent_folders")
}

func TestTerragruntScaffoldModuleShortUrlNoRootInclude(t *testing.T) {
func TestScaffoldModuleShortUrlNoRootInclude(t *testing.T) {
t.Parallel()

tmpEnvPath, err := os.MkdirTemp("", "terragrunt-scaffold-test")
require.NoError(t, err)

stdout := bytes.Buffer{}
stderr := bytes.Buffer{}

err = runTerragruntCommand(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold %s --var=EnableRootInclude=false", tmpEnvPath, TEST_SCAFOLD_MODULE_SHORT), &stdout, &stderr)
_, stderr, err := runTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold %s --var=EnableRootInclude=false", tmpEnvPath, TEST_SCAFFOLD_MODULE_SHORT))
require.NoError(t, err)
require.Contains(t, stderr.String(), "Scaffolding completed")
require.Contains(t, stderr, "Scaffolding completed")
// check that find_in_parent_folders is NOT generated in terragrunt.hcl
content, err := util.ReadFileAsString(fmt.Sprintf("%s/terragrunt.hcl", tmpEnvPath))
require.NoError(t, err)
require.NotContains(t, content, "find_in_parent_folders")
}

func TestTerragruntScaffoldModuleDifferentRevision(t *testing.T) {
func TestScaffoldModuleDifferentRevision(t *testing.T) {
t.Parallel()

tmpEnvPath, err := os.MkdirTemp("", "terragrunt-scaffold-test")
require.NoError(t, err)

stdout := bytes.Buffer{}
stderr := bytes.Buffer{}

err = runTerragruntCommand(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold %s --var=Ref=v0.53.1", tmpEnvPath, TEST_SCAFOLD_MODULE_SHORT), &stdout, &stderr)
_, stderr, err := runTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold %s --var=Ref=v0.53.1", tmpEnvPath, TEST_SCAFFOLD_MODULE_SHORT))

require.NoError(t, err)
require.Contains(t, stderr.String(), "git::https://github.com/gruntwork-io/terragrunt.git//test/fixture-inputs?ref=v0.53.1")
require.Contains(t, stderr.String(), "Scaffolding completed")
require.Contains(t, stderr, "git::https://github.com/gruntwork-io/terragrunt.git//test/fixture-inputs?ref=v0.53.1")
require.Contains(t, stderr, "Scaffolding completed")
}

func TestTerragruntScaffoldModuleDifferentRevisionAndSsh(t *testing.T) {
func TestScaffoldModuleDifferentRevisionAndSsh(t *testing.T) {
t.Parallel()

tmpEnvPath, err := os.MkdirTemp("", "terragrunt-scaffold-test")
require.NoError(t, err)

stdout := bytes.Buffer{}
stderr := bytes.Buffer{}

err = runTerragruntCommand(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold %s --var=Ref=v0.53.1 --var=SourceUrlType=git-ssh", tmpEnvPath, TEST_SCAFOLD_MODULE_SHORT), &stdout, &stderr)
_, stderr, err := runTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold %s --var=Ref=v0.53.1 --var=SourceUrlType=git-ssh", tmpEnvPath, TEST_SCAFFOLD_MODULE_SHORT))
require.NoError(t, err)
require.Contains(t, stderr.String(), "git::ssh://[email protected]/gruntwork-io/terragrunt.git//test/fixture-inputs?ref=v0.53.1")
require.Contains(t, stderr.String(), "Scaffolding completed")
require.Contains(t, stderr, "git::ssh://[email protected]/gruntwork-io/terragrunt.git//test/fixture-inputs?ref=v0.53.1")
require.Contains(t, stderr, "Scaffolding completed")
}

func TestTerragruntScaffoldModuleSsh(t *testing.T) {
func TestScaffoldModuleSsh(t *testing.T) {
t.Parallel()

tmpEnvPath, err := os.MkdirTemp("", "terragrunt-scaffold-test")
require.NoError(t, err)

stdout := bytes.Buffer{}
stderr := bytes.Buffer{}

err = runTerragruntCommand(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold %s", tmpEnvPath, TEST_SCAFOLD_MODULE_GIT), &stdout, &stderr)
_, stderr, err := runTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold %s", tmpEnvPath, TEST_SCAFFOLD_MODULE_GIT))
require.NoError(t, err)
require.Contains(t, stderr.String(), "Scaffolding completed")
require.Contains(t, stderr, "Scaffolding completed")
}

func TestTerragruntScaffoldModuleTemplate(t *testing.T) {
func TestScaffoldModuleTemplate(t *testing.T) {
t.Parallel()

tmpEnvPath, err := os.MkdirTemp("", "terragrunt-scaffold-test")
require.NoError(t, err)

stdout := bytes.Buffer{}
stderr := bytes.Buffer{}

err = runTerragruntCommand(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold %s", tmpEnvPath, TEST_SCAFOLD_TEMPLATE_MODULE), &stdout, &stderr)
_, stderr, err := runTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold %s", tmpEnvPath, TEST_SCAFFOLD_TEMPLATE_MODULE))
require.NoError(t, err)
require.Contains(t, stderr.String(), "Scaffolding completed")
require.Contains(t, stderr, "Scaffolding completed")
// check that exists file from .boilerplate dir
require.FileExists(t, fmt.Sprintf("%s/template-file.txt", tmpEnvPath))
}

func TestTerragruntScaffoldModuleExternalTemplate(t *testing.T) {
func TestScaffoldModuleExternalTemplate(t *testing.T) {
t.Parallel()

tmpEnvPath, err := os.MkdirTemp("", "terragrunt-scaffold-test")
require.NoError(t, err)

stdout := bytes.Buffer{}
stderr := bytes.Buffer{}

err = runTerragruntCommand(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold %s %s", tmpEnvPath, TEST_SCAFOLD_MODULE_GIT, TEST_SCAFOLD_EXTERNAL_TEMPLATE_MODULE), &stdout, &stderr)
_, stderr, err := runTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold %s %s", tmpEnvPath, TEST_SCAFFOLD_MODULE_GIT, TEST_SCAFFOLD_EXTERNAL_TEMPLATE_MODULE))
require.NoError(t, err)
require.Contains(t, stderr.String(), "Scaffolding completed")
require.Contains(t, stderr, "Scaffolding completed")
// check that exists file from external template
require.FileExists(t, fmt.Sprintf("%s/external-template.txt", tmpEnvPath))
}

func TestTerragruntScaffoldErrorNoModuleUrl(t *testing.T) {
func TestScaffoldErrorNoModuleUrl(t *testing.T) {
t.Parallel()

tmpEnvPath, err := os.MkdirTemp("", "terragrunt-scaffold-test")
require.NoError(t, err)

stdout := bytes.Buffer{}
stderr := bytes.Buffer{}

err = runTerragruntCommand(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold", tmpEnvPath), &stdout, &stderr)
_, _, err = runTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold", tmpEnvPath))
require.Error(t, err)
require.Contains(t, err.Error(), "No module URL passed")
}

func TestTerragruntScaffoldModuleVarFile(t *testing.T) {
func TestScaffoldModuleVarFile(t *testing.T) {
t.Parallel()
// generate var file with specific version, without root include and use GIT/SSH to clone module.
varFileContent := `
Expand All @@ -177,14 +153,49 @@ SourceUrlType: "git-ssh"
tmpEnvPath, err := os.MkdirTemp("", "terragrunt-scaffold-test")
require.NoError(t, err)

stdout := bytes.Buffer{}
stderr := bytes.Buffer{}

err = runTerragruntCommand(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold %s --var-file=%s", tmpEnvPath, TEST_SCAFOLD_MODULE_SHORT, varFile), &stdout, &stderr)
_, stderr, err := runTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold %s --var-file=%s", tmpEnvPath, TEST_SCAFFOLD_MODULE_SHORT, varFile))
require.NoError(t, err)
require.Contains(t, stderr.String(), "git::ssh://[email protected]/gruntwork-io/terragrunt.git//test/fixture-inputs?ref=v0.53.1")
require.Contains(t, stderr.String(), "Scaffolding completed")
require.Contains(t, stderr, "git::ssh://[email protected]/gruntwork-io/terragrunt.git//test/fixture-inputs?ref=v0.53.1")
require.Contains(t, stderr, "Scaffolding completed")
content, err := util.ReadFileAsString(fmt.Sprintf("%s/terragrunt.hcl", tmpEnvPath))
require.NoError(t, err)
require.NotContains(t, content, "find_in_parent_folders")
}

func TestScaffoldLocalModule(t *testing.T) {
t.Parallel()

tmpEnvPath, err := os.MkdirTemp("", "terragrunt-scaffold-test")
require.NoError(t, err)

workingDir, err := os.Getwd()
require.NoError(t, err)

_, stderr, err := runTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold %s", tmpEnvPath, fmt.Sprintf("%s//%s", workingDir, TEST_SCAFFOLD_LOCAL_MODULE)))
require.NoError(t, err)
require.Contains(t, stderr, "Scaffolding completed")
require.FileExists(t, fmt.Sprintf("%s/terragrunt.hcl", tmpEnvPath))
}

func TestScaffold3rdPartyModule(t *testing.T) {
t.Parallel()

tmpRoot, err := os.MkdirTemp("", "terragrunt-scaffold-test")
require.NoError(t, err)
tmpEnvPath := filepath.Join(tmpRoot, "app")
err = os.MkdirAll(tmpEnvPath, 0755)
assert.NoError(t, err)

// create "root" terragrunt.hcl
err = os.WriteFile(filepath.Join(tmpRoot, "terragrunt.hcl"), []byte(""), 0644)
assert.NoError(t, err)

_, stderr, err := runTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold %s", tmpEnvPath, TEST_SCAFFOLD_3RD_PARTY_MODULE))
require.NoError(t, err)
require.Contains(t, stderr, "Scaffolding completed")
require.FileExists(t, fmt.Sprintf("%s/terragrunt.hcl", tmpEnvPath))

// validate the generated files
_, _, err = runTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s hclvalidate", tmpEnvPath))
require.NoError(t, err)
}

0 comments on commit 081fce5

Please sign in to comment.