From e5c67ac770eac0803ba225387275385f0090ef30 Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Sun, 20 Oct 2024 20:08:17 +0100 Subject: [PATCH 01/25] feat: vendor path setting in yaml support --- atmos.yaml | 6 ++++++ internal/exec/vendor_utils.go | 32 +++++++++++++++++++++++--------- pkg/schema/schema.go | 5 +++++ 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/atmos.yaml b/atmos.yaml index 5fa3fb3c0..45ca1cc41 100644 --- a/atmos.yaml +++ b/atmos.yaml @@ -351,3 +351,9 @@ settings: # If the source and destination lists have the same length, all items in the destination lists are # deep-merged with all items in the source list. list_merge_strategy: replace + +vendor: + # Path to the vendor.yaml file + # Supports both absolute and relative paths + # Can also be set using 'ATMOS_VENDOR_YAML_PATH' ENV var, or '--vendor-yaml-path' command-line argument + vendor_yaml_path: "path/to/your/vendor.yaml" \ No newline at end of file diff --git a/internal/exec/vendor_utils.go b/internal/exec/vendor_utils.go index 7858d683a..96e1799b7 100644 --- a/internal/exec/vendor_utils.go +++ b/internal/exec/vendor_utils.go @@ -129,19 +129,33 @@ func ReadAndProcessVendorConfigFile(cliConfig schema.CliConfiguration, vendorCon var vendorConfig schema.AtmosVendorConfig vendorConfigFileExists := true - // Check if the vendoring manifest file exists - foundVendorConfigFile, fileExists := u.SearchConfigFile(vendorConfigFile) + foundVendorConfigFile := vendorConfigFile - if !fileExists { - // Look for the vendoring manifest in the directory pointed to by the `base_path` setting in the `atmos.yaml` - pathToVendorConfig := path.Join(cliConfig.BasePath, vendorConfigFile) + // Check if 'vendor_config_path' is specified in 'atmos.yaml' + if cliConfig.Vendor.VendorConfigPath != "" { + vendorConfigPath := cliConfig.Vendor.VendorConfigPath + if !filepath.IsAbs(vendorConfigPath) { + vendorConfigPath = path.Join(cliConfig.BasePath, vendorConfigPath) + } - if !u.FileExists(pathToVendorConfig) { - vendorConfigFileExists = false - return vendorConfig, vendorConfigFileExists, "", fmt.Errorf("vendor config file '%s' does not exist", pathToVendorConfig) + if !u.FileExists(vendorConfigPath) { + return vendorConfig, false, "", fmt.Errorf("vendor config file '%s' does not exist", vendorConfigPath) } - foundVendorConfigFile = pathToVendorConfig + foundVendorConfigFile = vendorConfigPath + } else { + // Look for the vendoring manifest in the current directory + if !u.FileExists(vendorConfigFile) { + // Look for the vendoring manifest in the directory pointed to by the `base_path` setting in the `atmos.yaml` + pathToVendorConfig := path.Join(cliConfig.BasePath, vendorConfigFile) + + if !u.FileExists(pathToVendorConfig) { + vendorConfigFileExists = false + return vendorConfig, vendorConfigFileExists, "", fmt.Errorf("vendor config file '%s' does not exist", pathToVendorConfig) + } + + foundVendorConfigFile = pathToVendorConfig + } } vendorConfigFileContent, err := os.ReadFile(foundVendorConfigFile) diff --git a/pkg/schema/schema.go b/pkg/schema/schema.go index d77dd9213..50dec3c45 100644 --- a/pkg/schema/schema.go +++ b/pkg/schema/schema.go @@ -15,6 +15,7 @@ type CliConfiguration struct { Schemas Schemas `yaml:"schemas,omitempty" json:"schemas,omitempty" mapstructure:"schemas"` Templates Templates `yaml:"templates,omitempty" json:"templates,omitempty" mapstructure:"templates"` Settings CliSettings `yaml:"settings,omitempty" json:"settings,omitempty" mapstructure:"settings"` + Vendor Vendor `yaml:"vendor,omitempty" json:"vendor,omitempty" mapstructure:"vendor"` Initialized bool `yaml:"initialized" json:"initialized" mapstructure:"initialized"` StacksBaseAbsolutePath string `yaml:"stacksBaseAbsolutePath,omitempty" json:"stacksBaseAbsolutePath,omitempty" mapstructure:"stacksBaseAbsolutePath"` IncludeStackAbsolutePaths []string `yaml:"includeStackAbsolutePaths,omitempty" json:"includeStackAbsolutePaths,omitempty" mapstructure:"includeStackAbsolutePaths"` @@ -544,3 +545,7 @@ type AtmosVendorConfig struct { Metadata AtmosVendorMetadata Spec AtmosVendorSpec `yaml:"spec" json:"spec" mapstructure:"spec"` } + +type Vendor struct { + VendorConfigPath string `yaml:"vendor_config_path" json:"vendor_config_path" mapstructure:"vendor_config_path"` +} From 626c3e463b460f54e999067273d328c6ff61798e Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Sun, 20 Oct 2024 21:02:06 +0100 Subject: [PATCH 02/25] feat: refactoring vendor config path --- internal/exec/vendor_utils.go | 33 ++++++++++++--------------------- pkg/schema/schema.go | 2 +- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/internal/exec/vendor_utils.go b/internal/exec/vendor_utils.go index 96e1799b7..e41c84387 100644 --- a/internal/exec/vendor_utils.go +++ b/internal/exec/vendor_utils.go @@ -131,33 +131,24 @@ func ReadAndProcessVendorConfigFile(cliConfig schema.CliConfiguration, vendorCon foundVendorConfigFile := vendorConfigFile - // Check if 'vendor_config_path' is specified in 'atmos.yaml' - if cliConfig.Vendor.VendorConfigPath != "" { - vendorConfigPath := cliConfig.Vendor.VendorConfigPath + // If the vendoring manifest is specified without an extension, use the default extension + vendorConfigPath := vendorConfigFile + if cliConfig.Vendor.VendorYamlPath != "" { + vendorConfigPath = cliConfig.Vendor.VendorYamlPath if !filepath.IsAbs(vendorConfigPath) { - vendorConfigPath = path.Join(cliConfig.BasePath, vendorConfigPath) + vendorConfigPath = filepath.Join(cliConfig.BasePath, vendorConfigPath) } - - if !u.FileExists(vendorConfigPath) { - return vendorConfig, false, "", fmt.Errorf("vendor config file '%s' does not exist", vendorConfigPath) - } - - foundVendorConfigFile = vendorConfigPath } else { - // Look for the vendoring manifest in the current directory - if !u.FileExists(vendorConfigFile) { - // Look for the vendoring manifest in the directory pointed to by the `base_path` setting in the `atmos.yaml` - pathToVendorConfig := path.Join(cliConfig.BasePath, vendorConfigFile) - - if !u.FileExists(pathToVendorConfig) { - vendorConfigFileExists = false - return vendorConfig, vendorConfigFileExists, "", fmt.Errorf("vendor config file '%s' does not exist", pathToVendorConfig) - } + vendorConfigPath = filepath.Join(cliConfig.BasePath, vendorConfigFile) + } - foundVendorConfigFile = pathToVendorConfig - } + if !u.FileExists(vendorConfigPath) { + vendorConfigFileExists = false + return vendorConfig, vendorConfigFileExists, "", fmt.Errorf("vendor config file '%s' does not exist", vendorConfigPath) } + foundVendorConfigFile = vendorConfigPath + vendorConfigFileContent, err := os.ReadFile(foundVendorConfigFile) if err != nil { return vendorConfig, vendorConfigFileExists, "", err diff --git a/pkg/schema/schema.go b/pkg/schema/schema.go index 50dec3c45..601eeabec 100644 --- a/pkg/schema/schema.go +++ b/pkg/schema/schema.go @@ -547,5 +547,5 @@ type AtmosVendorConfig struct { } type Vendor struct { - VendorConfigPath string `yaml:"vendor_config_path" json:"vendor_config_path" mapstructure:"vendor_config_path"` + VendorYamlPath string `yaml:"vendor_yaml_path" json:"vendor_yaml_path" mapstructure:"vendor_yaml_path"` } From 1b7eb1c01faa6c01ab47c056d0a3e537f734e6ef Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Tue, 22 Oct 2024 15:56:00 +0100 Subject: [PATCH 03/25] general refactoring process vendor --- internal/exec/vendor_utils.go | 40 ++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/internal/exec/vendor_utils.go b/internal/exec/vendor_utils.go index e41c84387..719c23c5f 100644 --- a/internal/exec/vendor_utils.go +++ b/internal/exec/vendor_utils.go @@ -127,41 +127,57 @@ func ReadAndProcessVendorConfigFile(cliConfig schema.CliConfiguration, vendorCon error, ) { var vendorConfig schema.AtmosVendorConfig - vendorConfigFileExists := true + var foundVendorConfigFile string + vendorConfigFileExists := false - foundVendorConfigFile := vendorConfigFile + // Build a list of possible paths to the vendor config file + var pathsToCheck []string - // If the vendoring manifest is specified without an extension, use the default extension - vendorConfigPath := vendorConfigFile + // If 'vendor_config_path' is specified in 'atmos.yaml', use it if cliConfig.Vendor.VendorYamlPath != "" { - vendorConfigPath = cliConfig.Vendor.VendorYamlPath + vendorConfigPath := cliConfig.Vendor.VendorYamlPath if !filepath.IsAbs(vendorConfigPath) { - vendorConfigPath = filepath.Join(cliConfig.BasePath, vendorConfigPath) + vendorConfigPath = path.Join(cliConfig.BasePath, vendorConfigPath) } + pathsToCheck = append(pathsToCheck, vendorConfigPath) } else { - vendorConfigPath = filepath.Join(cliConfig.BasePath, vendorConfigFile) + // Check the current directory + pathsToCheck = append(pathsToCheck, vendorConfigFile) + // Check the base_path directory + basePathVendorConfig := path.Join(cliConfig.BasePath, vendorConfigFile) + pathsToCheck = append(pathsToCheck, basePathVendorConfig) } - if !u.FileExists(vendorConfigPath) { - vendorConfigFileExists = false - return vendorConfig, vendorConfigFileExists, "", fmt.Errorf("vendor config file '%s' does not exist", vendorConfigPath) + // Search for the vendor config file + for _, filePath := range pathsToCheck { + if u.FileExists(filePath) { + foundVendorConfigFile = filePath + vendorConfigFileExists = true + break + } } - foundVendorConfigFile = vendorConfigPath + // If not found, return an error + if !vendorConfigFileExists { + return vendorConfig, false, "", fmt.Errorf("vendor config file not found in paths: %v", pathsToCheck) + } + // Read the content of the vendor config file vendorConfigFileContent, err := os.ReadFile(foundVendorConfigFile) if err != nil { return vendorConfig, vendorConfigFileExists, "", err } + // Unmarshal the YAML content into the vendorConfig struct vendorConfig, err = u.UnmarshalYAML[schema.AtmosVendorConfig](string(vendorConfigFileContent)) if err != nil { return vendorConfig, vendorConfigFileExists, "", err } + // Validate the 'kind' field if vendorConfig.Kind != "AtmosVendorConfig" { return vendorConfig, vendorConfigFileExists, "", - fmt.Errorf("invalid 'kind: %s' in the vendor config file '%s'. Supported kinds: 'AtmosVendorConfig'", + fmt.Errorf("invalid 'kind: %s' in the vendor config file '%s'. Supported kind: 'AtmosVendorConfig'", vendorConfig.Kind, foundVendorConfigFile, ) From 62b7c7db5feacb98e4dc5057910403cb6c1f9fd5 Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Tue, 22 Oct 2024 15:58:48 +0100 Subject: [PATCH 04/25] vendor yaml path update --- atmos.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atmos.yaml b/atmos.yaml index 45ca1cc41..aa49114cc 100644 --- a/atmos.yaml +++ b/atmos.yaml @@ -356,4 +356,4 @@ vendor: # Path to the vendor.yaml file # Supports both absolute and relative paths # Can also be set using 'ATMOS_VENDOR_YAML_PATH' ENV var, or '--vendor-yaml-path' command-line argument - vendor_yaml_path: "path/to/your/vendor.yaml" \ No newline at end of file + vendor_yaml_path: "./vendor.yaml" \ No newline at end of file From 729fdaeddb54044107fc5643cf9f326444e52ab8 Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Tue, 22 Oct 2024 18:06:03 +0100 Subject: [PATCH 05/25] sync master --- internal/exec/vendor_utils.go | 43 +++++++++-------------------------- 1 file changed, 11 insertions(+), 32 deletions(-) diff --git a/internal/exec/vendor_utils.go b/internal/exec/vendor_utils.go index 719c23c5f..7858d683a 100644 --- a/internal/exec/vendor_utils.go +++ b/internal/exec/vendor_utils.go @@ -127,57 +127,36 @@ func ReadAndProcessVendorConfigFile(cliConfig schema.CliConfiguration, vendorCon error, ) { var vendorConfig schema.AtmosVendorConfig - var foundVendorConfigFile string - vendorConfigFileExists := false + vendorConfigFileExists := true - // Build a list of possible paths to the vendor config file - var pathsToCheck []string + // Check if the vendoring manifest file exists + foundVendorConfigFile, fileExists := u.SearchConfigFile(vendorConfigFile) - // If 'vendor_config_path' is specified in 'atmos.yaml', use it - if cliConfig.Vendor.VendorYamlPath != "" { - vendorConfigPath := cliConfig.Vendor.VendorYamlPath - if !filepath.IsAbs(vendorConfigPath) { - vendorConfigPath = path.Join(cliConfig.BasePath, vendorConfigPath) - } - pathsToCheck = append(pathsToCheck, vendorConfigPath) - } else { - // Check the current directory - pathsToCheck = append(pathsToCheck, vendorConfigFile) - // Check the base_path directory - basePathVendorConfig := path.Join(cliConfig.BasePath, vendorConfigFile) - pathsToCheck = append(pathsToCheck, basePathVendorConfig) - } + if !fileExists { + // Look for the vendoring manifest in the directory pointed to by the `base_path` setting in the `atmos.yaml` + pathToVendorConfig := path.Join(cliConfig.BasePath, vendorConfigFile) - // Search for the vendor config file - for _, filePath := range pathsToCheck { - if u.FileExists(filePath) { - foundVendorConfigFile = filePath - vendorConfigFileExists = true - break + if !u.FileExists(pathToVendorConfig) { + vendorConfigFileExists = false + return vendorConfig, vendorConfigFileExists, "", fmt.Errorf("vendor config file '%s' does not exist", pathToVendorConfig) } - } - // If not found, return an error - if !vendorConfigFileExists { - return vendorConfig, false, "", fmt.Errorf("vendor config file not found in paths: %v", pathsToCheck) + foundVendorConfigFile = pathToVendorConfig } - // Read the content of the vendor config file vendorConfigFileContent, err := os.ReadFile(foundVendorConfigFile) if err != nil { return vendorConfig, vendorConfigFileExists, "", err } - // Unmarshal the YAML content into the vendorConfig struct vendorConfig, err = u.UnmarshalYAML[schema.AtmosVendorConfig](string(vendorConfigFileContent)) if err != nil { return vendorConfig, vendorConfigFileExists, "", err } - // Validate the 'kind' field if vendorConfig.Kind != "AtmosVendorConfig" { return vendorConfig, vendorConfigFileExists, "", - fmt.Errorf("invalid 'kind: %s' in the vendor config file '%s'. Supported kind: 'AtmosVendorConfig'", + fmt.Errorf("invalid 'kind: %s' in the vendor config file '%s'. Supported kinds: 'AtmosVendorConfig'", vendorConfig.Kind, foundVendorConfigFile, ) From 19263fb09c6227e52a6fef77b7f3f8c3db5475cf Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Tue, 22 Oct 2024 23:41:49 +0100 Subject: [PATCH 06/25] blank line yaml --- atmos.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atmos.yaml b/atmos.yaml index aa49114cc..1d718a72e 100644 --- a/atmos.yaml +++ b/atmos.yaml @@ -356,4 +356,4 @@ vendor: # Path to the vendor.yaml file # Supports both absolute and relative paths # Can also be set using 'ATMOS_VENDOR_YAML_PATH' ENV var, or '--vendor-yaml-path' command-line argument - vendor_yaml_path: "./vendor.yaml" \ No newline at end of file + vendor_yaml_path: "./vendor.yaml" From 2fb288c1d96710c415a8654b11c2c62cbf0666cf Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Tue, 22 Oct 2024 23:42:45 +0100 Subject: [PATCH 07/25] feat: set vendor path --- internal/exec/vendor_utils.go | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/internal/exec/vendor_utils.go b/internal/exec/vendor_utils.go index 7858d683a..6ae3c2766 100644 --- a/internal/exec/vendor_utils.go +++ b/internal/exec/vendor_utils.go @@ -80,7 +80,7 @@ func ExecuteVendorPullCommand(cmd *cobra.Command, args []string) error { // Check `vendor.yaml` vendorConfig, vendorConfigExists, foundVendorConfigFile, err := ReadAndProcessVendorConfigFile(cliConfig, cfg.AtmosVendorConfigFileName) - if vendorConfigExists && err != nil { + if err != nil { return err } @@ -128,22 +128,35 @@ func ReadAndProcessVendorConfigFile(cliConfig schema.CliConfiguration, vendorCon ) { var vendorConfig schema.AtmosVendorConfig vendorConfigFileExists := true + var foundVendorConfigFile string + + // Check if the vendor config path is defined in atmos.yaml + if cliConfig.Vendor.VendorYamlPath != "" { + // Resolve the vendor_yaml_path relative to base_path if it's a relative path + if !filepath.IsAbs(cliConfig.Vendor.VendorYamlPath) { + foundVendorConfigFile = filepath.Join(cliConfig.BasePath, cliConfig.Vendor.VendorYamlPath) + } else { + foundVendorConfigFile = cliConfig.Vendor.VendorYamlPath + } + } else { + // Path is not defined in atmos.yaml, proceed with existing logic + var fileExists bool + foundVendorConfigFile, fileExists = u.SearchConfigFile(vendorConfigFile) - // Check if the vendoring manifest file exists - foundVendorConfigFile, fileExists := u.SearchConfigFile(vendorConfigFile) + if !fileExists { + // Look for the vendoring manifest in the directory pointed to by the `base_path` setting in `atmos.yaml` + pathToVendorConfig := path.Join(cliConfig.BasePath, vendorConfigFile) - if !fileExists { - // Look for the vendoring manifest in the directory pointed to by the `base_path` setting in the `atmos.yaml` - pathToVendorConfig := path.Join(cliConfig.BasePath, vendorConfigFile) + if !u.FileExists(pathToVendorConfig) { + vendorConfigFileExists = false + return vendorConfig, vendorConfigFileExists, "", fmt.Errorf("vendor config file '%s' does not exist", pathToVendorConfig) + } - if !u.FileExists(pathToVendorConfig) { - vendorConfigFileExists = false - return vendorConfig, vendorConfigFileExists, "", fmt.Errorf("vendor config file '%s' does not exist", pathToVendorConfig) + foundVendorConfigFile = pathToVendorConfig } - - foundVendorConfigFile = pathToVendorConfig } + // Read the vendor config file vendorConfigFileContent, err := os.ReadFile(foundVendorConfigFile) if err != nil { return vendorConfig, vendorConfigFileExists, "", err From 1d9624e4bf37933ad84d2df87935e7eb3a9e5767 Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Tue, 22 Oct 2024 23:52:33 +0100 Subject: [PATCH 08/25] vendor improvements checking --- atmos.yaml | 12 ++++++------ internal/exec/vendor_utils.go | 4 ++++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/atmos.yaml b/atmos.yaml index 1d718a72e..e1d9b6fd3 100644 --- a/atmos.yaml +++ b/atmos.yaml @@ -17,6 +17,12 @@ # are considered paths relative to 'base_path'. base_path: "./examples/quick-start-advanced" +vendor: + # Path to the vendor.yaml file + # Supports both absolute and relative paths + # Can also be set using 'ATMOS_VENDOR_YAML_PATH' ENV var, or '--vendor-yaml-path' command-line argument + vendor_yaml_path: "./vendor.yaml" + components: terraform: # Optional `command` specifies the executable to be called by `atmos` when running Terraform commands @@ -351,9 +357,3 @@ settings: # If the source and destination lists have the same length, all items in the destination lists are # deep-merged with all items in the source list. list_merge_strategy: replace - -vendor: - # Path to the vendor.yaml file - # Supports both absolute and relative paths - # Can also be set using 'ATMOS_VENDOR_YAML_PATH' ENV var, or '--vendor-yaml-path' command-line argument - vendor_yaml_path: "./vendor.yaml" diff --git a/internal/exec/vendor_utils.go b/internal/exec/vendor_utils.go index 6ae3c2766..f964b9623 100644 --- a/internal/exec/vendor_utils.go +++ b/internal/exec/vendor_utils.go @@ -138,6 +138,10 @@ func ReadAndProcessVendorConfigFile(cliConfig schema.CliConfiguration, vendorCon } else { foundVendorConfigFile = cliConfig.Vendor.VendorYamlPath } + if !u.FileExists(foundVendorConfigFile) { + vendorConfigFileExists = false + return vendorConfig, vendorConfigFileExists, "", fmt.Errorf("vendor config file '%s' does not exist", foundVendorConfigFile) + } } else { // Path is not defined in atmos.yaml, proceed with existing logic var fileExists bool From ac9796b7fd8ee733053418d738ddfb6f7eb66220 Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Tue, 22 Oct 2024 23:58:12 +0100 Subject: [PATCH 09/25] vendor refactor remove redundant code --- internal/exec/vendor_utils.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/internal/exec/vendor_utils.go b/internal/exec/vendor_utils.go index f964b9623..6ae3c2766 100644 --- a/internal/exec/vendor_utils.go +++ b/internal/exec/vendor_utils.go @@ -138,10 +138,6 @@ func ReadAndProcessVendorConfigFile(cliConfig schema.CliConfiguration, vendorCon } else { foundVendorConfigFile = cliConfig.Vendor.VendorYamlPath } - if !u.FileExists(foundVendorConfigFile) { - vendorConfigFileExists = false - return vendorConfig, vendorConfigFileExists, "", fmt.Errorf("vendor config file '%s' does not exist", foundVendorConfigFile) - } } else { // Path is not defined in atmos.yaml, proceed with existing logic var fileExists bool From f1c1cf9ecfd1908f3e2f4dbbdf2500cd0a0278c5 Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Thu, 24 Oct 2024 00:54:22 +0100 Subject: [PATCH 10/25] implement env vars for vendor file --- pkg/config/const.go | 1 + pkg/config/utils.go | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/pkg/config/const.go b/pkg/config/const.go index 720f53507..de2a77cba 100644 --- a/pkg/config/const.go +++ b/pkg/config/const.go @@ -18,6 +18,7 @@ const ( CliConfigDirFlag = "--config-dir" StackDirFlag = "--stacks-dir" BasePathFlag = "--base-path" + VendorYamlPathFlag = "--vendor-yaml-path" WorkflowDirFlag = "--workflows-dir" KubeConfigConfigFlag = "--kubeconfig-path" JsonSchemaDirFlag = "--schemas-jsonschema-dir" diff --git a/pkg/config/utils.go b/pkg/config/utils.go index bd916b2bb..2cc982171 100644 --- a/pkg/config/utils.go +++ b/pkg/config/utils.go @@ -163,6 +163,12 @@ func processEnvVars(cliConfig *schema.CliConfiguration) error { cliConfig.BasePath = basePath } + vendorYamlPath := os.Getenv("ATMOS_VENDOR_YAML_PATH") + if len(vendorYamlPath) > 0 { + u.LogTrace(*cliConfig, fmt.Sprintf("Found ENV var ATMOS_VENDOR_YAML_PATH=%s", vendorYamlPath)) + cliConfig.Vendor.VendorYamlPath = vendorYamlPath + } + stacksBasePath := os.Getenv("ATMOS_STACKS_BASE_PATH") if len(stacksBasePath) > 0 { u.LogTrace(*cliConfig, fmt.Sprintf("Found ENV var ATMOS_STACKS_BASE_PATH=%s", stacksBasePath)) From 27a9803800bac8519baba3e3a81a0f9dcb8158ad Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Thu, 24 Oct 2024 06:55:05 +0100 Subject: [PATCH 11/25] implement env vars flag for vendor file --- internal/exec/utils.go | 14 ++++++++++++++ pkg/schema/schema.go | 2 ++ 2 files changed, 16 insertions(+) diff --git a/internal/exec/utils.go b/internal/exec/utils.go index 0a4b662c2..cecbc7d86 100644 --- a/internal/exec/utils.go +++ b/internal/exec/utils.go @@ -31,6 +31,7 @@ var ( cfg.CliConfigDirFlag, cfg.StackDirFlag, cfg.BasePathFlag, + cfg.VendorYamlPathFlag, cfg.GlobalOptionsFlag, cfg.DeployRunInitFlag, cfg.InitRunReconfigure, @@ -733,6 +734,19 @@ func processArgsAndFlags(componentType string, inputArgsAndFlags []string) (sche info.BasePath = stacksDirFlagParts[1] } + if arg == cfg.VendorYamlPathFlag { + if len(inputArgsAndFlags) <= (i + 1) { + return info, fmt.Errorf("invalid flag: %s", arg) + } + info.VendorYamlPathFlag = inputArgsAndFlags[i+1] + } else if strings.HasPrefix(arg+"=", cfg.VendorYamlPathFlag) { + var vendorYamlPathFlagParts = strings.Split(arg, "=") + if len(vendorYamlPathFlagParts) != 2 { + return info, fmt.Errorf("invalid flag: %s", arg) + } + info.VendorYamlPathFlag = vendorYamlPathFlagParts[1] + } + if arg == cfg.DeployRunInitFlag { if len(inputArgsAndFlags) <= (i + 1) { return info, fmt.Errorf("invalid flag: %s", arg) diff --git a/pkg/schema/schema.go b/pkg/schema/schema.go index 601eeabec..6204082fc 100644 --- a/pkg/schema/schema.go +++ b/pkg/schema/schema.go @@ -130,6 +130,7 @@ type ArgsAndFlagsInfo struct { StacksDir string WorkflowsDir string BasePath string + VendorYamlPathFlag string DeployRunInit string InitRunReconfigure string AutoGenerateBackendFile string @@ -175,6 +176,7 @@ type ConfigAndStacksInfo struct { AdditionalArgsAndFlags []string GlobalOptions []string BasePath string + VendorYamlPathFlag string TerraformCommand string TerraformDir string HelmfileCommand string From a8a80ccbf5eff6f891b56d90f252ffbd7630c296 Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Mon, 28 Oct 2024 16:59:08 +0000 Subject: [PATCH 12/25] update docs vendor path --- website/docs/cli/configuration/configuration.mdx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/website/docs/cli/configuration/configuration.mdx b/website/docs/cli/configuration/configuration.mdx index 0ecdb591b..c12a63858 100644 --- a/website/docs/cli/configuration/configuration.mdx +++ b/website/docs/cli/configuration/configuration.mdx @@ -48,6 +48,8 @@ If `atmos.yaml` is not found in any of the searched locations, Atmos will use th ```yaml base_path: "." +vendor: + vendor_yaml_path: vendor.yaml components: terraform: base_path: components/terraform @@ -605,6 +607,7 @@ setting `ATMOS_STACKS_BASE_PATH` to a path in `/localhost` to your local develop |:------------------------------------------------------|:------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ATMOS_CLI_CONFIG_PATH | N/A | Where to find `atmos.yaml`. Path to a folder where `atmos.yaml` CLI config file is located (e.g. `/config`) | | ATMOS_BASE_PATH | base_path | Base path to `components` and `stacks` folders | +| ATMOS_VENDOR_YAML_PATH | vendor.vendor_yaml_path | Path to the vendor.yaml file | | ATMOS_COMPONENTS_TERRAFORM_COMMAND | components.terraform.command | The executable to be called by `atmos` when running Terraform commands | | ATMOS_COMPONENTS_TERRAFORM_BASE_PATH | components.terraform.base_path | Base path to Terraform components | | ATMOS_COMPONENTS_TERRAFORM_APPLY_AUTO_APPROVE | components.terraform.apply_auto_approve | If set to `true`, auto-generate Terraform backend config files when executing `atmos terraform` commands | From 6c1f57e127d7c8c1f42bb770fb3808c9012f1eba Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Mon, 28 Oct 2024 17:06:03 +0000 Subject: [PATCH 13/25] improve description --- website/docs/cli/configuration/configuration.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/cli/configuration/configuration.mdx b/website/docs/cli/configuration/configuration.mdx index c12a63858..e0dfa3c97 100644 --- a/website/docs/cli/configuration/configuration.mdx +++ b/website/docs/cli/configuration/configuration.mdx @@ -607,7 +607,7 @@ setting `ATMOS_STACKS_BASE_PATH` to a path in `/localhost` to your local develop |:------------------------------------------------------|:------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ATMOS_CLI_CONFIG_PATH | N/A | Where to find `atmos.yaml`. Path to a folder where `atmos.yaml` CLI config file is located (e.g. `/config`) | | ATMOS_BASE_PATH | base_path | Base path to `components` and `stacks` folders | -| ATMOS_VENDOR_YAML_PATH | vendor.vendor_yaml_path | Path to the vendor.yaml file | +| ATMOS_VENDOR_YAML_PATH | vendor.vendor_yaml_path | Path to the vendor configuration file (vendor.yaml). Supports both absolute and relative paths. Used to configure vendor-specific settings for the Atmos CLI. | | ATMOS_COMPONENTS_TERRAFORM_COMMAND | components.terraform.command | The executable to be called by `atmos` when running Terraform commands | | ATMOS_COMPONENTS_TERRAFORM_BASE_PATH | components.terraform.base_path | Base path to Terraform components | | ATMOS_COMPONENTS_TERRAFORM_APPLY_AUTO_APPROVE | components.terraform.apply_auto_approve | If set to `true`, auto-generate Terraform backend config files when executing `atmos terraform` commands | From 9b71751e94d528d4314b695979684e5a752a36c2 Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Wed, 30 Oct 2024 18:09:02 +0000 Subject: [PATCH 14/25] added demo base vendor files general refactoring --- atmos.yaml | 7 +- examples/demo-vendoring/atmos.yaml | 10 +++ .../demo-vendoring/nested-vendor/vendor1.yaml | 14 ++++ .../demo-vendoring/stacks/catalog/myapp.yaml | 9 +++ .../demo-vendoring/stacks/deploy/dev.yaml | 12 +++ .../demo-vendoring/stacks/deploy/prod.yaml | 12 +++ .../demo-vendoring/stacks/deploy/staging.yaml | 12 +++ examples/demo-vendoring/vendor/vendor1.yaml | 14 ++++ examples/demo-vendoring/vendor/vendor2.yaml | 14 ++++ internal/exec/utils.go | 14 ++-- internal/exec/vendor_utils.go | 81 +++++++++++++------ pkg/config/const.go | 2 +- pkg/config/utils.go | 8 +- pkg/schema/schema.go | 8 +- 14 files changed, 173 insertions(+), 44 deletions(-) create mode 100644 examples/demo-vendoring/nested-vendor/vendor1.yaml create mode 100644 examples/demo-vendoring/stacks/catalog/myapp.yaml create mode 100644 examples/demo-vendoring/stacks/deploy/dev.yaml create mode 100644 examples/demo-vendoring/stacks/deploy/prod.yaml create mode 100644 examples/demo-vendoring/stacks/deploy/staging.yaml create mode 100644 examples/demo-vendoring/vendor/vendor1.yaml create mode 100644 examples/demo-vendoring/vendor/vendor2.yaml diff --git a/atmos.yaml b/atmos.yaml index e1d9b6fd3..931312e27 100644 --- a/atmos.yaml +++ b/atmos.yaml @@ -18,10 +18,11 @@ base_path: "./examples/quick-start-advanced" vendor: - # Path to the vendor.yaml file + # Path to vendor configuration file or directory containing vendor files # Supports both absolute and relative paths - # Can also be set using 'ATMOS_VENDOR_YAML_PATH' ENV var, or '--vendor-yaml-path' command-line argument - vendor_yaml_path: "./vendor.yaml" + # If a directory is specified, all .yaml files in the directory will be processed in lexicographical order + # Can also be set using 'ATMOS_VENDOR_BASE_PATH' ENV var, or '--vendor-base-path' command-line argument + base_path: "./vendor.yaml" components: terraform: diff --git a/examples/demo-vendoring/atmos.yaml b/examples/demo-vendoring/atmos.yaml index 1c7d3ad24..54bf52cc6 100644 --- a/examples/demo-vendoring/atmos.yaml +++ b/examples/demo-vendoring/atmos.yaml @@ -16,6 +16,16 @@ stacks: - "**/_defaults.yaml" name_pattern: "{stage}" +vendor: + # Single file + base_path: "./vendor.yaml" + + # Directory with multiple files + #base_path: "./vendor" + + # Absolute path + # base_path: "nested-vendor/vendor1.yaml" + logs: file: "/dev/stderr" level: Info diff --git a/examples/demo-vendoring/nested-vendor/vendor1.yaml b/examples/demo-vendoring/nested-vendor/vendor1.yaml new file mode 100644 index 000000000..59f2ca35e --- /dev/null +++ b/examples/demo-vendoring/nested-vendor/vendor1.yaml @@ -0,0 +1,14 @@ +apiVersion: atmos/v1 +kind: AtmosVendorConfig +metadata: + name: vendor-test-1 + description: Test vendor config 1 +spec: + sources: + - component: "ipinfo" + source: "github.com/cloudposse/atmos.git//examples/demo-library/{{ .Component }}?ref={{.Version}}" + version: "main" + targets: + - "components/terraform/{{ .Component }}/{{.Version}}" + tags: + - demo \ No newline at end of file diff --git a/examples/demo-vendoring/stacks/catalog/myapp.yaml b/examples/demo-vendoring/stacks/catalog/myapp.yaml new file mode 100644 index 000000000..9d4fe3f77 --- /dev/null +++ b/examples/demo-vendoring/stacks/catalog/myapp.yaml @@ -0,0 +1,9 @@ +components: + terraform: + myapp: + vars: + location: Los Angeles + lang: en + format: '' + options: '0' + units: m diff --git a/examples/demo-vendoring/stacks/deploy/dev.yaml b/examples/demo-vendoring/stacks/deploy/dev.yaml new file mode 100644 index 000000000..9df297c70 --- /dev/null +++ b/examples/demo-vendoring/stacks/deploy/dev.yaml @@ -0,0 +1,12 @@ +vars: + stage: dev + +import: + - catalog/myapp + +components: + terraform: + myapp: + vars: + location: Stockholm + lang: se diff --git a/examples/demo-vendoring/stacks/deploy/prod.yaml b/examples/demo-vendoring/stacks/deploy/prod.yaml new file mode 100644 index 000000000..968a5dfdd --- /dev/null +++ b/examples/demo-vendoring/stacks/deploy/prod.yaml @@ -0,0 +1,12 @@ +vars: + stage: prod + +import: + - catalog/myapp + +components: + terraform: + myapp: + vars: + location: Los Angeles + lang: en diff --git a/examples/demo-vendoring/stacks/deploy/staging.yaml b/examples/demo-vendoring/stacks/deploy/staging.yaml new file mode 100644 index 000000000..4c28c7470 --- /dev/null +++ b/examples/demo-vendoring/stacks/deploy/staging.yaml @@ -0,0 +1,12 @@ +vars: + stage: staging + +import: + - catalog/myapp + +components: + terraform: + myapp: + vars: + location: Los Angeles + lang: en diff --git a/examples/demo-vendoring/vendor/vendor1.yaml b/examples/demo-vendoring/vendor/vendor1.yaml new file mode 100644 index 000000000..59f2ca35e --- /dev/null +++ b/examples/demo-vendoring/vendor/vendor1.yaml @@ -0,0 +1,14 @@ +apiVersion: atmos/v1 +kind: AtmosVendorConfig +metadata: + name: vendor-test-1 + description: Test vendor config 1 +spec: + sources: + - component: "ipinfo" + source: "github.com/cloudposse/atmos.git//examples/demo-library/{{ .Component }}?ref={{.Version}}" + version: "main" + targets: + - "components/terraform/{{ .Component }}/{{.Version}}" + tags: + - demo \ No newline at end of file diff --git a/examples/demo-vendoring/vendor/vendor2.yaml b/examples/demo-vendoring/vendor/vendor2.yaml new file mode 100644 index 000000000..5b664fca3 --- /dev/null +++ b/examples/demo-vendoring/vendor/vendor2.yaml @@ -0,0 +1,14 @@ +apiVersion: atmos/v1 +kind: AtmosVendorConfig +metadata: + name: vendor-test-2 + description: Test vendor config 2 +spec: + sources: + - component: "weather" + source: "github.com/cloudposse/atmos.git//examples/demo-library/{{ .Component }}?ref={{.Version}}" + version: "main" + targets: + - "components/terraform/{{ .Component }}/{{.Version}}" + tags: + - demo \ No newline at end of file diff --git a/internal/exec/utils.go b/internal/exec/utils.go index 140d8660e..a211019a7 100644 --- a/internal/exec/utils.go +++ b/internal/exec/utils.go @@ -31,7 +31,7 @@ var ( cfg.CliConfigDirFlag, cfg.StackDirFlag, cfg.BasePathFlag, - cfg.VendorYamlPathFlag, + cfg.VendorBasePathFlag, cfg.GlobalOptionsFlag, cfg.DeployRunInitFlag, cfg.InitRunReconfigure, @@ -748,17 +748,17 @@ func processArgsAndFlags(componentType string, inputArgsAndFlags []string) (sche info.BasePath = stacksDirFlagParts[1] } - if arg == cfg.VendorYamlPathFlag { + if arg == cfg.VendorBasePathFlag { if len(inputArgsAndFlags) <= (i + 1) { return info, fmt.Errorf("invalid flag: %s", arg) } - info.VendorYamlPathFlag = inputArgsAndFlags[i+1] - } else if strings.HasPrefix(arg+"=", cfg.VendorYamlPathFlag) { - var vendorYamlPathFlagParts = strings.Split(arg, "=") - if len(vendorYamlPathFlagParts) != 2 { + info.VendorBasePath = inputArgsAndFlags[i+1] + } else if strings.HasPrefix(arg+"=", cfg.VendorBasePathFlag) { + var vendorBasePathFlagParts = strings.Split(arg, "=") + if len(vendorBasePathFlagParts) != 2 { return info, fmt.Errorf("invalid flag: %s", arg) } - info.VendorYamlPathFlag = vendorYamlPathFlagParts[1] + info.VendorBasePath = vendorBasePathFlagParts[1] } if arg == cfg.DeployRunInitFlag { diff --git a/internal/exec/vendor_utils.go b/internal/exec/vendor_utils.go index a61c131d0..191f947cf 100644 --- a/internal/exec/vendor_utils.go +++ b/internal/exec/vendor_utils.go @@ -6,6 +6,7 @@ import ( "os" "path" "path/filepath" + "sort" "strconv" "strings" "time" @@ -14,6 +15,7 @@ import ( cp "github.com/otiai10/copy" "github.com/samber/lo" "github.com/spf13/cobra" + "gopkg.in/yaml.v2" cfg "github.com/cloudposse/atmos/pkg/config" "github.com/cloudposse/atmos/pkg/schema" @@ -120,23 +122,20 @@ func ExecuteVendorPullCommand(cmd *cobra.Command, args []string) error { } // ReadAndProcessVendorConfigFile reads and processes the Atmos vendoring config file `vendor.yaml` -func ReadAndProcessVendorConfigFile(cliConfig schema.CliConfiguration, vendorConfigFile string) ( - schema.AtmosVendorConfig, - bool, - string, - error, -) { +func ReadAndProcessVendorConfigFile( + cliConfig schema.CliConfiguration, + vendorConfigFile string, +) (schema.AtmosVendorConfig, bool, string, error) { var vendorConfig schema.AtmosVendorConfig - vendorConfigFileExists := true + var vendorConfigFileExists bool var foundVendorConfigFile string - // Check if the vendor config path is defined in atmos.yaml - if cliConfig.Vendor.VendorYamlPath != "" { - // Resolve the vendor_yaml_path relative to base_path if it's a relative path - if !filepath.IsAbs(cliConfig.Vendor.VendorYamlPath) { - foundVendorConfigFile = filepath.Join(cliConfig.BasePath, cliConfig.Vendor.VendorYamlPath) + // Check if vendor config is specified in atmos.yaml + if cliConfig.Vendor.BasePath != "" { + if !filepath.IsAbs(cliConfig.Vendor.BasePath) { + foundVendorConfigFile = filepath.Join(cliConfig.BasePath, cliConfig.Vendor.BasePath) } else { - foundVendorConfigFile = cliConfig.Vendor.VendorYamlPath + foundVendorConfigFile = cliConfig.Vendor.BasePath } } else { // Path is not defined in atmos.yaml, proceed with existing logic @@ -149,32 +148,62 @@ func ReadAndProcessVendorConfigFile(cliConfig schema.CliConfiguration, vendorCon if !u.FileExists(pathToVendorConfig) { vendorConfigFileExists = false - return vendorConfig, vendorConfigFileExists, "", fmt.Errorf("vendor config file '%s' does not exist", pathToVendorConfig) + return vendorConfig, vendorConfigFileExists, "", fmt.Errorf("vendor config file or directory '%s' does not exist", pathToVendorConfig) } foundVendorConfigFile = pathToVendorConfig } } - // Read the vendor config file - vendorConfigFileContent, err := os.ReadFile(foundVendorConfigFile) + // Check if it's a directory + fileInfo, err := os.Stat(foundVendorConfigFile) if err != nil { - return vendorConfig, vendorConfigFileExists, "", err + return vendorConfig, false, "", err } - vendorConfig, err = u.UnmarshalYAML[schema.AtmosVendorConfig](string(vendorConfigFileContent)) - if err != nil { - return vendorConfig, vendorConfigFileExists, "", err + var configFiles []string + if fileInfo.IsDir() { + // Read all .yaml files from directory + entries, err := os.ReadDir(foundVendorConfigFile) + if err != nil { + return vendorConfig, false, "", err + } + + // Filter for .yaml files and sort + for _, entry := range entries { + if !entry.IsDir() && (strings.HasSuffix(entry.Name(), ".yaml") || strings.HasSuffix(entry.Name(), ".yml")) { + configFiles = append(configFiles, filepath.Join(foundVendorConfigFile, entry.Name())) + } + } + sort.Strings(configFiles) + } else { + configFiles = []string{foundVendorConfigFile} } - if vendorConfig.Kind != "AtmosVendorConfig" { - return vendorConfig, vendorConfigFileExists, "", - fmt.Errorf("invalid 'kind: %s' in the vendor config file '%s'. Supported kinds: 'AtmosVendorConfig'", - vendorConfig.Kind, - foundVendorConfigFile, - ) + // Process all config files + var mergedSources []schema.AtmosVendorSource + var mergedImports []string + + for _, configFile := range configFiles { + vendorConfigFileContent, err := os.ReadFile(configFile) + if err != nil { + return vendorConfig, false, "", err + } + + var currentConfig schema.AtmosVendorConfig + if err := yaml.Unmarshal(vendorConfigFileContent, ¤tConfig); err != nil { + return vendorConfig, false, "", err + } + + mergedSources = append(mergedSources, currentConfig.Spec.Sources...) + mergedImports = append(mergedImports, currentConfig.Spec.Imports...) } + // Create final merged config + vendorConfig.Spec.Sources = mergedSources + vendorConfig.Spec.Imports = mergedImports + vendorConfigFileExists = true + return vendorConfig, vendorConfigFileExists, foundVendorConfigFile, nil } diff --git a/pkg/config/const.go b/pkg/config/const.go index cd371fb80..e3e71c29d 100644 --- a/pkg/config/const.go +++ b/pkg/config/const.go @@ -18,7 +18,7 @@ const ( CliConfigDirFlag = "--config-dir" StackDirFlag = "--stacks-dir" BasePathFlag = "--base-path" - VendorYamlPathFlag = "--vendor-yaml-path" + VendorBasePathFlag = "--vendor-base-path" WorkflowDirFlag = "--workflows-dir" KubeConfigConfigFlag = "--kubeconfig-path" JsonSchemaDirFlag = "--schemas-jsonschema-dir" diff --git a/pkg/config/utils.go b/pkg/config/utils.go index ce1cead3d..ced26646f 100644 --- a/pkg/config/utils.go +++ b/pkg/config/utils.go @@ -163,10 +163,10 @@ func processEnvVars(cliConfig *schema.CliConfiguration) error { cliConfig.BasePath = basePath } - vendorYamlPath := os.Getenv("ATMOS_VENDOR_YAML_PATH") - if len(vendorYamlPath) > 0 { - u.LogTrace(*cliConfig, fmt.Sprintf("Found ENV var ATMOS_VENDOR_YAML_PATH=%s", vendorYamlPath)) - cliConfig.Vendor.VendorYamlPath = vendorYamlPath + vendorBasePath := os.Getenv("ATMOS_VENDOR_BASE_PATH") + if len(vendorBasePath) > 0 { + u.LogTrace(*cliConfig, fmt.Sprintf("Found ENV var ATMOS_VENDOR_BASE_PATH=%s", vendorBasePath)) + cliConfig.Vendor.BasePath = vendorBasePath } stacksBasePath := os.Getenv("ATMOS_STACKS_BASE_PATH") diff --git a/pkg/schema/schema.go b/pkg/schema/schema.go index 64897462f..85c2b0ac5 100644 --- a/pkg/schema/schema.go +++ b/pkg/schema/schema.go @@ -131,7 +131,7 @@ type ArgsAndFlagsInfo struct { StacksDir string WorkflowsDir string BasePath string - VendorYamlPathFlag string + VendorBasePath string DeployRunInit string InitRunReconfigure string AutoGenerateBackendFile string @@ -178,7 +178,7 @@ type ConfigAndStacksInfo struct { AdditionalArgsAndFlags []string GlobalOptions []string BasePath string - VendorYamlPathFlag string + VendorBasePathFlag string TerraformCommand string TerraformDir string HelmfileCommand string @@ -551,5 +551,7 @@ type AtmosVendorConfig struct { } type Vendor struct { - VendorYamlPath string `yaml:"vendor_yaml_path" json:"vendor_yaml_path" mapstructure:"vendor_yaml_path"` + // Path to vendor configuration file or directory containing vendor files + // If a directory is specified, all .yaml files in the directory will be processed in lexicographical order + BasePath string `yaml:"base_path" json:"base_path" mapstructure:"base_path"` } From 673828fae4daeb2630346ce21909df4aa982a4e9 Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Wed, 30 Oct 2024 21:38:25 +0000 Subject: [PATCH 15/25] formating changes --- atmos.yaml | 3 +++ examples/demo-vendoring/nested-vendor/vendor1.yaml | 5 +++-- examples/demo-vendoring/vendor/vendor1.yaml | 5 +++-- examples/demo-vendoring/vendor/vendor2.yaml | 5 +++-- website/docs/cli/configuration/configuration.mdx | 4 ++-- 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/atmos.yaml b/atmos.yaml index 931312e27..995064854 100644 --- a/atmos.yaml +++ b/atmos.yaml @@ -22,6 +22,9 @@ vendor: # Supports both absolute and relative paths # If a directory is specified, all .yaml files in the directory will be processed in lexicographical order # Can also be set using 'ATMOS_VENDOR_BASE_PATH' ENV var, or '--vendor-base-path' command-line argument + # Examples: + # base_path: "./vendor.yaml" # Single file + # base_path: "./vendor/configs/" # Directory containing multiple .yaml files base_path: "./vendor.yaml" components: diff --git a/examples/demo-vendoring/nested-vendor/vendor1.yaml b/examples/demo-vendoring/nested-vendor/vendor1.yaml index 59f2ca35e..bb68b6d90 100644 --- a/examples/demo-vendoring/nested-vendor/vendor1.yaml +++ b/examples/demo-vendoring/nested-vendor/vendor1.yaml @@ -2,7 +2,8 @@ apiVersion: atmos/v1 kind: AtmosVendorConfig metadata: name: vendor-test-1 - description: Test vendor config 1 + description: Demo vendor configuration showcasing the structure and usage of Atmos vendor configs. + This example demonstrates component sourcing from GitHub repositories with versioning. spec: sources: - component: "ipinfo" @@ -11,4 +12,4 @@ spec: targets: - "components/terraform/{{ .Component }}/{{.Version}}" tags: - - demo \ No newline at end of file + - demo diff --git a/examples/demo-vendoring/vendor/vendor1.yaml b/examples/demo-vendoring/vendor/vendor1.yaml index 59f2ca35e..05febfff6 100644 --- a/examples/demo-vendoring/vendor/vendor1.yaml +++ b/examples/demo-vendoring/vendor/vendor1.yaml @@ -2,7 +2,8 @@ apiVersion: atmos/v1 kind: AtmosVendorConfig metadata: name: vendor-test-1 - description: Test vendor config 1 + description: Demo vendor configuration showcasing the structure and usage of Atmos vendor configs. + This example demonstrates component sourcing from GitHub repositories with versioning. spec: sources: - component: "ipinfo" @@ -11,4 +12,4 @@ spec: targets: - "components/terraform/{{ .Component }}/{{.Version}}" tags: - - demo \ No newline at end of file + - demo diff --git a/examples/demo-vendoring/vendor/vendor2.yaml b/examples/demo-vendoring/vendor/vendor2.yaml index 5b664fca3..cffa3a2b7 100644 --- a/examples/demo-vendoring/vendor/vendor2.yaml +++ b/examples/demo-vendoring/vendor/vendor2.yaml @@ -2,7 +2,8 @@ apiVersion: atmos/v1 kind: AtmosVendorConfig metadata: name: vendor-test-2 - description: Test vendor config 2 + description: Demo vendor configuration showcasing the structure and usage of Atmos vendor configs. + This example demonstrates component sourcing from GitHub repositories with versioning. spec: sources: - component: "weather" @@ -11,4 +12,4 @@ spec: targets: - "components/terraform/{{ .Component }}/{{.Version}}" tags: - - demo \ No newline at end of file + - demo diff --git a/website/docs/cli/configuration/configuration.mdx b/website/docs/cli/configuration/configuration.mdx index e0dfa3c97..a2227bbcb 100644 --- a/website/docs/cli/configuration/configuration.mdx +++ b/website/docs/cli/configuration/configuration.mdx @@ -49,7 +49,7 @@ If `atmos.yaml` is not found in any of the searched locations, Atmos will use th ```yaml base_path: "." vendor: - vendor_yaml_path: vendor.yaml + base_path: "./vendor.yaml" components: terraform: base_path: components/terraform @@ -607,7 +607,7 @@ setting `ATMOS_STACKS_BASE_PATH` to a path in `/localhost` to your local develop |:------------------------------------------------------|:------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ATMOS_CLI_CONFIG_PATH | N/A | Where to find `atmos.yaml`. Path to a folder where `atmos.yaml` CLI config file is located (e.g. `/config`) | | ATMOS_BASE_PATH | base_path | Base path to `components` and `stacks` folders | -| ATMOS_VENDOR_YAML_PATH | vendor.vendor_yaml_path | Path to the vendor configuration file (vendor.yaml). Supports both absolute and relative paths. Used to configure vendor-specific settings for the Atmos CLI. | +| ATMOS_VENDOR_BASE_PATH | vendor.base_path | Path to vendor configuration file or directory containing vendor files. If a directory is specified, all .yaml files in the directory will be processed in lexicographical order. Supports both absolute and relative paths. | | ATMOS_COMPONENTS_TERRAFORM_COMMAND | components.terraform.command | The executable to be called by `atmos` when running Terraform commands | | ATMOS_COMPONENTS_TERRAFORM_BASE_PATH | components.terraform.base_path | Base path to Terraform components | | ATMOS_COMPONENTS_TERRAFORM_APPLY_AUTO_APPROVE | components.terraform.apply_auto_approve | If set to `true`, auto-generate Terraform backend config files when executing `atmos terraform` commands | From 69afaf1f25053b4010d55e6c7d924c7585a3b99e Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Wed, 30 Oct 2024 22:18:51 +0000 Subject: [PATCH 16/25] feat: added doublestar support --- internal/exec/vendor_utils.go | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/internal/exec/vendor_utils.go b/internal/exec/vendor_utils.go index 191f947cf..ebed3f914 100644 --- a/internal/exec/vendor_utils.go +++ b/internal/exec/vendor_utils.go @@ -17,6 +17,7 @@ import ( "github.com/spf13/cobra" "gopkg.in/yaml.v2" + "github.com/bmatcuk/doublestar/v4" cfg "github.com/cloudposse/atmos/pkg/config" "github.com/cloudposse/atmos/pkg/schema" u "github.com/cloudposse/atmos/pkg/utils" @@ -163,18 +164,14 @@ func ReadAndProcessVendorConfigFile( var configFiles []string if fileInfo.IsDir() { - // Read all .yaml files from directory - entries, err := os.ReadDir(foundVendorConfigFile) + matches, err := doublestar.Glob(os.DirFS(foundVendorConfigFile), "**/*.{yaml,yml}") if err != nil { return vendorConfig, false, "", err } - - // Filter for .yaml files and sort - for _, entry := range entries { - if !entry.IsDir() && (strings.HasSuffix(entry.Name(), ".yaml") || strings.HasSuffix(entry.Name(), ".yml")) { - configFiles = append(configFiles, filepath.Join(foundVendorConfigFile, entry.Name())) - } + for i, match := range matches { + matches[i] = filepath.Join(foundVendorConfigFile, match) } + configFiles = matches sort.Strings(configFiles) } else { configFiles = []string{foundVendorConfigFile} From f17ba17208a35fec913f3370519917926e9f60e1 Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Wed, 30 Oct 2024 22:23:29 +0000 Subject: [PATCH 17/25] address commit requests --- atmos.yaml | 4 ++-- examples/demo-vendoring/atmos.yaml | 2 +- .../demo-vendoring/{nested-vendor => vendor.d}/vendor1.yaml | 0 3 files changed, 3 insertions(+), 3 deletions(-) rename examples/demo-vendoring/{nested-vendor => vendor.d}/vendor1.yaml (100%) diff --git a/atmos.yaml b/atmos.yaml index 995064854..77fb489a5 100644 --- a/atmos.yaml +++ b/atmos.yaml @@ -15,7 +15,7 @@ # are independent settings (supporting both absolute and relative paths). # If 'base_path' is provided, 'components.terraform.base_path', 'components.helmfile.base_path', 'stacks.base_path' and 'workflows.base_path' # are considered paths relative to 'base_path'. -base_path: "./examples/quick-start-advanced" +base_path: "./" vendor: # Path to vendor configuration file or directory containing vendor files @@ -24,7 +24,7 @@ vendor: # Can also be set using 'ATMOS_VENDOR_BASE_PATH' ENV var, or '--vendor-base-path' command-line argument # Examples: # base_path: "./vendor.yaml" # Single file - # base_path: "./vendor/configs/" # Directory containing multiple .yaml files + # base_path: "./vendor.d/" # Directory containing multiple .yaml files base_path: "./vendor.yaml" components: diff --git a/examples/demo-vendoring/atmos.yaml b/examples/demo-vendoring/atmos.yaml index 54bf52cc6..a3b1d5c2a 100644 --- a/examples/demo-vendoring/atmos.yaml +++ b/examples/demo-vendoring/atmos.yaml @@ -24,7 +24,7 @@ vendor: #base_path: "./vendor" # Absolute path - # base_path: "nested-vendor/vendor1.yaml" + # base_path: "vendor.d/vendor1.yaml" logs: file: "/dev/stderr" diff --git a/examples/demo-vendoring/nested-vendor/vendor1.yaml b/examples/demo-vendoring/vendor.d/vendor1.yaml similarity index 100% rename from examples/demo-vendoring/nested-vendor/vendor1.yaml rename to examples/demo-vendoring/vendor.d/vendor1.yaml From f33daa4c5e1fd1c34006905cb4de01f21ba12ad9 Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Thu, 31 Oct 2024 00:12:34 +0000 Subject: [PATCH 18/25] deduplicate imports feature --- internal/exec/vendor_utils.go | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/internal/exec/vendor_utils.go b/internal/exec/vendor_utils.go index ebed3f914..34fe4abc1 100644 --- a/internal/exec/vendor_utils.go +++ b/internal/exec/vendor_utils.go @@ -181,19 +181,37 @@ func ReadAndProcessVendorConfigFile( var mergedSources []schema.AtmosVendorSource var mergedImports []string + seenSources := make(map[string]bool) + seenImports := make(map[string]bool) + for _, configFile := range configFiles { vendorConfigFileContent, err := os.ReadFile(configFile) if err != nil { - return vendorConfig, false, "", err + return vendorConfig, false, "", fmt.Errorf("error reading vendor config file '%s': %w", configFile, err) } var currentConfig schema.AtmosVendorConfig if err := yaml.Unmarshal(vendorConfigFileContent, ¤tConfig); err != nil { - return vendorConfig, false, "", err + return vendorConfig, false, "", fmt.Errorf("error parsing YAML file '%s': %w", configFile, err) + } + + // Set file field and deduplicate sources + for i := range currentConfig.Spec.Sources { + source := ¤tConfig.Spec.Sources[i] + source.File = configFile + if !seenSources[source.Source] { + vendorConfig.Spec.Sources = append(vendorConfig.Spec.Sources, *source) + seenSources[source.Source] = true + } } - mergedSources = append(mergedSources, currentConfig.Spec.Sources...) - mergedImports = append(mergedImports, currentConfig.Spec.Imports...) + // Deduplicate imports + for _, imp := range currentConfig.Spec.Imports { + if !seenImports[imp] { + vendorConfig.Spec.Imports = append(vendorConfig.Spec.Imports, imp) + seenImports[imp] = true + } + } } // Create final merged config From 9e94dd549214ea650dd8f3824ac19377ad72117a Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Thu, 31 Oct 2024 11:55:31 +0000 Subject: [PATCH 19/25] general fixes and vendoring folder formating clean up --- examples/demo-vendoring/atmos.yaml | 2 +- .../github/stargazers/main/README.md | 13 +++++ .../terraform/github/stargazers/main/main.tf | 3 ++ .../github/stargazers/main/outputs.tf | 4 ++ .../github/stargazers/main/providers.tf | 3 ++ .../github/stargazers/main/variables.tf | 4 ++ .../github/stargazers/main/versions.tf | 5 ++ .../terraform/ipinfo/main/README.md | 13 +++++ .../components/terraform/ipinfo/main/main.tf | 7 +++ .../terraform/ipinfo/main/outputs.tf | 4 ++ .../terraform/ipinfo/main/providers.tf | 1 + .../terraform/ipinfo/main/variables.tf | 5 ++ .../terraform/ipinfo/main/versions.tf | 5 ++ .../terraform/weather/main/README.md | 50 +++++++++++++++++++ .../components/terraform/weather/main/main.tf | 22 ++++++++ .../terraform/weather/main/outputs.tf | 27 ++++++++++ .../terraform/weather/main/providers.tf | 1 + .../terraform/weather/main/variables.tf | 34 +++++++++++++ .../terraform/weather/main/versions.tf | 5 ++ examples/demo-vendoring/vendor.d/vendor1.yaml | 5 +- examples/demo-vendoring/vendor/vendor1.yaml | 5 +- examples/demo-vendoring/vendor/vendor2.yaml | 5 +- 22 files changed, 216 insertions(+), 7 deletions(-) create mode 100644 examples/demo-vendoring/components/terraform/github/stargazers/main/README.md create mode 100644 examples/demo-vendoring/components/terraform/github/stargazers/main/main.tf create mode 100644 examples/demo-vendoring/components/terraform/github/stargazers/main/outputs.tf create mode 100644 examples/demo-vendoring/components/terraform/github/stargazers/main/providers.tf create mode 100644 examples/demo-vendoring/components/terraform/github/stargazers/main/variables.tf create mode 100644 examples/demo-vendoring/components/terraform/github/stargazers/main/versions.tf create mode 100644 examples/demo-vendoring/components/terraform/ipinfo/main/README.md create mode 100644 examples/demo-vendoring/components/terraform/ipinfo/main/main.tf create mode 100644 examples/demo-vendoring/components/terraform/ipinfo/main/outputs.tf create mode 100644 examples/demo-vendoring/components/terraform/ipinfo/main/providers.tf create mode 100644 examples/demo-vendoring/components/terraform/ipinfo/main/variables.tf create mode 100644 examples/demo-vendoring/components/terraform/ipinfo/main/versions.tf create mode 100644 examples/demo-vendoring/components/terraform/weather/main/README.md create mode 100644 examples/demo-vendoring/components/terraform/weather/main/main.tf create mode 100644 examples/demo-vendoring/components/terraform/weather/main/outputs.tf create mode 100644 examples/demo-vendoring/components/terraform/weather/main/providers.tf create mode 100644 examples/demo-vendoring/components/terraform/weather/main/variables.tf create mode 100644 examples/demo-vendoring/components/terraform/weather/main/versions.tf diff --git a/examples/demo-vendoring/atmos.yaml b/examples/demo-vendoring/atmos.yaml index a3b1d5c2a..20983e4f9 100644 --- a/examples/demo-vendoring/atmos.yaml +++ b/examples/demo-vendoring/atmos.yaml @@ -24,7 +24,7 @@ vendor: #base_path: "./vendor" # Absolute path - # base_path: "vendor.d/vendor1.yaml" + #base_path: "vendor.d/vendor1.yaml" logs: file: "/dev/stderr" diff --git a/examples/demo-vendoring/components/terraform/github/stargazers/main/README.md b/examples/demo-vendoring/components/terraform/github/stargazers/main/README.md new file mode 100644 index 000000000..ef3b13ab6 --- /dev/null +++ b/examples/demo-vendoring/components/terraform/github/stargazers/main/README.md @@ -0,0 +1,13 @@ +# Example Terraform GitHub Stargazers Component + +This Terraform module retrieves the number of stargazers for a specified GitHub repository. + +## Usage + +### Inputs + +- `repository`: The GitHub repository in the format 'owner/repo'. + +### Outputs + +- `stargazers_count`: The number of stargazers for the specified GitHub repository. diff --git a/examples/demo-vendoring/components/terraform/github/stargazers/main/main.tf b/examples/demo-vendoring/components/terraform/github/stargazers/main/main.tf new file mode 100644 index 000000000..bbaef9513 --- /dev/null +++ b/examples/demo-vendoring/components/terraform/github/stargazers/main/main.tf @@ -0,0 +1,3 @@ +data "github_repository" "repo" { + full_name = var.repository +} diff --git a/examples/demo-vendoring/components/terraform/github/stargazers/main/outputs.tf b/examples/demo-vendoring/components/terraform/github/stargazers/main/outputs.tf new file mode 100644 index 000000000..5f3cbbff2 --- /dev/null +++ b/examples/demo-vendoring/components/terraform/github/stargazers/main/outputs.tf @@ -0,0 +1,4 @@ +output "stargazers_count" { + description = "The number of stargazers for the specified GitHub repository" + value = data.github_repository.repo.stargazers_count +} diff --git a/examples/demo-vendoring/components/terraform/github/stargazers/main/providers.tf b/examples/demo-vendoring/components/terraform/github/stargazers/main/providers.tf new file mode 100644 index 000000000..d08ff256a --- /dev/null +++ b/examples/demo-vendoring/components/terraform/github/stargazers/main/providers.tf @@ -0,0 +1,3 @@ +provider "github" { + # No token is needed for accessing public repository data +} diff --git a/examples/demo-vendoring/components/terraform/github/stargazers/main/variables.tf b/examples/demo-vendoring/components/terraform/github/stargazers/main/variables.tf new file mode 100644 index 000000000..5fbe9ff26 --- /dev/null +++ b/examples/demo-vendoring/components/terraform/github/stargazers/main/variables.tf @@ -0,0 +1,4 @@ +variable "repository" { + description = "The GitHub repository in the format 'owner/repo'" + type = string +} diff --git a/examples/demo-vendoring/components/terraform/github/stargazers/main/versions.tf b/examples/demo-vendoring/components/terraform/github/stargazers/main/versions.tf new file mode 100644 index 000000000..e2a3d732d --- /dev/null +++ b/examples/demo-vendoring/components/terraform/github/stargazers/main/versions.tf @@ -0,0 +1,5 @@ +terraform { + required_version = ">= 1.0.0" + + required_providers {} +} diff --git a/examples/demo-vendoring/components/terraform/ipinfo/main/README.md b/examples/demo-vendoring/components/terraform/ipinfo/main/README.md new file mode 100644 index 000000000..a1b28ebfd --- /dev/null +++ b/examples/demo-vendoring/components/terraform/ipinfo/main/README.md @@ -0,0 +1,13 @@ +# Example Terraform IPinfo Component + +This Terraform module retrieves data from the IPinfo API for a specified IP address. If no IP address is specified, it retrieves data for the requester's IP address. + +## Usage + +### Inputs + +- `ip_address` (optional): The IP address to retrieve information for. If not specified, the requester's IP address will be used. The default value is an empty string. + +### Outputs + +- `metadata`: The data retrieved from IPinfo for the specified IP address, in JSON format. diff --git a/examples/demo-vendoring/components/terraform/ipinfo/main/main.tf b/examples/demo-vendoring/components/terraform/ipinfo/main/main.tf new file mode 100644 index 000000000..0e3e9d0b0 --- /dev/null +++ b/examples/demo-vendoring/components/terraform/ipinfo/main/main.tf @@ -0,0 +1,7 @@ +data "http" "ipinfo" { + url = var.ip_address != "" ? "https://ipinfo.io/${var.ip_address}" : "https://ipinfo.io" + + request_headers = { + Accept = "application/json" + } +} diff --git a/examples/demo-vendoring/components/terraform/ipinfo/main/outputs.tf b/examples/demo-vendoring/components/terraform/ipinfo/main/outputs.tf new file mode 100644 index 000000000..12bb2bb8d --- /dev/null +++ b/examples/demo-vendoring/components/terraform/ipinfo/main/outputs.tf @@ -0,0 +1,4 @@ +output "metadata" { + description = "The data retrieved from IPinfo for the specified IP address" + value = jsondecode(data.http.ipinfo.response_body) +} diff --git a/examples/demo-vendoring/components/terraform/ipinfo/main/providers.tf b/examples/demo-vendoring/components/terraform/ipinfo/main/providers.tf new file mode 100644 index 000000000..0b91fe2aa --- /dev/null +++ b/examples/demo-vendoring/components/terraform/ipinfo/main/providers.tf @@ -0,0 +1 @@ +provider "http" {} diff --git a/examples/demo-vendoring/components/terraform/ipinfo/main/variables.tf b/examples/demo-vendoring/components/terraform/ipinfo/main/variables.tf new file mode 100644 index 000000000..85f32544d --- /dev/null +++ b/examples/demo-vendoring/components/terraform/ipinfo/main/variables.tf @@ -0,0 +1,5 @@ +variable "ip_address" { + description = "The IP address to retrieve information for (optional)" + type = string + default = "" +} diff --git a/examples/demo-vendoring/components/terraform/ipinfo/main/versions.tf b/examples/demo-vendoring/components/terraform/ipinfo/main/versions.tf new file mode 100644 index 000000000..e2a3d732d --- /dev/null +++ b/examples/demo-vendoring/components/terraform/ipinfo/main/versions.tf @@ -0,0 +1,5 @@ +terraform { + required_version = ">= 1.0.0" + + required_providers {} +} diff --git a/examples/demo-vendoring/components/terraform/weather/main/README.md b/examples/demo-vendoring/components/terraform/weather/main/README.md new file mode 100644 index 000000000..1d7a7ee03 --- /dev/null +++ b/examples/demo-vendoring/components/terraform/weather/main/README.md @@ -0,0 +1,50 @@ +# Example Terraform Weather Component + +This Terraform "root" module fetches weather information for a specified location with custom display options. +It queries data from the [`wttr.in`](https://wttr.in) weather service and stores the result in a local file (`cache.txt`). +It also provides several outputs like weather information, request URL, stage, location, language, and units of measurement. + +## Features + +- Fetch weather updates for a location using HTTP request. +- Write the obtained weather data in a local file. +- Customizable display options. +- View the request URL. +- Get informed about the stage, location, language, and units in the metadata. + +## Usage + +To include this module in your [Atmos Stacks](https://atmos.tools/core-concepts/stacks) configuration: + +```yaml +components: + terraform: + weather: + vars: + stage: dev + location: New York + options: 0T + format: v2 + lang: en + units: m +``` + +### Inputs +- `stage`: Stage where it will be deployed. +- `location`: Location for which the weather is reported. Default is "Los Angeles". +- `options`: Options to customize the output. Default is "0T". +- `format`: Specifies the output format. Default is "v2". +- `lang`: Language in which the weather will be displayed. Default is "en". +- `units`: Units in which the weather will be displayed. Default is "m". + +### Outputs +- `weather`: The fetched weather data. +- `url`: Requested URL. +- `stage`: Stage of deployment. +- `location`: Location of the reported weather. +- `lang`: Language used for weather data. +- `units`: Units of measurement for the weather data. + +Please note, this module requires Terraform version >=1.0.0, and you need to specify no other required providers. + +Happy Weather Tracking! diff --git a/examples/demo-vendoring/components/terraform/weather/main/main.tf b/examples/demo-vendoring/components/terraform/weather/main/main.tf new file mode 100644 index 000000000..9971bf5b0 --- /dev/null +++ b/examples/demo-vendoring/components/terraform/weather/main/main.tf @@ -0,0 +1,22 @@ +locals { + url = format("https://wttr.in/%v?%v&format=%v&lang=%v&u=%v", + urlencode(var.location), + urlencode(var.options), + urlencode(var.format), + urlencode(var.lang), + urlencode(var.units), + ) +} + +data "http" "weather" { + url = local.url + request_headers = { + User-Agent = "curl" + } +} + +# Now write this to a file (as an example of a resource) +resource "local_file" "cache" { + filename = "cache.${var.stage}.txt" + content = data.http.weather.response_body +} diff --git a/examples/demo-vendoring/components/terraform/weather/main/outputs.tf b/examples/demo-vendoring/components/terraform/weather/main/outputs.tf new file mode 100644 index 000000000..f0e7fd442 --- /dev/null +++ b/examples/demo-vendoring/components/terraform/weather/main/outputs.tf @@ -0,0 +1,27 @@ +output "weather" { + value = data.http.weather.response_body +} + +output "url" { + value = local.url +} + +output "stage" { + value = var.stage + description = "Stage where it was deployed" +} + +output "location" { + value = var.location + description = "Location of the weather report." +} + +output "lang" { + value = var.lang + description = "Language which the weather is displayed." +} + +output "units" { + value = var.units + description = "Units the weather is displayed." +} diff --git a/examples/demo-vendoring/components/terraform/weather/main/providers.tf b/examples/demo-vendoring/components/terraform/weather/main/providers.tf new file mode 100644 index 000000000..0b91fe2aa --- /dev/null +++ b/examples/demo-vendoring/components/terraform/weather/main/providers.tf @@ -0,0 +1 @@ +provider "http" {} diff --git a/examples/demo-vendoring/components/terraform/weather/main/variables.tf b/examples/demo-vendoring/components/terraform/weather/main/variables.tf new file mode 100644 index 000000000..c8a32310a --- /dev/null +++ b/examples/demo-vendoring/components/terraform/weather/main/variables.tf @@ -0,0 +1,34 @@ +variable "stage" { + description = "Stage where it will be deployed" + type = string +} + +variable "location" { + description = "Location for which the weather." + type = string + default = "Los Angeles" +} + +variable "options" { + description = "Options to customize the output." + type = string + default = "0T" +} + +variable "format" { + description = "Format of the output." + type = string + default = "v2" +} + +variable "lang" { + description = "Language in which the weather is displayed." + type = string + default = "en" +} + +variable "units" { + description = "Units in which the weather is displayed." + type = string + default = "m" +} diff --git a/examples/demo-vendoring/components/terraform/weather/main/versions.tf b/examples/demo-vendoring/components/terraform/weather/main/versions.tf new file mode 100644 index 000000000..e2a3d732d --- /dev/null +++ b/examples/demo-vendoring/components/terraform/weather/main/versions.tf @@ -0,0 +1,5 @@ +terraform { + required_version = ">= 1.0.0" + + required_providers {} +} diff --git a/examples/demo-vendoring/vendor.d/vendor1.yaml b/examples/demo-vendoring/vendor.d/vendor1.yaml index bb68b6d90..68cf94762 100644 --- a/examples/demo-vendoring/vendor.d/vendor1.yaml +++ b/examples/demo-vendoring/vendor.d/vendor1.yaml @@ -2,8 +2,9 @@ apiVersion: atmos/v1 kind: AtmosVendorConfig metadata: name: vendor-test-1 - description: Demo vendor configuration showcasing the structure and usage of Atmos vendor configs. - This example demonstrates component sourcing from GitHub repositories with versioning. + description: | + Demo vendor configuration showcasing the structure and usage of Atmos vendor configs. + This example demonstrates component sourcing from GitHub repositories with versioning. spec: sources: - component: "ipinfo" diff --git a/examples/demo-vendoring/vendor/vendor1.yaml b/examples/demo-vendoring/vendor/vendor1.yaml index 05febfff6..68cf94762 100644 --- a/examples/demo-vendoring/vendor/vendor1.yaml +++ b/examples/demo-vendoring/vendor/vendor1.yaml @@ -2,8 +2,9 @@ apiVersion: atmos/v1 kind: AtmosVendorConfig metadata: name: vendor-test-1 - description: Demo vendor configuration showcasing the structure and usage of Atmos vendor configs. - This example demonstrates component sourcing from GitHub repositories with versioning. + description: | + Demo vendor configuration showcasing the structure and usage of Atmos vendor configs. + This example demonstrates component sourcing from GitHub repositories with versioning. spec: sources: - component: "ipinfo" diff --git a/examples/demo-vendoring/vendor/vendor2.yaml b/examples/demo-vendoring/vendor/vendor2.yaml index cffa3a2b7..6d28fb481 100644 --- a/examples/demo-vendoring/vendor/vendor2.yaml +++ b/examples/demo-vendoring/vendor/vendor2.yaml @@ -2,8 +2,9 @@ apiVersion: atmos/v1 kind: AtmosVendorConfig metadata: name: vendor-test-2 - description: Demo vendor configuration showcasing the structure and usage of Atmos vendor configs. - This example demonstrates component sourcing from GitHub repositories with versioning. + description: | + Demo vendor configuration showcasing the structure and usage of Atmos vendor configs. + This example demonstrates component sourcing from GitHub repositories with versioning. spec: sources: - component: "weather" From aa85470efce068fb5bac641371cef55da2f95f7c Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Thu, 31 Oct 2024 11:55:51 +0000 Subject: [PATCH 20/25] general fixes and vendoring folder formating clean up --- .../github/stargazers/main/README.md | 13 ----- .../terraform/github/stargazers/main/main.tf | 3 -- .../github/stargazers/main/outputs.tf | 4 -- .../github/stargazers/main/providers.tf | 3 -- .../github/stargazers/main/variables.tf | 4 -- .../github/stargazers/main/versions.tf | 5 -- .../terraform/ipinfo/main/README.md | 13 ----- .../components/terraform/ipinfo/main/main.tf | 7 --- .../terraform/ipinfo/main/outputs.tf | 4 -- .../terraform/ipinfo/main/providers.tf | 1 - .../terraform/ipinfo/main/variables.tf | 5 -- .../terraform/ipinfo/main/versions.tf | 5 -- .../terraform/weather/main/README.md | 50 ------------------- .../components/terraform/weather/main/main.tf | 22 -------- .../terraform/weather/main/outputs.tf | 27 ---------- .../terraform/weather/main/providers.tf | 1 - .../terraform/weather/main/variables.tf | 34 ------------- .../terraform/weather/main/versions.tf | 5 -- 18 files changed, 206 deletions(-) delete mode 100644 examples/demo-vendoring/components/terraform/github/stargazers/main/README.md delete mode 100644 examples/demo-vendoring/components/terraform/github/stargazers/main/main.tf delete mode 100644 examples/demo-vendoring/components/terraform/github/stargazers/main/outputs.tf delete mode 100644 examples/demo-vendoring/components/terraform/github/stargazers/main/providers.tf delete mode 100644 examples/demo-vendoring/components/terraform/github/stargazers/main/variables.tf delete mode 100644 examples/demo-vendoring/components/terraform/github/stargazers/main/versions.tf delete mode 100644 examples/demo-vendoring/components/terraform/ipinfo/main/README.md delete mode 100644 examples/demo-vendoring/components/terraform/ipinfo/main/main.tf delete mode 100644 examples/demo-vendoring/components/terraform/ipinfo/main/outputs.tf delete mode 100644 examples/demo-vendoring/components/terraform/ipinfo/main/providers.tf delete mode 100644 examples/demo-vendoring/components/terraform/ipinfo/main/variables.tf delete mode 100644 examples/demo-vendoring/components/terraform/ipinfo/main/versions.tf delete mode 100644 examples/demo-vendoring/components/terraform/weather/main/README.md delete mode 100644 examples/demo-vendoring/components/terraform/weather/main/main.tf delete mode 100644 examples/demo-vendoring/components/terraform/weather/main/outputs.tf delete mode 100644 examples/demo-vendoring/components/terraform/weather/main/providers.tf delete mode 100644 examples/demo-vendoring/components/terraform/weather/main/variables.tf delete mode 100644 examples/demo-vendoring/components/terraform/weather/main/versions.tf diff --git a/examples/demo-vendoring/components/terraform/github/stargazers/main/README.md b/examples/demo-vendoring/components/terraform/github/stargazers/main/README.md deleted file mode 100644 index ef3b13ab6..000000000 --- a/examples/demo-vendoring/components/terraform/github/stargazers/main/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Example Terraform GitHub Stargazers Component - -This Terraform module retrieves the number of stargazers for a specified GitHub repository. - -## Usage - -### Inputs - -- `repository`: The GitHub repository in the format 'owner/repo'. - -### Outputs - -- `stargazers_count`: The number of stargazers for the specified GitHub repository. diff --git a/examples/demo-vendoring/components/terraform/github/stargazers/main/main.tf b/examples/demo-vendoring/components/terraform/github/stargazers/main/main.tf deleted file mode 100644 index bbaef9513..000000000 --- a/examples/demo-vendoring/components/terraform/github/stargazers/main/main.tf +++ /dev/null @@ -1,3 +0,0 @@ -data "github_repository" "repo" { - full_name = var.repository -} diff --git a/examples/demo-vendoring/components/terraform/github/stargazers/main/outputs.tf b/examples/demo-vendoring/components/terraform/github/stargazers/main/outputs.tf deleted file mode 100644 index 5f3cbbff2..000000000 --- a/examples/demo-vendoring/components/terraform/github/stargazers/main/outputs.tf +++ /dev/null @@ -1,4 +0,0 @@ -output "stargazers_count" { - description = "The number of stargazers for the specified GitHub repository" - value = data.github_repository.repo.stargazers_count -} diff --git a/examples/demo-vendoring/components/terraform/github/stargazers/main/providers.tf b/examples/demo-vendoring/components/terraform/github/stargazers/main/providers.tf deleted file mode 100644 index d08ff256a..000000000 --- a/examples/demo-vendoring/components/terraform/github/stargazers/main/providers.tf +++ /dev/null @@ -1,3 +0,0 @@ -provider "github" { - # No token is needed for accessing public repository data -} diff --git a/examples/demo-vendoring/components/terraform/github/stargazers/main/variables.tf b/examples/demo-vendoring/components/terraform/github/stargazers/main/variables.tf deleted file mode 100644 index 5fbe9ff26..000000000 --- a/examples/demo-vendoring/components/terraform/github/stargazers/main/variables.tf +++ /dev/null @@ -1,4 +0,0 @@ -variable "repository" { - description = "The GitHub repository in the format 'owner/repo'" - type = string -} diff --git a/examples/demo-vendoring/components/terraform/github/stargazers/main/versions.tf b/examples/demo-vendoring/components/terraform/github/stargazers/main/versions.tf deleted file mode 100644 index e2a3d732d..000000000 --- a/examples/demo-vendoring/components/terraform/github/stargazers/main/versions.tf +++ /dev/null @@ -1,5 +0,0 @@ -terraform { - required_version = ">= 1.0.0" - - required_providers {} -} diff --git a/examples/demo-vendoring/components/terraform/ipinfo/main/README.md b/examples/demo-vendoring/components/terraform/ipinfo/main/README.md deleted file mode 100644 index a1b28ebfd..000000000 --- a/examples/demo-vendoring/components/terraform/ipinfo/main/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Example Terraform IPinfo Component - -This Terraform module retrieves data from the IPinfo API for a specified IP address. If no IP address is specified, it retrieves data for the requester's IP address. - -## Usage - -### Inputs - -- `ip_address` (optional): The IP address to retrieve information for. If not specified, the requester's IP address will be used. The default value is an empty string. - -### Outputs - -- `metadata`: The data retrieved from IPinfo for the specified IP address, in JSON format. diff --git a/examples/demo-vendoring/components/terraform/ipinfo/main/main.tf b/examples/demo-vendoring/components/terraform/ipinfo/main/main.tf deleted file mode 100644 index 0e3e9d0b0..000000000 --- a/examples/demo-vendoring/components/terraform/ipinfo/main/main.tf +++ /dev/null @@ -1,7 +0,0 @@ -data "http" "ipinfo" { - url = var.ip_address != "" ? "https://ipinfo.io/${var.ip_address}" : "https://ipinfo.io" - - request_headers = { - Accept = "application/json" - } -} diff --git a/examples/demo-vendoring/components/terraform/ipinfo/main/outputs.tf b/examples/demo-vendoring/components/terraform/ipinfo/main/outputs.tf deleted file mode 100644 index 12bb2bb8d..000000000 --- a/examples/demo-vendoring/components/terraform/ipinfo/main/outputs.tf +++ /dev/null @@ -1,4 +0,0 @@ -output "metadata" { - description = "The data retrieved from IPinfo for the specified IP address" - value = jsondecode(data.http.ipinfo.response_body) -} diff --git a/examples/demo-vendoring/components/terraform/ipinfo/main/providers.tf b/examples/demo-vendoring/components/terraform/ipinfo/main/providers.tf deleted file mode 100644 index 0b91fe2aa..000000000 --- a/examples/demo-vendoring/components/terraform/ipinfo/main/providers.tf +++ /dev/null @@ -1 +0,0 @@ -provider "http" {} diff --git a/examples/demo-vendoring/components/terraform/ipinfo/main/variables.tf b/examples/demo-vendoring/components/terraform/ipinfo/main/variables.tf deleted file mode 100644 index 85f32544d..000000000 --- a/examples/demo-vendoring/components/terraform/ipinfo/main/variables.tf +++ /dev/null @@ -1,5 +0,0 @@ -variable "ip_address" { - description = "The IP address to retrieve information for (optional)" - type = string - default = "" -} diff --git a/examples/demo-vendoring/components/terraform/ipinfo/main/versions.tf b/examples/demo-vendoring/components/terraform/ipinfo/main/versions.tf deleted file mode 100644 index e2a3d732d..000000000 --- a/examples/demo-vendoring/components/terraform/ipinfo/main/versions.tf +++ /dev/null @@ -1,5 +0,0 @@ -terraform { - required_version = ">= 1.0.0" - - required_providers {} -} diff --git a/examples/demo-vendoring/components/terraform/weather/main/README.md b/examples/demo-vendoring/components/terraform/weather/main/README.md deleted file mode 100644 index 1d7a7ee03..000000000 --- a/examples/demo-vendoring/components/terraform/weather/main/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# Example Terraform Weather Component - -This Terraform "root" module fetches weather information for a specified location with custom display options. -It queries data from the [`wttr.in`](https://wttr.in) weather service and stores the result in a local file (`cache.txt`). -It also provides several outputs like weather information, request URL, stage, location, language, and units of measurement. - -## Features - -- Fetch weather updates for a location using HTTP request. -- Write the obtained weather data in a local file. -- Customizable display options. -- View the request URL. -- Get informed about the stage, location, language, and units in the metadata. - -## Usage - -To include this module in your [Atmos Stacks](https://atmos.tools/core-concepts/stacks) configuration: - -```yaml -components: - terraform: - weather: - vars: - stage: dev - location: New York - options: 0T - format: v2 - lang: en - units: m -``` - -### Inputs -- `stage`: Stage where it will be deployed. -- `location`: Location for which the weather is reported. Default is "Los Angeles". -- `options`: Options to customize the output. Default is "0T". -- `format`: Specifies the output format. Default is "v2". -- `lang`: Language in which the weather will be displayed. Default is "en". -- `units`: Units in which the weather will be displayed. Default is "m". - -### Outputs -- `weather`: The fetched weather data. -- `url`: Requested URL. -- `stage`: Stage of deployment. -- `location`: Location of the reported weather. -- `lang`: Language used for weather data. -- `units`: Units of measurement for the weather data. - -Please note, this module requires Terraform version >=1.0.0, and you need to specify no other required providers. - -Happy Weather Tracking! diff --git a/examples/demo-vendoring/components/terraform/weather/main/main.tf b/examples/demo-vendoring/components/terraform/weather/main/main.tf deleted file mode 100644 index 9971bf5b0..000000000 --- a/examples/demo-vendoring/components/terraform/weather/main/main.tf +++ /dev/null @@ -1,22 +0,0 @@ -locals { - url = format("https://wttr.in/%v?%v&format=%v&lang=%v&u=%v", - urlencode(var.location), - urlencode(var.options), - urlencode(var.format), - urlencode(var.lang), - urlencode(var.units), - ) -} - -data "http" "weather" { - url = local.url - request_headers = { - User-Agent = "curl" - } -} - -# Now write this to a file (as an example of a resource) -resource "local_file" "cache" { - filename = "cache.${var.stage}.txt" - content = data.http.weather.response_body -} diff --git a/examples/demo-vendoring/components/terraform/weather/main/outputs.tf b/examples/demo-vendoring/components/terraform/weather/main/outputs.tf deleted file mode 100644 index f0e7fd442..000000000 --- a/examples/demo-vendoring/components/terraform/weather/main/outputs.tf +++ /dev/null @@ -1,27 +0,0 @@ -output "weather" { - value = data.http.weather.response_body -} - -output "url" { - value = local.url -} - -output "stage" { - value = var.stage - description = "Stage where it was deployed" -} - -output "location" { - value = var.location - description = "Location of the weather report." -} - -output "lang" { - value = var.lang - description = "Language which the weather is displayed." -} - -output "units" { - value = var.units - description = "Units the weather is displayed." -} diff --git a/examples/demo-vendoring/components/terraform/weather/main/providers.tf b/examples/demo-vendoring/components/terraform/weather/main/providers.tf deleted file mode 100644 index 0b91fe2aa..000000000 --- a/examples/demo-vendoring/components/terraform/weather/main/providers.tf +++ /dev/null @@ -1 +0,0 @@ -provider "http" {} diff --git a/examples/demo-vendoring/components/terraform/weather/main/variables.tf b/examples/demo-vendoring/components/terraform/weather/main/variables.tf deleted file mode 100644 index c8a32310a..000000000 --- a/examples/demo-vendoring/components/terraform/weather/main/variables.tf +++ /dev/null @@ -1,34 +0,0 @@ -variable "stage" { - description = "Stage where it will be deployed" - type = string -} - -variable "location" { - description = "Location for which the weather." - type = string - default = "Los Angeles" -} - -variable "options" { - description = "Options to customize the output." - type = string - default = "0T" -} - -variable "format" { - description = "Format of the output." - type = string - default = "v2" -} - -variable "lang" { - description = "Language in which the weather is displayed." - type = string - default = "en" -} - -variable "units" { - description = "Units in which the weather is displayed." - type = string - default = "m" -} diff --git a/examples/demo-vendoring/components/terraform/weather/main/versions.tf b/examples/demo-vendoring/components/terraform/weather/main/versions.tf deleted file mode 100644 index e2a3d732d..000000000 --- a/examples/demo-vendoring/components/terraform/weather/main/versions.tf +++ /dev/null @@ -1,5 +0,0 @@ -terraform { - required_version = ">= 1.0.0" - - required_providers {} -} From a29cf8278184bd15b7a2ef83966cdea938e2d897 Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Thu, 31 Oct 2024 11:56:20 +0000 Subject: [PATCH 21/25] fixes for iteration over vendor files --- internal/exec/vendor_utils.go | 47 +++++++++++++---------------------- 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/internal/exec/vendor_utils.go b/internal/exec/vendor_utils.go index 34fe4abc1..ba1029b84 100644 --- a/internal/exec/vendor_utils.go +++ b/internal/exec/vendor_utils.go @@ -128,6 +128,10 @@ func ReadAndProcessVendorConfigFile( vendorConfigFile string, ) (schema.AtmosVendorConfig, bool, string, error) { var vendorConfig schema.AtmosVendorConfig + + // Initialize empty sources slice + vendorConfig.Spec.Sources = []schema.AtmosVendorSource{} + var vendorConfigFileExists bool var foundVendorConfigFile string @@ -164,14 +168,13 @@ func ReadAndProcessVendorConfigFile( var configFiles []string if fileInfo.IsDir() { - matches, err := doublestar.Glob(os.DirFS(foundVendorConfigFile), "**/*.{yaml,yml}") + matches, err := doublestar.Glob(os.DirFS(foundVendorConfigFile), "*.{yaml,yml}") if err != nil { return vendorConfig, false, "", err } - for i, match := range matches { - matches[i] = filepath.Join(foundVendorConfigFile, match) + for _, match := range matches { + configFiles = append(configFiles, filepath.Join(foundVendorConfigFile, match)) } - configFiles = matches sort.Strings(configFiles) } else { configFiles = []string{foundVendorConfigFile} @@ -181,37 +184,21 @@ func ReadAndProcessVendorConfigFile( var mergedSources []schema.AtmosVendorSource var mergedImports []string - seenSources := make(map[string]bool) - seenImports := make(map[string]bool) - for _, configFile := range configFiles { - vendorConfigFileContent, err := os.ReadFile(configFile) - if err != nil { - return vendorConfig, false, "", fmt.Errorf("error reading vendor config file '%s': %w", configFile, err) - } - var currentConfig schema.AtmosVendorConfig - if err := yaml.Unmarshal(vendorConfigFileContent, ¤tConfig); err != nil { - return vendorConfig, false, "", fmt.Errorf("error parsing YAML file '%s': %w", configFile, err) + yamlFile, err := os.ReadFile(configFile) + if err != nil { + return vendorConfig, false, "", err } - // Set file field and deduplicate sources - for i := range currentConfig.Spec.Sources { - source := ¤tConfig.Spec.Sources[i] - source.File = configFile - if !seenSources[source.Source] { - vendorConfig.Spec.Sources = append(vendorConfig.Spec.Sources, *source) - seenSources[source.Source] = true - } + err = yaml.Unmarshal(yamlFile, ¤tConfig) + if err != nil { + return vendorConfig, false, "", err } - // Deduplicate imports - for _, imp := range currentConfig.Spec.Imports { - if !seenImports[imp] { - vendorConfig.Spec.Imports = append(vendorConfig.Spec.Imports, imp) - seenImports[imp] = true - } - } + // Merge sources and imports from current config + mergedSources = append(mergedSources, currentConfig.Spec.Sources...) + mergedImports = append(mergedImports, currentConfig.Spec.Imports...) } // Create final merged config @@ -588,7 +575,7 @@ func processVendorImports( return nil, nil, err } - for i, _ := range vendorConfig.Spec.Sources { + for i := range vendorConfig.Spec.Sources { vendorConfig.Spec.Sources[i].File = imp } From 5204a627df42c9635c822b8c194ea59a8faabd24 Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Thu, 31 Oct 2024 13:25:02 +0000 Subject: [PATCH 22/25] put back deduplication logic --- internal/exec/vendor_utils.go | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/internal/exec/vendor_utils.go b/internal/exec/vendor_utils.go index ba1029b84..1caf2d038 100644 --- a/internal/exec/vendor_utils.go +++ b/internal/exec/vendor_utils.go @@ -183,6 +183,8 @@ func ReadAndProcessVendorConfigFile( // Process all config files var mergedSources []schema.AtmosVendorSource var mergedImports []string + sourceMap := make(map[string]bool) // Track unique sources by component name + importMap := make(map[string]bool) // Track unique imports for _, configFile := range configFiles { var currentConfig schema.AtmosVendorConfig @@ -196,9 +198,26 @@ func ReadAndProcessVendorConfigFile( return vendorConfig, false, "", err } - // Merge sources and imports from current config - mergedSources = append(mergedSources, currentConfig.Spec.Sources...) - mergedImports = append(mergedImports, currentConfig.Spec.Imports...) + // Merge sources, checking for duplicates + for _, source := range currentConfig.Spec.Sources { + if source.Component != "" { + if sourceMap[source.Component] { + return vendorConfig, false, "", fmt.Errorf("duplicate component '%s' found in config file '%s'", + source.Component, configFile) + } + sourceMap[source.Component] = true + } + mergedSources = append(mergedSources, source) + } + + // Merge imports, checking for duplicates + for _, imp := range currentConfig.Spec.Imports { + if importMap[imp] { + continue // Skip duplicate imports + } + importMap[imp] = true + mergedImports = append(mergedImports, imp) + } } // Create final merged config From 1e96e032b3832cfca2e37d238c2c2d354ef1e330 Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Thu, 31 Oct 2024 14:25:05 +0000 Subject: [PATCH 23/25] handle no files case --- internal/exec/vendor_utils.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/exec/vendor_utils.go b/internal/exec/vendor_utils.go index 1caf2d038..b2073c5b6 100644 --- a/internal/exec/vendor_utils.go +++ b/internal/exec/vendor_utils.go @@ -176,6 +176,9 @@ func ReadAndProcessVendorConfigFile( configFiles = append(configFiles, filepath.Join(foundVendorConfigFile, match)) } sort.Strings(configFiles) + if len(configFiles) == 0 { + return vendorConfig, false, "", fmt.Errorf("no YAML configuration files found in directory '%s'", foundVendorConfigFile) + } } else { configFiles = []string{foundVendorConfigFile} } From 5cb80f0febcf8cbd3544472159634521b8582025 Mon Sep 17 00:00:00 2001 From: "Erik Osterman (CEO @ Cloud Posse)" Date: Thu, 31 Oct 2024 10:55:33 -0500 Subject: [PATCH 24/25] Update atmos.yaml --- atmos.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atmos.yaml b/atmos.yaml index 77fb489a5..285651fc9 100644 --- a/atmos.yaml +++ b/atmos.yaml @@ -23,7 +23,7 @@ vendor: # If a directory is specified, all .yaml files in the directory will be processed in lexicographical order # Can also be set using 'ATMOS_VENDOR_BASE_PATH' ENV var, or '--vendor-base-path' command-line argument # Examples: - # base_path: "./vendor.yaml" # Single file + # base_path: "./vendor.yaml" # Single file # base_path: "./vendor.d/" # Directory containing multiple .yaml files base_path: "./vendor.yaml" From 1f8098356393bec1879974a33a465d14de9e6ec3 Mon Sep 17 00:00:00 2001 From: Cerebrovinny Date: Wed, 13 Nov 2024 16:45:31 +0000 Subject: [PATCH 25/25] update pkg yaml --- internal/exec/vendor_utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/exec/vendor_utils.go b/internal/exec/vendor_utils.go index b2073c5b6..d2d5cd7a6 100644 --- a/internal/exec/vendor_utils.go +++ b/internal/exec/vendor_utils.go @@ -15,7 +15,7 @@ import ( cp "github.com/otiai10/copy" "github.com/samber/lo" "github.com/spf13/cobra" - "gopkg.in/yaml.v2" + "gopkg.in/yaml.v3" "github.com/bmatcuk/doublestar/v4" cfg "github.com/cloudposse/atmos/pkg/config"