mirror of
https://github.com/3bbbeau/tfvars-atlantis-config.git
synced 2024-11-22 05:50:51 +00:00
99 lines
3.1 KiB
Go
99 lines
3.1 KiB
Go
|
package cmd
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"os"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/3bbbeau/tfvars-atlantis-config/logger"
|
||
|
"github.com/spf13/cobra"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
// ATLANTIS_WORKSPACE is the environment variable that contains the name of
|
||
|
// the workspace that Atlantis is currently running for.
|
||
|
ATLANTIS_WORKSPACE = "WORKSPACE"
|
||
|
)
|
||
|
|
||
|
// NewMultiEnvCmd creates a new `multienv` command
|
||
|
func NewMultiEnvCmd() *cobra.Command {
|
||
|
cmd := &cobra.Command{
|
||
|
Use: "multienv",
|
||
|
Short: "Returns a string representing the multienv for Atlantis",
|
||
|
Long: `Returns a string representing the multienv for Atlantis, e.g.:
|
||
|
EnvVar1Name=value1,EnvVar2Name=value2,EnvVar3Name=value3
|
||
|
|
||
|
Reference: https://www.runatlantis.io/docs/custom-workflows.html#multiple-environment-variables-multienv-command
|
||
|
|
||
|
This is useful when you want to configure providers via environment variables
|
||
|
on a per-workspace/environment basis.`,
|
||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||
|
workspace := os.Getenv(ATLANTIS_WORKSPACE)
|
||
|
if len(workspace) == 0 {
|
||
|
return fmt.Errorf("environment variable %s is not set. no workspace for multienv", ATLANTIS_WORKSPACE)
|
||
|
}
|
||
|
|
||
|
multienv, err := multienv(os.Getenv(ATLANTIS_WORKSPACE))
|
||
|
if err != nil {
|
||
|
if errors.Is(err, ErrNoEnvVars) {
|
||
|
logger.FromContext(cmd.Context()).Debug("no matching prefixed environment variables found")
|
||
|
// Return nil to indicate success, but no multienv string
|
||
|
return nil
|
||
|
}
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// Atlanis expects the multienv string to be written to stdout
|
||
|
fmt.Print(multienv)
|
||
|
return nil
|
||
|
},
|
||
|
}
|
||
|
return cmd
|
||
|
}
|
||
|
|
||
|
var ErrNoEnvVars error = fmt.Errorf("no matching prefixed environment variables found")
|
||
|
|
||
|
// Generates the Atlantis multienv string for multi-environment
|
||
|
// Terraform projects, e.g:
|
||
|
//
|
||
|
// EnvVar1Name=value1,EnvVar2Name=value2,EnvVar3Name=value3
|
||
|
//
|
||
|
// Given a prefix for the workspace name, strips the
|
||
|
// environment name from existing environment vars while keeping their value.
|
||
|
//
|
||
|
// This is useful when you want to configure providers via environment variables
|
||
|
// on a per-environment basis.
|
||
|
//
|
||
|
// Example:
|
||
|
//
|
||
|
// DEV_AWS_ACCESS_KEY_ID="foo"
|
||
|
// DEV_AWS_SECRET_ACCESS_KEY="bar"
|
||
|
// ->
|
||
|
// AWS_ACCESS_KEY_ID=$DEV_AWS_ACCESS_KEY_ID
|
||
|
// AWS_SECRET_ACCESS_KEY=$DEV_AWS_SECRET_ACCESS_KEY
|
||
|
func multienv(prefix string) (string, error) {
|
||
|
prefix = strings.ToUpper(prefix)
|
||
|
if !strings.HasSuffix(prefix, "_") {
|
||
|
prefix += "_"
|
||
|
}
|
||
|
|
||
|
strippedEnviron := []string{}
|
||
|
for _, v := range os.Environ() {
|
||
|
if strings.HasPrefix(v, prefix) {
|
||
|
// Limits the split to only two parts, separating the key from the first
|
||
|
// occurrence of '=', otherwise if the value contains '=' character(s) the
|
||
|
// string would be split into more than two parts.
|
||
|
split := strings.SplitN(v, "=", 2)
|
||
|
|
||
|
// Strips the prefix from the environment variable name, e.g. "DEV_" from
|
||
|
// "DEV_AWS_ACCESS_KEY_ID" and let it equal to the original environment variable
|
||
|
strippedEnviron = append(strippedEnviron, fmt.Sprintf("%s=%s", strings.TrimPrefix(split[0], prefix), split[1]))
|
||
|
}
|
||
|
}
|
||
|
if len(strippedEnviron) == 0 {
|
||
|
return "", ErrNoEnvVars
|
||
|
}
|
||
|
return strings.Join(strippedEnviron, ","), nil
|
||
|
}
|