Skip to content
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

Set custom User Agent for Terraform providers #729

Merged
merged 18 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ builds:
binary: atmos
ldflags:
# Set `atmos` version to the GitHub release tag using Go `ldflags`
- '-s -w -X "github.com/cloudposse/atmos/cmd.Version={{.Version}}"'
- '-s -w -X "github.com/cloudposse/atmos/pkg/version.Version={{.Version}}"'
Cerebrovinny marked this conversation as resolved.
Show resolved Hide resolved

archives:
- format: binary
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ get:
go get

build: get
env $(if $(GOOS),GOOS=$(GOOS)) $(if $(GOARCH),GOARCH=$(GOARCH)) go build -o build/atmos -v -ldflags "-X 'github.com/cloudposse/atmos/cmd.Version=${VERSION}'"
env $(if $(GOOS),GOOS=$(GOOS)) $(if $(GOARCH),GOARCH=$(GOARCH)) go build -o build/atmos -v -ldflags "-X 'github.com/cloudposse/atmos/pkg/version.Version=${VERSION}'"

version: build
chmod +x ./build/atmos
Expand Down
2 changes: 1 addition & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

version="0.0.1"
aknysh marked this conversation as resolved.
Show resolved Hide resolved

go build -o build/atmos -v -ldflags "-X 'github.com/cloudposse/atmos/cmd.Version=$version'"
go build -o build/atmos -v -ldflags "-X 'github.com/cloudposse/atmos/version.Version=$version'"

# https://www.digitalocean.com/community/tutorials/using-ldflags-to-set-version-information-for-go-applications
# https://blog.kowalczyk.info/article/vEja/embedding-build-number-in-go-executable.html
Expand Down
7 changes: 3 additions & 4 deletions cmd/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ import (
tuiUtils "github.com/cloudposse/atmos/internal/tui/utils"
"github.com/cloudposse/atmos/pkg/schema"
u "github.com/cloudposse/atmos/pkg/utils"
"github.com/cloudposse/atmos/pkg/version"
)

var Version = "0.0.1"

var versionCmd = &cobra.Command{
Use: "version",
Short: "Print the CLI version",
Expand All @@ -27,14 +26,14 @@ var versionCmd = &cobra.Command{
u.LogErrorAndExit(schema.CliConfiguration{}, err)
}

u.PrintMessage(fmt.Sprintf("\U0001F47D Atmos %s on %s/%s", Version, runtime.GOOS, runtime.GOARCH))
u.PrintMessage(fmt.Sprintf("\U0001F47D Atmos %s on %s/%s", version.Version, runtime.GOOS, runtime.GOARCH))
fmt.Println()

// Check for the latest Atmos release on GitHub
latestReleaseTag, err := u.GetLatestGitHubRepoRelease("cloudposse", "atmos")
if err == nil && latestReleaseTag != "" {
latestRelease := strings.TrimPrefix(latestReleaseTag, "v")
currentRelease := strings.TrimPrefix(Version, "v")
currentRelease := strings.TrimPrefix(version.Version, "v")
if latestRelease != currentRelease {
printMessageToUpgradeToAtmosLatestRelease(latestRelease)
}
Expand Down
6 changes: 6 additions & 0 deletions internal/exec/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/cloudposse/atmos/pkg/schema"
u "github.com/cloudposse/atmos/pkg/utils"
"github.com/cloudposse/atmos/pkg/version"
)

// processHelp processes help commands
Expand Down Expand Up @@ -45,6 +46,11 @@ func processHelp(componentType string, command string) error {
u.PrintMessage(" - double-dash '--' can be used to signify the end of the options for Atmos and the start of the additional " +
"native arguments and flags for the 'terraform' commands. " +
"For example: atmos terraform plan <component> -s <stack> -- -refresh=false -lock=false")

u.PrintMessage(fmt.Sprintf(" - '--append-user-agent' flag sets the TF_APPEND_USER_AGENT environment variable to customize the User-Agent string in Terraform provider requests. "+
"Example: 'Atmos/%s (Cloud Posse; +https://atmos.tools)'. "+
"If not specified, defaults to 'atmos %s'\n", version.Version, version.Version))

}

if componentType == "helmfile" {
Expand Down
10 changes: 10 additions & 0 deletions internal/exec/terraform.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,16 @@ func ExecuteTerraform(info schema.ConfigAndStacksInfo) error {
// https://developer.hashicorp.com/terraform/cli/config/environment-variables#tf_in_automation
info.ComponentEnvList = append(info.ComponentEnvList, "TF_IN_AUTOMATION=true")

// Set 'TF_APPEND_USER_AGENT' ENV var based on precedence
// Precedence: Environment Variable > atmos.yaml > Default
appendUserAgent := cliConfig.Components.Terraform.AppendUserAgent
if envUA, exists := os.LookupEnv("TF_APPEND_USER_AGENT"); exists && envUA != "" {
appendUserAgent = envUA
}
if appendUserAgent != "" {
info.ComponentEnvList = append(info.ComponentEnvList, fmt.Sprintf("TF_APPEND_USER_AGENT=%s", appendUserAgent))
}
aknysh marked this conversation as resolved.
Show resolved Hide resolved

// Print ENV vars if they are found in the component's stack config
if len(info.ComponentEnvList) > 0 {
u.LogDebug(cliConfig, "\nUsing ENV vars:")
Expand Down
14 changes: 14 additions & 0 deletions internal/exec/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ var (
cfg.DeployRunInitFlag,
cfg.InitRunReconfigure,
cfg.AutoGenerateBackendFileFlag,
cfg.AppendUserAgentFlag,
cfg.FromPlanFlag,
cfg.PlanFileFlag,
cfg.HelpFlag1,
Expand Down Expand Up @@ -668,6 +669,19 @@ func processArgsAndFlags(componentType string, inputArgsAndFlags []string) (sche
info.TerraformDir = terraformDirFlagParts[1]
}

if arg == cfg.AppendUserAgentFlag {
if len(inputArgsAndFlags) <= (i + 1) {
return info, fmt.Errorf("invalid flag: %s", arg)
}
info.AppendUserAgent = inputArgsAndFlags[i+1]
} else if strings.HasPrefix(arg+"=", cfg.AppendUserAgentFlag) {
var appendUserAgentFlagParts = strings.Split(arg, "=")
if len(appendUserAgentFlagParts) != 2 {
return info, fmt.Errorf("invalid flag: %s", arg)
}
info.AppendUserAgent = appendUserAgentFlagParts[1]
}

if arg == cfg.HelmfileCommandFlag {
if len(inputArgsAndFlags) <= (i + 1) {
return info, fmt.Errorf("invalid flag: %s", arg)
Expand Down
8 changes: 8 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (

"github.com/cloudposse/atmos/pkg/schema"
u "github.com/cloudposse/atmos/pkg/utils"
"github.com/cloudposse/atmos/pkg/version"
)

var (
Expand Down Expand Up @@ -43,6 +44,7 @@ var (
DeployRunInit: true,
InitRunReconfigure: true,
AutoGenerateBackendFile: true,
AppendUserAgent: fmt.Sprintf("Atmos/%s (Cloud Posse; +https://atmos.tools)", version.Version),
aknysh marked this conversation as resolved.
Show resolved Hide resolved
},
Helmfile: schema.Helmfile{
BasePath: "components/helmfile",
Expand Down Expand Up @@ -105,6 +107,7 @@ func InitCliConfig(configAndStacksInfo schema.ConfigAndStacksInfo, processStacks

// Default configuration values
v.SetDefault("components.helmfile.use_eks", true)
v.SetDefault("components.terraform.append_user_agent", fmt.Sprintf("Atmos/%s (Cloud Posse; +https://atmos.tools)", version.Version))
aknysh marked this conversation as resolved.
Show resolved Hide resolved

// Process config in system folder
configFilePath1 := ""
Expand Down Expand Up @@ -243,6 +246,11 @@ func InitCliConfig(configAndStacksInfo schema.ConfigAndStacksInfo, processStacks
cliConfig.BasePath = configAndStacksInfo.AtmosBasePath
}

// After unmarshalling, ensure AppendUserAgent is set if still empty
if cliConfig.Components.Terraform.AppendUserAgent == "" {
cliConfig.Components.Terraform.AppendUserAgent = fmt.Sprintf("Atmos/%s (Cloud Posse; +https://atmos.tools)", version.Version)
}
aknysh marked this conversation as resolved.
Show resolved Hide resolved
aknysh marked this conversation as resolved.
Show resolved Hide resolved

// Check config
err = checkConfig(cliConfig)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions pkg/config/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const (

DeployRunInitFlag = "--deploy-run-init"
AutoGenerateBackendFileFlag = "--auto-generate-backend-file"
AppendUserAgentFlag = "--append-user-agent"
InitRunReconfigure = "--init-run-reconfigure"

FromPlanFlag = "--from-plan"
Expand Down
6 changes: 6 additions & 0 deletions pkg/config/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,12 @@ func processEnvVars(cliConfig *schema.CliConfiguration) error {
cliConfig.Logs.Level = logsLevel
}

tfAppendUserAgent := os.Getenv("ATMOS_COMPONENTS_TERRAFORM_APPEND_USER_AGENT")
if len(tfAppendUserAgent) > 0 {
u.LogTrace(*cliConfig, fmt.Sprintf("Found ENV var ATMOS_COMPONENTS_TERRAFORM_APPEND_USER_AGENT=%s", tfAppendUserAgent))
cliConfig.Components.Terraform.AppendUserAgent = tfAppendUserAgent
}

listMergeStrategy := os.Getenv("ATMOS_SETTINGS_LIST_MERGE_STRATEGY")
if len(listMergeStrategy) > 0 {
u.LogTrace(*cliConfig, fmt.Sprintf("Found ENV var ATMOS_SETTINGS_LIST_MERGE_STRATEGY=%s", listMergeStrategy))
Expand Down
2 changes: 2 additions & 0 deletions pkg/schema/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ type TemplatesSettingsGomplate struct {
type Terraform struct {
BasePath string `yaml:"base_path" json:"base_path" mapstructure:"base_path"`
ApplyAutoApprove bool `yaml:"apply_auto_approve" json:"apply_auto_approve" mapstructure:"apply_auto_approve"`
AppendUserAgent string `yaml:"append_user_agent" json:"append_user_agent" mapstructure:"append_user_agent"`
aknysh marked this conversation as resolved.
Show resolved Hide resolved
DeployRunInit bool `yaml:"deploy_run_init" json:"deploy_run_init" mapstructure:"deploy_run_init"`
InitRunReconfigure bool `yaml:"init_run_reconfigure" json:"init_run_reconfigure" mapstructure:"init_run_reconfigure"`
AutoGenerateBackendFile bool `yaml:"auto_generate_backend_file" json:"auto_generate_backend_file" mapstructure:"auto_generate_backend_file"`
Expand Down Expand Up @@ -132,6 +133,7 @@ type ArgsAndFlagsInfo struct {
DeployRunInit string
InitRunReconfigure string
AutoGenerateBackendFile string
AppendUserAgent string
UseTerraformPlan bool
PlanFile string
DryRun bool
Expand Down
5 changes: 5 additions & 0 deletions pkg/version/version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package version

aknysh marked this conversation as resolved.
Show resolved Hide resolved
// Version holds the current version of the Atmos CLI.
// It can be set dynamically during build time using ldflags.
var Version = "0.0.1" // Default version; will be overridden during build
14 changes: 8 additions & 6 deletions website/docs/cli/commands/terraform/usage.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ atmos terraform workspace test/test-component-override-3 -s tenant1-ue2-dev --re
atmos terraform workspace test/test-component-override-3 -s tenant1-ue2-dev --redirect-stderr ./errors.txt

atmos terraform plan test/test-component -s tenant1-ue2-dev -- -refresh=false -lock=false

atmos terraform plan test/test-component -s tenant1-ue2-dev --append-user-agent "Acme/1.0 (Build 1234; arm64)"
```

## Arguments
Expand All @@ -124,12 +126,12 @@ atmos terraform plan test/test-component -s tenant1-ue2-dev -- -refresh=false -l

## Flags

| Flag | Description | Alias | Required |
| :------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------- | :---- | :------- |
| `--stack` | Atmos stack | `-s` | yes |
| `--dry-run` | Dry run | | no |
| `--redirect-stderr` | File descriptor to redirect `stderr` to.<br/>Errors can be redirected to any file or any standard file descriptor<br/>(including `/dev/null`) | | no |

| Flag | Description | Alias | Required |
| :------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------- | :---- | :------- |
| `--stack` | Atmos stack | `-s` | yes |
| `--dry-run` | Dry run | | no |
| `--redirect-stderr` | File descriptor to redirect `stderr` to.<br/>Errors can be redirected to any file or any standard file descriptor<br/>(including `/dev/null`) | | no |
| `--append-user-agent` | Append a custom User-Agent to Terraform requests. Can also be set using the ATMOS_COMPONENTS_TERRAFORM_APPEND_USER_AGENT environment variable.| | no |
aknysh marked this conversation as resolved.
Show resolved Hide resolved
<br />

:::note
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ components:
init_run_reconfigure: true
# Can also be set using 'ATMOS_COMPONENTS_TERRAFORM_AUTO_GENERATE_BACKEND_FILE' ENV var, or '--auto-generate-backend-file' command-line argument
auto_generate_backend_file: false
# Can also be set using 'ATMOS_COMPONENTS_TERRAFORM_APPEND_USER_AGENT' ENV var, or '--append-user-agent' command-line argument
append_user_agent: "Acme/1.0 (Build 1234; arm64)"
Cerebrovinny marked this conversation as resolved.
Show resolved Hide resolved
Cerebrovinny marked this conversation as resolved.
Show resolved Hide resolved
```

<dl>
Expand Down
2 changes: 1 addition & 1 deletion website/docs/quick-start/install-atmos.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ Atmos has a few other ways to install, including using Go, asdf, mise, aqua, bui
or run this and replace `$version` with the version that should be returned with `atmos version`.

```shell
go build -o build/atmos -v -ldflags "-X 'github.com/cloudposse/atmos/cmd.Version=$version'"
go build -o build/atmos -v -ldflags "-X 'github.com/cloudposse/atmos/pkg/version.Version=$version'"
aknysh marked this conversation as resolved.
Show resolved Hide resolved
```
</TabItem>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
- 'atmos terraform generate varfile' command generates a varfile for an 'atmos' component in a stack
- 'atmos terraform generate varfiles' command generates varfiles for all 'atmos' components in all stacks
- 'atmos terraform shell' command configures an environment for an 'atmos' component in a stack and starts a new shell allowing executing all native terraform commands inside the shell without using atmos-specific arguments and flags
- `--append-user-agent` flag allows you to customize the User-Agent string appended to Terraform requests for enhanced observability and traceability.
Cerebrovinny marked this conversation as resolved.
Show resolved Hide resolved
- double-dash '--' can be used to signify the end of the options for Atmos and the start of the additional native arguments and flags for the 'terraform' commands. For example: atmos terraform plan &lt;component&gt; -s &lt;stack&gt; -- -refresh=false -lock=false

Cerebrovinny marked this conversation as resolved.
Show resolved Hide resolved
Usage: terraform [global options] &lt;subcommand&gt; [args]
Expand Down
Loading