cli: change generate-config flag to update-config flag (#1897)

This commit is contained in:
miampf 2023-06-28 12:47:44 +00:00 committed by GitHub
parent 9bb91ca447
commit 77b28cb5e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 285 additions and 380 deletions

View File

@ -42,10 +42,11 @@ runs:
shell: bash shell: bash
if: inputs.cloudProvider == 'aws' if: inputs.cloudProvider == 'aws'
run: | run: |
constellation config generate aws
constellation iam create aws \ constellation iam create aws \
--zone=${{ inputs.awsZone }} \ --zone=${{ inputs.awsZone }} \
--prefix=${{ inputs.namePrefix }} \ --prefix=${{ inputs.namePrefix }} \
--generate-config --yes --update-config --yes
- name: Constellation iam create azure - name: Constellation iam create azure
shell: bash shell: bash
@ -55,21 +56,23 @@ runs:
if [[ $output == *"tf-log"* ]]; then if [[ $output == *"tf-log"* ]]; then
TFFLAG="--tf-log=DEBUG" TFFLAG="--tf-log=DEBUG"
fi fi
constellation config generate azure
constellation iam create azure \ constellation iam create azure \
--region=${{ inputs.azureRegion }} \ --region=${{ inputs.azureRegion }} \
--resourceGroup="${{ inputs.namePrefix }}-rg" \ --resourceGroup="${{ inputs.namePrefix }}-rg" \
--servicePrincipal="${{ inputs.namePrefix }}-sp" \ --servicePrincipal="${{ inputs.namePrefix }}-sp" \
--generate-config --yes ${TFFLAG:-} --update-config --yes ${TFFLAG:-}
- name: Constellation iam create gcp - name: Constellation iam create gcp
shell: bash shell: bash
if: inputs.cloudProvider == 'gcp' if: inputs.cloudProvider == 'gcp'
run: | run: |
constellation config generate gcp
constellation iam create gcp \ constellation iam create gcp \
--projectID=${{ inputs.gcpProjectID }} \ --projectID=${{ inputs.gcpProjectID }} \
--zone=${{ inputs.gcpZone }} \ --zone=${{ inputs.gcpZone }} \
--serviceAccountID="${{ inputs.namePrefix }}-sa" \ --serviceAccountID="${{ inputs.namePrefix }}-sa" \
--generate-config --yes --update-config --yes
- name: Set existing config - name: Set existing config
id: setExistingConfig id: setExistingConfig

View File

@ -57,7 +57,8 @@ jobs:
- name: Create IAM configuration - name: Create IAM configuration
shell: pwsh shell: pwsh
run: | run: |
.\constellation.exe iam create azure --region=westus --resourceGroup=e2eWindoewsRG --servicePrincipal=e2eWindoewsSP --generate-config --debug -y .\constellation.exe config generate azure
.\constellation.exe iam create azure --region=westus --resourceGroup=e2eWindoewsRG --servicePrincipal=e2eWindoewsSP --update-config --debug -y
- name: Login to Azure (Cluster service principal) - name: Login to Azure (Cluster service principal)
uses: ./.github/actions/login_azure uses: ./.github/actions/login_azure

View File

@ -22,7 +22,6 @@ import (
"github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/file"
"github.com/spf13/afero" "github.com/spf13/afero"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"golang.org/x/mod/semver"
) )
var ( var (
@ -59,8 +58,7 @@ func newIAMCreateCmd() *cobra.Command {
} }
cmd.PersistentFlags().BoolP("yes", "y", false, "create the IAM configuration without further confirmation") cmd.PersistentFlags().BoolP("yes", "y", false, "create the IAM configuration without further confirmation")
cmd.PersistentFlags().Bool("generate-config", false, "automatically generate a configuration file and fill in the required fields") cmd.PersistentFlags().Bool("update-config", false, "automatically update the config file with the specific IAM information")
cmd.PersistentFlags().StringP("kubernetes", "k", semver.MajorMinor(config.Default().KubernetesVersion), "Kubernetes version to use in format MAJOR.MINOR - only usable in combination with --generate-config")
cmd.AddCommand(newIAMCreateAWSCmd()) cmd.AddCommand(newIAMCreateAWSCmd())
cmd.AddCommand(newIAMCreateAzureCmd()) cmd.AddCommand(newIAMCreateAzureCmd())
@ -215,16 +213,13 @@ func (c *iamCreator) create(ctx context.Context) error {
} }
c.log.Debugf("Using flags: %+v", flags) c.log.Debugf("Using flags: %+v", flags)
if err := c.checkWorkingDir(flags); err != nil { if err := c.checkWorkingDir(); err != nil {
return err return err
} }
if !flags.yesFlag { if !flags.yesFlag {
c.cmd.Printf("The following IAM configuration will be created:\n\n") c.cmd.Printf("The following IAM configuration will be created:\n\n")
c.providerCreator.printConfirmValues(c.cmd, flags) c.providerCreator.printConfirmValues(c.cmd, flags)
if flags.generateConfig {
c.cmd.Printf("The configuration file %s will be automatically generated and populated with the IAM values.\n", flags.configPath)
}
ok, err := askToConfirm(c.cmd, "Do you want to create the configuration?") ok, err := askToConfirm(c.cmd, "Do you want to create the configuration?")
if err != nil { if err != nil {
return err return err
@ -235,10 +230,16 @@ func (c *iamCreator) create(ctx context.Context) error {
} }
} }
var conf config.Config
if flags.updateConfig {
c.cmd.Printf("The configuration file %q will be automatically updated and populated with the IAM values.\n", flags.configPath)
c.log.Debugf("Parsing config %s", flags.configPath)
if err = c.fileHandler.ReadYAML(flags.configPath, &conf); err != nil {
return fmt.Errorf("error reading the configuration file: %w", err)
}
}
c.spinner.Start("Creating", false) c.spinner.Start("Creating", false)
conf := createConfig(c.provider)
iamFile, err := c.creator.Create(ctx, c.provider, c.iamConfig) iamFile, err := c.creator.Create(ctx, c.provider, c.iamConfig)
c.spinner.Stop() c.spinner.Stop()
if err != nil { if err != nil {
@ -252,14 +253,10 @@ func (c *iamCreator) create(ctx context.Context) error {
return err return err
} }
if flags.generateConfig { if flags.updateConfig {
c.log.Debugf("Writing IAM configuration to %s", flags.configPath) c.log.Debugf("Writing IAM configuration to %s", flags.configPath)
c.providerCreator.writeOutputValuesToConfig(conf, flags, iamFile) c.providerCreator.writeOutputValuesToConfig(&conf, flags, iamFile)
// Only overwrite when --generate-config && --kubernetes. Otherwise this string is empty from parseFlagsAndSetupConfig. if err := c.fileHandler.WriteYAML(flags.configPath, conf, file.OptOverwrite); err != nil {
if flags.k8sVersion != "" {
conf.KubernetesVersion = flags.k8sVersion
}
if err := c.fileHandler.WriteYAML(flags.configPath, conf, file.OptMkdirAll); err != nil {
return err return err
} }
c.cmd.Printf("Your IAM configuration was created and filled into %s successfully.\n", flags.configPath) c.cmd.Printf("Your IAM configuration was created and filled into %s successfully.\n", flags.configPath)
@ -282,35 +279,15 @@ func (c *iamCreator) parseFlagsAndSetupConfig() (iamFlags, error) {
if err != nil { if err != nil {
return iamFlags{}, fmt.Errorf("parsing yes bool: %w", err) return iamFlags{}, fmt.Errorf("parsing yes bool: %w", err)
} }
generateConfig, err := c.cmd.Flags().GetBool("generate-config") updateConfig, err := c.cmd.Flags().GetBool("update-config")
if err != nil { if err != nil {
return iamFlags{}, fmt.Errorf("parsing generate-config bool: %w", err) return iamFlags{}, fmt.Errorf("parsing update-config bool: %w", err)
}
k8sVersion, err := c.cmd.Flags().GetString("kubernetes")
if err != nil {
return iamFlags{}, fmt.Errorf("parsing kubernetes string: %w", err)
}
// This is implemented slightly differently compared to "config generate", since this flag is only respected in combination with --generate-config.
// Even if an invalid version is set, in case --generate-config is false, we don't overwrite the default value of the config.
// So we only need to validate the input to the flag when --generate-config is set.
// Otherwise, we return an empty string. Later, we only overwrite the value in the config when we haven't passed an empty string.
// Instead, we should have our validated K8s version parameter then.
var resolvedVersion string
if generateConfig {
resolvedVersion, err = resolveK8sVersion(k8sVersion)
if err != nil {
return iamFlags{}, fmt.Errorf("resolving kubernetes version: %w", err)
}
} else if c.cmd.Flag("kubernetes").Changed {
c.cmd.Println("Warning: --generate-config is not set, ignoring --kubernetes flag.")
} }
flags := iamFlags{ flags := iamFlags{
configPath: configPath, configPath: configPath,
yesFlag: yesFlag, yesFlag: yesFlag,
generateConfig: generateConfig, updateConfig: updateConfig,
k8sVersion: resolvedVersion,
} }
flags, err = c.providerCreator.parseFlagsAndSetupConfig(c.cmd, flags, c.iamConfig) flags, err = c.providerCreator.parseFlagsAndSetupConfig(c.cmd, flags, c.iamConfig)
@ -321,28 +298,22 @@ func (c *iamCreator) parseFlagsAndSetupConfig() (iamFlags, error) {
return flags, nil return flags, nil
} }
// checkWorkingDir checks if the current working directory already contains a Terraform dir or a Constellation config file. // checkWorkingDir checks if the current working directory already contains a Terraform dir.
func (c *iamCreator) checkWorkingDir(flags iamFlags) error { func (c *iamCreator) checkWorkingDir() error {
if _, err := c.fileHandler.Stat(constants.TerraformIAMWorkingDir); err == nil { if _, err := c.fileHandler.Stat(constants.TerraformIAMWorkingDir); err == nil {
return fmt.Errorf("the current working directory already contains the Terraform workspace directory %q. Please run the command in a different directory or destroy the existing workspace", constants.TerraformIAMWorkingDir) return fmt.Errorf("the current working directory already contains the Terraform workspace directory %q. Please run the command in a different directory or destroy the existing workspace", constants.TerraformIAMWorkingDir)
} }
if flags.generateConfig {
if _, err := c.fileHandler.Stat(flags.configPath); err == nil {
return fmt.Errorf("the flag --generate-config is set, but %q already exists. Please either run the command in a different directory, define another config path, or delete or move the existing configuration", flags.configPath)
}
}
return nil return nil
} }
// iamFlags contains the parsed flags of the iam create command, including the parsed flags of the selected cloud provider. // iamFlags contains the parsed flags of the iam create command, including the parsed flags of the selected cloud provider.
type iamFlags struct { type iamFlags struct {
aws awsFlags aws awsFlags
azure azureFlags azure azureFlags
gcp gcpFlags gcp gcpFlags
configPath string configPath string
yesFlag bool yesFlag bool
generateConfig bool updateConfig bool
k8sVersion string
} }
// awsFlags contains the parsed flags of the iam create aws command. // awsFlags contains the parsed flags of the iam create aws command.

View File

@ -18,11 +18,9 @@ import (
"github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/file"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/versions"
"github.com/spf13/afero" "github.com/spf13/afero"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"golang.org/x/mod/semver"
) )
func TestParseIDFile(t *testing.T) { func TestParseIDFile(t *testing.T) {
@ -69,18 +67,18 @@ func TestParseIDFile(t *testing.T) {
} }
func TestIAMCreateAWS(t *testing.T) { func TestIAMCreateAWS(t *testing.T) {
defaultFs := func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string, existingDirs []string) afero.Fs { defaultFs := func(require *require.Assertions, provider cloudprovider.Provider, existingConfigFiles []string, existingDirs []string) afero.Fs {
fs := afero.NewMemMapFs() fs := afero.NewMemMapFs()
fileHandler := file.NewHandler(fs) fileHandler := file.NewHandler(fs)
for _, f := range existingFiles { for _, f := range existingConfigFiles {
require.NoError(fileHandler.Write(f, []byte{1, 2, 3}, file.OptNone)) require.NoError(fileHandler.WriteYAML(f, createConfig(cloudprovider.AWS), file.OptNone))
} }
for _, d := range existingDirs { for _, d := range existingDirs {
require.NoError(fs.MkdirAll(d, 0o755)) require.NoError(fs.MkdirAll(d, 0o755))
} }
return fs return fs
} }
readOnlyFs := func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string, existingDirs []string) afero.Fs { readOnlyFs := func(require *require.Assertions, provider cloudprovider.Provider, existingConfigFiles []string, existingDirs []string) afero.Fs {
fs := afero.NewReadOnlyFs(afero.NewMemMapFs()) fs := afero.NewReadOnlyFs(afero.NewMemMapFs())
return fs return fs
} }
@ -93,22 +91,41 @@ func TestIAMCreateAWS(t *testing.T) {
} }
testCases := map[string]struct { testCases := map[string]struct {
setupFs func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string, existingDirs []string) afero.Fs setupFs func(require *require.Assertions, provider cloudprovider.Provider, existingConfigFiles []string, existingDirs []string) afero.Fs
creator *stubIAMCreator creator *stubIAMCreator
provider cloudprovider.Provider provider cloudprovider.Provider
zoneFlag string zoneFlag string
prefixFlag string prefixFlag string
yesFlag bool yesFlag bool
generateConfigFlag bool updateConfigFlag bool
k8sVersionFlag string configFlag string
configFlag string existingConfigFiles []string
existingFiles []string existingDirs []string
existingDirs []string stdin string
stdin string wantAbort bool
wantAbort bool wantErr bool
wantErr bool
}{ }{
"iam create aws": { "iam create aws": {
setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.AWS,
zoneFlag: "us-east-2a",
prefixFlag: "test",
yesFlag: true,
existingConfigFiles: []string{constants.ConfigFilename},
},
"iam create aws --update-config": {
setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.AWS,
zoneFlag: "us-east-2a",
prefixFlag: "test",
yesFlag: true,
configFlag: constants.ConfigFilename,
updateConfigFlag: true,
existingConfigFiles: []string{constants.ConfigFilename},
},
"iam create aws no config": {
setupFs: defaultFs, setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile}, creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.AWS, provider: cloudprovider.AWS,
@ -116,49 +133,27 @@ func TestIAMCreateAWS(t *testing.T) {
prefixFlag: "test", prefixFlag: "test",
yesFlag: true, yesFlag: true,
}, },
"iam create aws generate config": { "iam create aws --update-config with --config": {
setupFs: defaultFs, setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile}, creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.AWS, provider: cloudprovider.AWS,
zoneFlag: "us-east-2a", zoneFlag: "us-east-2a",
prefixFlag: "test", prefixFlag: "test",
yesFlag: true, yesFlag: true,
configFlag: constants.ConfigFilename, updateConfigFlag: true,
generateConfigFlag: true, configFlag: "custom-config.yaml",
existingConfigFiles: []string{"custom-config.yaml"},
}, },
"iam create aws generate config custom path": { "iam create aws --update-config --config path doesn't exist": {
setupFs: defaultFs, setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile}, creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.AWS, provider: cloudprovider.AWS,
zoneFlag: "us-east-2a", zoneFlag: "us-east-2a",
prefixFlag: "test", prefixFlag: "test",
yesFlag: true, yesFlag: true,
generateConfigFlag: true, updateConfigFlag: true,
configFlag: "custom-config.yaml", wantErr: true,
}, configFlag: constants.ConfigFilename,
"iam create aws generate config path already exists": {
setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.AWS,
zoneFlag: "us-east-2a",
prefixFlag: "test",
yesFlag: true,
generateConfigFlag: true,
wantErr: true,
configFlag: constants.ConfigFilename,
existingFiles: []string{constants.ConfigFilename},
},
"iam create aws generate config custom path already exists": {
setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.AWS,
zoneFlag: "us-east-2a",
prefixFlag: "test",
yesFlag: true,
generateConfigFlag: true,
wantErr: true,
configFlag: "custom-config.yaml",
existingFiles: []string{"custom-config.yaml"},
}, },
"iam create aws existing terraform dir": { "iam create aws existing terraform dir": {
setupFs: defaultFs, setupFs: defaultFs,
@ -178,15 +173,16 @@ func TestIAMCreateAWS(t *testing.T) {
prefixFlag: "test", prefixFlag: "test",
stdin: "yes\n", stdin: "yes\n",
}, },
"interactive generate config": { "interactive update config": {
setupFs: defaultFs, setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile}, creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.AWS, provider: cloudprovider.AWS,
zoneFlag: "us-east-2a", zoneFlag: "us-east-2a",
prefixFlag: "test", prefixFlag: "test",
stdin: "yes\n", stdin: "yes\n",
configFlag: constants.ConfigFilename, configFlag: constants.ConfigFilename,
generateConfigFlag: true, updateConfigFlag: true,
existingConfigFiles: []string{constants.ConfigFilename},
}, },
"interactive abort": { "interactive abort": {
setupFs: defaultFs, setupFs: defaultFs,
@ -197,16 +193,17 @@ func TestIAMCreateAWS(t *testing.T) {
stdin: "no\n", stdin: "no\n",
wantAbort: true, wantAbort: true,
}, },
"interactive generate config abort": { "interactive update config abort": {
setupFs: defaultFs, setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile}, creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.AWS, provider: cloudprovider.AWS,
zoneFlag: "us-east-2a", zoneFlag: "us-east-2a",
prefixFlag: "test", prefixFlag: "test",
stdin: "no\n", stdin: "no\n",
generateConfigFlag: true, updateConfigFlag: true,
configFlag: constants.ConfigFilename, configFlag: constants.ConfigFilename,
wantAbort: true, wantAbort: true,
existingConfigFiles: []string{constants.ConfigFilename},
}, },
"invalid zone": { "invalid zone": {
setupFs: defaultFs, setupFs: defaultFs,
@ -218,47 +215,15 @@ func TestIAMCreateAWS(t *testing.T) {
wantErr: true, wantErr: true,
}, },
"unwritable fs": { "unwritable fs": {
setupFs: readOnlyFs, setupFs: readOnlyFs,
creator: &stubIAMCreator{id: validIAMIDFile}, creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.AWS, provider: cloudprovider.AWS,
zoneFlag: "us-east-2a", zoneFlag: "us-east-2a",
prefixFlag: "test", prefixFlag: "test",
yesFlag: true, yesFlag: true,
generateConfigFlag: true, updateConfigFlag: true,
wantErr: true, wantErr: true,
configFlag: constants.ConfigFilename, configFlag: constants.ConfigFilename,
},
"iam create azure without generate config and invalid kubernetes version": {
setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.AWS,
zoneFlag: "us-east-2a",
prefixFlag: "test",
k8sVersionFlag: "1.11.1", // supposed to be ignored without generateConfigFlag
yesFlag: true,
},
"iam create azure generate config with valid kubernetes version": {
setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.AWS,
zoneFlag: "us-east-2a",
prefixFlag: "test",
generateConfigFlag: true,
k8sVersionFlag: semver.MajorMinor(string(versions.Default)),
configFlag: constants.ConfigFilename,
yesFlag: true,
},
"iam create azure generate config with invalid kubernetes version": {
setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.AWS,
zoneFlag: "us-east-2a",
prefixFlag: "test",
generateConfigFlag: true,
k8sVersionFlag: "1.22.1",
configFlag: constants.ConfigFilename,
yesFlag: true,
wantErr: true,
}, },
} }
@ -274,8 +239,7 @@ func TestIAMCreateAWS(t *testing.T) {
// register persistent flags manually // register persistent flags manually
cmd.Flags().String("config", constants.ConfigFilename, "") cmd.Flags().String("config", constants.ConfigFilename, "")
cmd.Flags().Bool("generate-config", false, "") cmd.Flags().Bool("update-config", false, "")
cmd.Flags().String("kubernetes", semver.MajorMinor(config.Default().KubernetesVersion), "")
cmd.Flags().Bool("yes", false, "") cmd.Flags().Bool("yes", false, "")
cmd.Flags().String("name", "constell", "") cmd.Flags().String("name", "constell", "")
cmd.Flags().String("tf-log", "NONE", "") cmd.Flags().String("tf-log", "NONE", "")
@ -289,17 +253,14 @@ func TestIAMCreateAWS(t *testing.T) {
if tc.yesFlag { if tc.yesFlag {
require.NoError(cmd.Flags().Set("yes", "true")) require.NoError(cmd.Flags().Set("yes", "true"))
} }
if tc.generateConfigFlag { if tc.updateConfigFlag {
require.NoError(cmd.Flags().Set("generate-config", "true")) require.NoError(cmd.Flags().Set("update-config", "true"))
} }
if tc.configFlag != "" { if tc.configFlag != "" {
require.NoError(cmd.Flags().Set("config", tc.configFlag)) require.NoError(cmd.Flags().Set("config", tc.configFlag))
} }
if tc.k8sVersionFlag != "" {
require.NoError(cmd.Flags().Set("kubernetes", tc.k8sVersionFlag))
}
fileHandler := file.NewHandler(tc.setupFs(require, tc.provider, tc.existingFiles, tc.existingDirs)) fileHandler := file.NewHandler(tc.setupFs(require, tc.provider, tc.existingConfigFiles, tc.existingDirs))
iamCreator := &iamCreator{ iamCreator := &iamCreator{
cmd: cmd, cmd: cmd,
@ -323,7 +284,7 @@ func TestIAMCreateAWS(t *testing.T) {
return return
} }
if tc.generateConfigFlag { if tc.updateConfigFlag {
readConfig := &config.Config{} readConfig := &config.Config{}
readErr := fileHandler.ReadYAML(tc.configFlag, readConfig) readErr := fileHandler.ReadYAML(tc.configFlag, readConfig)
require.NoError(readErr) require.NoError(readErr)
@ -340,18 +301,18 @@ func TestIAMCreateAWS(t *testing.T) {
} }
func TestIAMCreateAzure(t *testing.T) { func TestIAMCreateAzure(t *testing.T) {
defaultFs := func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string, existingDirs []string) afero.Fs { defaultFs := func(require *require.Assertions, provider cloudprovider.Provider, existingConfigFiles []string, existingDirs []string) afero.Fs {
fs := afero.NewMemMapFs() fs := afero.NewMemMapFs()
fileHandler := file.NewHandler(fs) fileHandler := file.NewHandler(fs)
for _, f := range existingFiles { for _, f := range existingConfigFiles {
require.NoError(fileHandler.Write(f, []byte{1, 2, 3}, file.OptNone)) require.NoError(fileHandler.WriteYAML(f, createConfig(cloudprovider.Azure), file.OptNone))
} }
for _, d := range existingDirs { for _, d := range existingDirs {
require.NoError(fs.MkdirAll(d, 0o755)) require.NoError(fs.MkdirAll(d, 0o755))
} }
return fs return fs
} }
readOnlyFs := func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string, existingDirs []string) afero.Fs { readOnlyFs := func(require *require.Assertions, provider cloudprovider.Provider, existingConfigFiles []string, existingDirs []string) afero.Fs {
fs := afero.NewReadOnlyFs(afero.NewMemMapFs()) fs := afero.NewReadOnlyFs(afero.NewMemMapFs())
return fs return fs
} }
@ -365,17 +326,16 @@ func TestIAMCreateAzure(t *testing.T) {
} }
testCases := map[string]struct { testCases := map[string]struct {
setupFs func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string, existingDirs []string) afero.Fs setupFs func(require *require.Assertions, provider cloudprovider.Provider, existingConfigFiles []string, existingDirs []string) afero.Fs
creator *stubIAMCreator creator *stubIAMCreator
provider cloudprovider.Provider provider cloudprovider.Provider
regionFlag string regionFlag string
servicePrincipalFlag string servicePrincipalFlag string
resourceGroupFlag string resourceGroupFlag string
yesFlag bool yesFlag bool
generateConfigFlag bool updateConfigFlag bool
k8sVersionFlag string
configFlag string configFlag string
existingFiles []string existingConfigFiles []string
existingDirs []string existingDirs []string
stdin string stdin string
wantAbort bool wantAbort bool
@ -390,51 +350,61 @@ func TestIAMCreateAzure(t *testing.T) {
resourceGroupFlag: "constell-test-rg", resourceGroupFlag: "constell-test-rg",
yesFlag: true, yesFlag: true,
}, },
"iam create azure generate config": { "iam create azure with existing config": {
setupFs: defaultFs, setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile}, creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.Azure, provider: cloudprovider.Azure,
regionFlag: "westus", regionFlag: "westus",
servicePrincipalFlag: "constell-test-sp", servicePrincipalFlag: "constell-test-sp",
resourceGroupFlag: "constell-test-rg", resourceGroupFlag: "constell-test-rg",
generateConfigFlag: true, yesFlag: true,
existingConfigFiles: []string{constants.ConfigFilename},
},
"iam create azure --update-config": {
setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.Azure,
regionFlag: "westus",
servicePrincipalFlag: "constell-test-sp",
resourceGroupFlag: "constell-test-rg",
updateConfigFlag: true,
configFlag: constants.ConfigFilename, configFlag: constants.ConfigFilename,
yesFlag: true, yesFlag: true,
existingConfigFiles: []string{constants.ConfigFilename},
}, },
"iam create azure generate config custom path": { "iam create azure --update-config with --config": {
setupFs: defaultFs, setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile}, creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.Azure, provider: cloudprovider.Azure,
regionFlag: "westus", regionFlag: "westus",
servicePrincipalFlag: "constell-test-sp", servicePrincipalFlag: "constell-test-sp",
resourceGroupFlag: "constell-test-rg", resourceGroupFlag: "constell-test-rg",
generateConfigFlag: true, updateConfigFlag: true,
configFlag: "custom-config.yaml", configFlag: "custom-config.yaml",
yesFlag: true, yesFlag: true,
existingConfigFiles: []string{"custom-config.yaml"},
}, },
"iam create azure generate config custom path already exists": { "iam create azure --update-config custom --config path doesn't exist": {
setupFs: defaultFs, setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile}, creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.Azure, provider: cloudprovider.Azure,
regionFlag: "westus", regionFlag: "westus",
servicePrincipalFlag: "constell-test-sp", servicePrincipalFlag: "constell-test-sp",
resourceGroupFlag: "constell-test-rg", resourceGroupFlag: "constell-test-rg",
generateConfigFlag: true, updateConfigFlag: true,
yesFlag: true, yesFlag: true,
wantErr: true, wantErr: true,
configFlag: "custom-config.yaml", configFlag: "custom-config.yaml",
existingFiles: []string{"custom-config.yaml"},
}, },
"iam create generate config path already exists": { "iam create azur --update-config --config path doesn't exists": {
setupFs: defaultFs, setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile}, creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.Azure, provider: cloudprovider.Azure,
regionFlag: "westus", regionFlag: "westus",
servicePrincipalFlag: "constell-test-sp", servicePrincipalFlag: "constell-test-sp",
resourceGroupFlag: "constell-test-rg", resourceGroupFlag: "constell-test-rg",
generateConfigFlag: true, updateConfigFlag: true,
configFlag: constants.ConfigFilename, configFlag: constants.ConfigFilename,
existingFiles: []string{constants.ConfigFilename},
yesFlag: true, yesFlag: true,
wantErr: true, wantErr: true,
}, },
@ -458,7 +428,7 @@ func TestIAMCreateAzure(t *testing.T) {
resourceGroupFlag: "constell-test-rg", resourceGroupFlag: "constell-test-rg",
stdin: "yes\n", stdin: "yes\n",
}, },
"interactive generate config": { "interactive update config": {
setupFs: defaultFs, setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile}, creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.Azure, provider: cloudprovider.Azure,
@ -466,8 +436,9 @@ func TestIAMCreateAzure(t *testing.T) {
servicePrincipalFlag: "constell-test-sp", servicePrincipalFlag: "constell-test-sp",
resourceGroupFlag: "constell-test-rg", resourceGroupFlag: "constell-test-rg",
stdin: "yes\n", stdin: "yes\n",
generateConfigFlag: true, updateConfigFlag: true,
configFlag: constants.ConfigFilename, configFlag: constants.ConfigFilename,
existingConfigFiles: []string{constants.ConfigFilename},
}, },
"interactive abort": { "interactive abort": {
setupFs: defaultFs, setupFs: defaultFs,
@ -479,7 +450,7 @@ func TestIAMCreateAzure(t *testing.T) {
stdin: "no\n", stdin: "no\n",
wantAbort: true, wantAbort: true,
}, },
"interactive generate config abort": { "interactive update config abort": {
setupFs: defaultFs, setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile}, creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.Azure, provider: cloudprovider.Azure,
@ -487,8 +458,9 @@ func TestIAMCreateAzure(t *testing.T) {
servicePrincipalFlag: "constell-test-sp", servicePrincipalFlag: "constell-test-sp",
resourceGroupFlag: "constell-test-rg", resourceGroupFlag: "constell-test-rg",
stdin: "no\n", stdin: "no\n",
generateConfigFlag: true, updateConfigFlag: true,
wantAbort: true, wantAbort: true,
existingConfigFiles: []string{constants.ConfigFilename},
}, },
"unwritable fs": { "unwritable fs": {
setupFs: readOnlyFs, setupFs: readOnlyFs,
@ -498,45 +470,10 @@ func TestIAMCreateAzure(t *testing.T) {
servicePrincipalFlag: "constell-test-sp", servicePrincipalFlag: "constell-test-sp",
resourceGroupFlag: "constell-test-rg", resourceGroupFlag: "constell-test-rg",
yesFlag: true, yesFlag: true,
generateConfigFlag: true, updateConfigFlag: true,
configFlag: constants.ConfigFilename, configFlag: constants.ConfigFilename,
wantErr: true, wantErr: true,
}, },
"iam create azure without generate config and invalid kubernetes version": {
setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.Azure,
regionFlag: "westus",
servicePrincipalFlag: "constell-test-sp",
resourceGroupFlag: "constell-test-rg",
k8sVersionFlag: "1.11.1", // supposed to be ignored without generateConfigFlag
yesFlag: true,
},
"iam create azure generate config with valid kubernetes version": {
setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.Azure,
regionFlag: "westus",
servicePrincipalFlag: "constell-test-sp",
resourceGroupFlag: "constell-test-rg",
generateConfigFlag: true,
k8sVersionFlag: semver.MajorMinor(string(versions.Default)),
configFlag: constants.ConfigFilename,
yesFlag: true,
},
"iam create azure generate config with invalid kubernetes version": {
setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.Azure,
regionFlag: "westus",
servicePrincipalFlag: "constell-test-sp",
resourceGroupFlag: "constell-test-rg",
generateConfigFlag: true,
k8sVersionFlag: "1.22.1",
configFlag: constants.ConfigFilename,
yesFlag: true,
wantErr: true,
},
} }
for name, tc := range testCases { for name, tc := range testCases {
@ -551,8 +488,7 @@ func TestIAMCreateAzure(t *testing.T) {
// register persistent flags manually // register persistent flags manually
cmd.Flags().String("config", constants.ConfigFilename, "") cmd.Flags().String("config", constants.ConfigFilename, "")
cmd.Flags().Bool("generate-config", false, "") cmd.Flags().Bool("update-config", false, "")
cmd.Flags().String("kubernetes", semver.MajorMinor(config.Default().KubernetesVersion), "")
cmd.Flags().Bool("yes", false, "") cmd.Flags().Bool("yes", false, "")
cmd.Flags().String("name", "constell", "") cmd.Flags().String("name", "constell", "")
cmd.Flags().String("tf-log", "NONE", "") cmd.Flags().String("tf-log", "NONE", "")
@ -569,17 +505,14 @@ func TestIAMCreateAzure(t *testing.T) {
if tc.yesFlag { if tc.yesFlag {
require.NoError(cmd.Flags().Set("yes", "true")) require.NoError(cmd.Flags().Set("yes", "true"))
} }
if tc.generateConfigFlag { if tc.updateConfigFlag {
require.NoError(cmd.Flags().Set("generate-config", "true")) require.NoError(cmd.Flags().Set("update-config", "true"))
} }
if tc.configFlag != "" { if tc.configFlag != "" {
require.NoError(cmd.Flags().Set("config", tc.configFlag)) require.NoError(cmd.Flags().Set("config", tc.configFlag))
} }
if tc.k8sVersionFlag != "" {
require.NoError(cmd.Flags().Set("kubernetes", tc.k8sVersionFlag))
}
fileHandler := file.NewHandler(tc.setupFs(require, tc.provider, tc.existingFiles, tc.existingDirs)) fileHandler := file.NewHandler(tc.setupFs(require, tc.provider, tc.existingConfigFiles, tc.existingDirs))
iamCreator := &iamCreator{ iamCreator := &iamCreator{
cmd: cmd, cmd: cmd,
@ -603,7 +536,7 @@ func TestIAMCreateAzure(t *testing.T) {
return return
} }
if tc.generateConfigFlag { if tc.updateConfigFlag {
readConfig := &config.Config{} readConfig := &config.Config{}
readErr := fileHandler.ReadYAML(tc.configFlag, readConfig) readErr := fileHandler.ReadYAML(tc.configFlag, readConfig)
require.NoError(readErr) require.NoError(readErr)
@ -621,18 +554,18 @@ func TestIAMCreateAzure(t *testing.T) {
} }
func TestIAMCreateGCP(t *testing.T) { func TestIAMCreateGCP(t *testing.T) {
defaultFs := func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string, existingDirs []string) afero.Fs { defaultFs := func(require *require.Assertions, provider cloudprovider.Provider, existingConfigFiles []string, existingDirs []string) afero.Fs {
fs := afero.NewMemMapFs() fs := afero.NewMemMapFs()
fileHandler := file.NewHandler(fs) fileHandler := file.NewHandler(fs)
for _, f := range existingFiles { for _, f := range existingConfigFiles {
require.NoError(fileHandler.Write(f, []byte{1, 2, 3}, file.OptNone)) require.NoError(fileHandler.WriteYAML(f, createConfig(cloudprovider.GCP), file.OptNone))
} }
for _, d := range existingDirs { for _, d := range existingDirs {
require.NoError(fs.MkdirAll(d, 0o755)) require.NoError(fs.MkdirAll(d, 0o755))
} }
return fs return fs
} }
readOnlyFs := func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string, existingDirs []string) afero.Fs { readOnlyFs := func(require *require.Assertions, provider cloudprovider.Provider, existingConfigFiles []string, existingDirs []string) afero.Fs {
fs := afero.NewReadOnlyFs(afero.NewMemMapFs()) fs := afero.NewReadOnlyFs(afero.NewMemMapFs())
return fs return fs
} }
@ -650,17 +583,16 @@ func TestIAMCreateGCP(t *testing.T) {
} }
testCases := map[string]struct { testCases := map[string]struct {
setupFs func(require *require.Assertions, provider cloudprovider.Provider, existingFiles []string, existingDirs []string) afero.Fs setupFs func(require *require.Assertions, provider cloudprovider.Provider, existingConfigFiles []string, existingDirs []string) afero.Fs
creator *stubIAMCreator creator *stubIAMCreator
provider cloudprovider.Provider provider cloudprovider.Provider
zoneFlag string zoneFlag string
serviceAccountIDFlag string serviceAccountIDFlag string
projectIDFlag string projectIDFlag string
yesFlag bool yesFlag bool
generateConfigFlag bool updateConfigFlag bool
k8sVersionFlag string
configFlag string configFlag string
existingFiles []string existingConfigFiles []string
existingDirs []string existingDirs []string
stdin string stdin string
wantAbort bool wantAbort bool
@ -675,51 +607,61 @@ func TestIAMCreateGCP(t *testing.T) {
projectIDFlag: "constell-1234", projectIDFlag: "constell-1234",
yesFlag: true, yesFlag: true,
}, },
"iam create gcp generate config": { "iam create gcp with existing config": {
setupFs: defaultFs, setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile}, creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.GCP, provider: cloudprovider.GCP,
zoneFlag: "europe-west1-a", zoneFlag: "europe-west1-a",
serviceAccountIDFlag: "constell-test", serviceAccountIDFlag: "constell-test",
projectIDFlag: "constell-1234", projectIDFlag: "constell-1234",
generateConfigFlag: true, yesFlag: true,
existingConfigFiles: []string{constants.ConfigFilename},
},
"iam create gcp --update-config": {
setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.GCP,
zoneFlag: "europe-west1-a",
serviceAccountIDFlag: "constell-test",
projectIDFlag: "constell-1234",
updateConfigFlag: true,
configFlag: constants.ConfigFilename, configFlag: constants.ConfigFilename,
yesFlag: true, yesFlag: true,
existingConfigFiles: []string{constants.ConfigFilename},
}, },
"iam create gcp generate config custom path": { "iam create gcp --update-config with --config": {
setupFs: defaultFs, setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile}, creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.GCP, provider: cloudprovider.GCP,
zoneFlag: "europe-west1-a", zoneFlag: "europe-west1-a",
serviceAccountIDFlag: "constell-test", serviceAccountIDFlag: "constell-test",
projectIDFlag: "constell-1234", projectIDFlag: "constell-1234",
generateConfigFlag: true, updateConfigFlag: true,
configFlag: "custom-config.yaml", configFlag: "custom-config.yaml",
yesFlag: true, yesFlag: true,
existingConfigFiles: []string{"custom-config.yaml"},
}, },
"iam create gcp generate config path already exists": { "iam create gcp --update-config --config path doesn't exists": {
setupFs: defaultFs, setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile}, creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.GCP, provider: cloudprovider.GCP,
zoneFlag: "europe-west1-a", zoneFlag: "europe-west1-a",
serviceAccountIDFlag: "constell-test", serviceAccountIDFlag: "constell-test",
projectIDFlag: "constell-1234", projectIDFlag: "constell-1234",
generateConfigFlag: true, updateConfigFlag: true,
configFlag: constants.ConfigFilename, configFlag: constants.ConfigFilename,
existingFiles: []string{constants.ConfigFilename},
yesFlag: true, yesFlag: true,
wantErr: true, wantErr: true,
}, },
"iam create gcp generate config custom path already exists": { "iam create gcp --update-config wrong --config path": {
setupFs: defaultFs, setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile}, creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.GCP, provider: cloudprovider.GCP,
zoneFlag: "europe-west1-a", zoneFlag: "europe-west1-a",
serviceAccountIDFlag: "constell-test", serviceAccountIDFlag: "constell-test",
projectIDFlag: "constell-1234", projectIDFlag: "constell-1234",
generateConfigFlag: true, updateConfigFlag: true,
configFlag: "custom-config.yaml", configFlag: "custom-config.yaml",
existingFiles: []string{"custom-config.yaml"},
yesFlag: true, yesFlag: true,
wantErr: true, wantErr: true,
}, },
@ -762,7 +704,7 @@ func TestIAMCreateGCP(t *testing.T) {
projectIDFlag: "constell-1234", projectIDFlag: "constell-1234",
stdin: "yes\n", stdin: "yes\n",
}, },
"interactive generate config": { "interactive update config": {
setupFs: defaultFs, setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile}, creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.GCP, provider: cloudprovider.GCP,
@ -771,7 +713,8 @@ func TestIAMCreateGCP(t *testing.T) {
projectIDFlag: "constell-1234", projectIDFlag: "constell-1234",
stdin: "yes\n", stdin: "yes\n",
configFlag: constants.ConfigFilename, configFlag: constants.ConfigFilename,
generateConfigFlag: true, updateConfigFlag: true,
existingConfigFiles: []string{constants.ConfigFilename},
}, },
"interactive abort": { "interactive abort": {
setupFs: defaultFs, setupFs: defaultFs,
@ -783,7 +726,7 @@ func TestIAMCreateGCP(t *testing.T) {
stdin: "no\n", stdin: "no\n",
wantAbort: true, wantAbort: true,
}, },
"interactive abort generate config": { "interactive abort update config": {
setupFs: defaultFs, setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile}, creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.GCP, provider: cloudprovider.GCP,
@ -793,7 +736,8 @@ func TestIAMCreateGCP(t *testing.T) {
stdin: "no\n", stdin: "no\n",
wantAbort: true, wantAbort: true,
configFlag: constants.ConfigFilename, configFlag: constants.ConfigFilename,
generateConfigFlag: true, updateConfigFlag: true,
existingConfigFiles: []string{constants.ConfigFilename},
}, },
"unwritable fs": { "unwritable fs": {
setupFs: readOnlyFs, setupFs: readOnlyFs,
@ -803,45 +747,10 @@ func TestIAMCreateGCP(t *testing.T) {
serviceAccountIDFlag: "constell-test", serviceAccountIDFlag: "constell-test",
projectIDFlag: "constell-1234", projectIDFlag: "constell-1234",
yesFlag: true, yesFlag: true,
generateConfigFlag: true, updateConfigFlag: true,
configFlag: constants.ConfigFilename, configFlag: constants.ConfigFilename,
wantErr: true, wantErr: true,
}, },
"iam create gcp without generate config and invalid kubernetes version": {
setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.GCP,
zoneFlag: "europe-west1-a",
serviceAccountIDFlag: "constell-test",
projectIDFlag: "constell-1234",
k8sVersionFlag: "1.11.1", // supposed to be ignored without generateConfigFlag
yesFlag: true,
},
"iam create gcp generate config with valid kubernetes version": {
setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.GCP,
zoneFlag: "europe-west1-a",
serviceAccountIDFlag: "constell-test",
projectIDFlag: "constell-1234",
generateConfigFlag: true,
k8sVersionFlag: semver.MajorMinor(string(versions.Default)),
configFlag: constants.ConfigFilename,
yesFlag: true,
},
"iam create gcp generate config with invalid kubernetes version": {
setupFs: defaultFs,
creator: &stubIAMCreator{id: validIAMIDFile},
provider: cloudprovider.GCP,
zoneFlag: "europe-west1-a",
serviceAccountIDFlag: "constell-test",
projectIDFlag: "constell-1234",
generateConfigFlag: true,
k8sVersionFlag: "1.22.1",
configFlag: constants.ConfigFilename,
yesFlag: true,
wantErr: true,
},
} }
for name, tc := range testCases { for name, tc := range testCases {
@ -856,8 +765,7 @@ func TestIAMCreateGCP(t *testing.T) {
// register persistent flags manually // register persistent flags manually
cmd.Flags().String("config", constants.ConfigFilename, "") cmd.Flags().String("config", constants.ConfigFilename, "")
cmd.Flags().Bool("generate-config", false, "") cmd.Flags().Bool("update-config", false, "")
cmd.Flags().String("kubernetes", semver.MajorMinor(config.Default().KubernetesVersion), "")
cmd.Flags().Bool("yes", false, "") cmd.Flags().Bool("yes", false, "")
cmd.Flags().String("name", "constell", "") cmd.Flags().String("name", "constell", "")
cmd.Flags().String("tf-log", "NONE", "") cmd.Flags().String("tf-log", "NONE", "")
@ -874,17 +782,14 @@ func TestIAMCreateGCP(t *testing.T) {
if tc.yesFlag { if tc.yesFlag {
require.NoError(cmd.Flags().Set("yes", "true")) require.NoError(cmd.Flags().Set("yes", "true"))
} }
if tc.generateConfigFlag { if tc.updateConfigFlag {
require.NoError(cmd.Flags().Set("generate-config", "true")) require.NoError(cmd.Flags().Set("update-config", "true"))
} }
if tc.configFlag != "" { if tc.configFlag != "" {
require.NoError(cmd.Flags().Set("config", tc.configFlag)) require.NoError(cmd.Flags().Set("config", tc.configFlag))
} }
if tc.k8sVersionFlag != "" {
require.NoError(cmd.Flags().Set("kubernetes", tc.k8sVersionFlag))
}
fileHandler := file.NewHandler(tc.setupFs(require, tc.provider, tc.existingFiles, tc.existingDirs)) fileHandler := file.NewHandler(tc.setupFs(require, tc.provider, tc.existingConfigFiles, tc.existingDirs))
iamCreator := &iamCreator{ iamCreator := &iamCreator{
cmd: cmd, cmd: cmd,
@ -908,7 +813,7 @@ func TestIAMCreateGCP(t *testing.T) {
return return
} }
if tc.generateConfigFlag { if tc.updateConfigFlag {
readConfig := &config.Config{} readConfig := &config.Config{}
readErr := fileHandler.ReadYAML(tc.configFlag, readConfig) readErr := fileHandler.ReadYAML(tc.configFlag, readConfig)
require.NoError(readErr) require.NoError(readErr)

View File

@ -50,7 +50,7 @@ func newUpgradeCheckCmd() *cobra.Command {
RunE: runUpgradeCheck, RunE: runUpgradeCheck,
} }
cmd.Flags().BoolP("write-config", "w", false, "update the specified config file with the suggested versions") cmd.Flags().BoolP("update-config", "u", false, "update the specified config file with the suggested versions")
cmd.Flags().String("ref", versionsapi.ReleaseRef, "the reference to use for querying new versions") cmd.Flags().String("ref", versionsapi.ReleaseRef, "the reference to use for querying new versions")
cmd.Flags().String("stream", "stable", "the stream to use for querying new versions") cmd.Flags().String("stream", "stable", "the stream to use for querying new versions")
@ -109,9 +109,9 @@ func parseUpgradeCheckFlags(cmd *cobra.Command) (upgradeCheckFlags, error) {
if err != nil { if err != nil {
return upgradeCheckFlags{}, fmt.Errorf("parsing force bool: %w", err) return upgradeCheckFlags{}, fmt.Errorf("parsing force bool: %w", err)
} }
writeConfig, err := cmd.Flags().GetBool("write-config") updateConfig, err := cmd.Flags().GetBool("update-config")
if err != nil { if err != nil {
return upgradeCheckFlags{}, fmt.Errorf("parsing write-config bool: %w", err) return upgradeCheckFlags{}, fmt.Errorf("parsing update-config bool: %w", err)
} }
ref, err := cmd.Flags().GetString("ref") ref, err := cmd.Flags().GetString("ref")
if err != nil { if err != nil {
@ -134,7 +134,7 @@ func parseUpgradeCheckFlags(cmd *cobra.Command) (upgradeCheckFlags, error) {
return upgradeCheckFlags{ return upgradeCheckFlags{
configPath: configPath, configPath: configPath,
force: force, force: force,
writeConfig: writeConfig, updateConfig: updateConfig,
ref: ref, ref: ref,
stream: stream, stream: stream,
terraformLogLevel: logLevel, terraformLogLevel: logLevel,
@ -257,7 +257,7 @@ func (u *upgradeCheckCmd) upgradeCheck(cmd *cobra.Command, fileHandler file.Hand
// Using Print over Println as buildString already includes a trailing newline where necessary. // Using Print over Println as buildString already includes a trailing newline where necessary.
cmd.Print(updateMsg) cmd.Print(updateMsg)
if flags.writeConfig { if flags.updateConfig {
if err := upgrade.writeConfig(conf, fileHandler, flags.configPath); err != nil { if err := upgrade.writeConfig(conf, fileHandler, flags.configPath); err != nil {
return fmt.Errorf("writing config: %w", err) return fmt.Errorf("writing config: %w", err)
} }
@ -717,7 +717,7 @@ func (v *versionCollector) filterCompatibleCLIVersions(ctx context.Context, cliP
type upgradeCheckFlags struct { type upgradeCheckFlags struct {
configPath string configPath string
force bool force bool
writeConfig bool updateConfig bool
ref string ref string
stream string stream string
terraformLogLevel terraform.LogLevel terraformLogLevel terraform.LogLevel

View File

@ -13,19 +13,47 @@ If you encounter any problem with the following steps, make sure to use the [lat
## Create a cluster ## Create a cluster
1. Create the configuration file and IAM resources for your selected cloud provider 1. Create the [configuration file](../workflows/config.md) for your cloud provider.
First, you need to create a [configuration file](../workflows/config.md) and an [IAM configuration](../workflows/config.md#creating-an-iam-configuration). The easiest way to do this is the following CLI command:
<tabs groupId="csp"> <tabs groupId="csp">
<tabItem value="azure" label="Azure"> <tabItem value="azure" label="Azure">
```bash ```bash
constellation iam create azure --region=westus --resourceGroup=constellTest --servicePrincipal=spTest --generate-config constellation config generate azure
``` ```
This command creates IAM configuration on the Azure region `westus` creating a new resource group `constellTest` and a new service principal `spTest`. It also creates the configuration file `constellation-conf.yaml` in your current directory with the IAM values filled in. </tabItem>
<tabItem value="gcp" label="GCP">
```bash
constellation config generate gcp
```
</tabItem>
<tabItem value="aws" label="AWS">
```bash
constellation config generate aws
```
</tabItem>
</tabs>
2. Create your [IAM configuration](../workflows/config.md#creating-an-iam-configuration).
<tabs groupId="csp">
<tabItem value="azure" label="Azure">
```bash
constellation iam create azure --region=westus --resourceGroup=constellTest --servicePrincipal=spTest --update-config
```
This command creates IAM configuration on the Azure region `westus` creating a new resource group `constellTest` and a new service principal `spTest`. It also updates the configuration file `constellation-conf.yaml` in your current directory with the IAM values filled in.
Note that CVMs are currently only supported in a few regions, check [Azure's products available by region](https://azure.microsoft.com/en-us/global-infrastructure/services/?products=virtual-machines&regions=all). These are: Note that CVMs are currently only supported in a few regions, check [Azure's products available by region](https://azure.microsoft.com/en-us/global-infrastructure/services/?products=virtual-machines&regions=all). These are:
* `westus` * `westus`
@ -38,10 +66,10 @@ If you encounter any problem with the following steps, make sure to use the [lat
<tabItem value="gcp" label="GCP"> <tabItem value="gcp" label="GCP">
```bash ```bash
constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test --generate-config constellation iam create gcp --projectID=yourproject-12345 --zone=europe-west2-a --serviceAccountID=constell-test --update-config
``` ```
This command creates IAM configuration in the GCP project `yourproject-12345` on the GCP zone `europe-west2-a` creating a new service account `constell-test`. It also creates the configuration file `constellation-conf.yaml` in your current directory with the IAM values filled in. This command creates IAM configuration in the GCP project `yourproject-12345` on the GCP zone `europe-west2-a` creating a new service account `constell-test`. It also updates the configuration file `constellation-conf.yaml` in your current directory with the IAM values filled in.
Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `C2D` or `N2D`. Note that only regions offering CVMs of the `C2D` or `N2D` series are supported. You can find a [list of all regions in Google's documentation](https://cloud.google.com/compute/docs/regions-zones#available), which you can filter by machine type `C2D` or `N2D`.
@ -50,10 +78,10 @@ If you encounter any problem with the following steps, make sure to use the [lat
<tabItem value="aws" label="AWS"> <tabItem value="aws" label="AWS">
```bash ```bash
constellation iam create aws --zone=us-east-2a --prefix=constellTest --generate-config constellation iam create aws --zone=us-east-2a --prefix=constellTest --update-config
``` ```
This command creates IAM configuration for the AWS zone `us-east-2a` using the prefix `constellTest` for all named resources being created. It also creates the configuration file `constellation-conf.yaml` in your current directory with the IAM values filled in. This command creates IAM configuration for the AWS zone `us-east-2a` using the prefix `constellTest` for all named resources being created. It also updates the configuration file `constellation-conf.yaml` in your current directory with the IAM values filled in.
Depending on the attestation variant selected on config generation, different regions are available. Depending on the attestation variant selected on config generation, different regions are available.
AMD SEV-SNP machines (requires the default attestation variant `awsSEVSNP`) are currently available in the following regions: AMD SEV-SNP machines (requires the default attestation variant `awsSEVSNP`) are currently available in the following regions:
@ -89,7 +117,7 @@ If you encounter any problem with the following steps, make sure to use the [lat
::: :::
--> -->
2. Create the cluster with one control-plane node and two worker nodes. `constellation create` uses options set in `constellation-conf.yaml`. 3. Create the cluster with one control-plane node and two worker nodes. `constellation create` uses options set in `constellation-conf.yaml`.
If you want to manually use [Terraform](../reference/terraform.md) for managing the cloud resources instead, follow the corresponding instructions in the [Create workflow](../workflows/create.md). If you want to manually use [Terraform](../reference/terraform.md) for managing the cloud resources instead, follow the corresponding instructions in the [Create workflow](../workflows/create.md).
:::tip :::tip
@ -109,7 +137,7 @@ If you encounter any problem with the following steps, make sure to use the [lat
Your Constellation cluster was created successfully. Your Constellation cluster was created successfully.
``` ```
3. Initialize the cluster 4. Initialize the cluster.
```bash ```bash
constellation init constellation init
@ -140,7 +168,7 @@ If you encounter any problem with the following steps, make sure to use the [lat
::: :::
4. Configure kubectl 5. Configure kubectl.
```bash ```bash
export KUBECONFIG="$PWD/constellation-admin.conf" export KUBECONFIG="$PWD/constellation-admin.conf"

View File

@ -416,7 +416,7 @@ constellation upgrade check [flags]
-h, --help help for check -h, --help help for check
--ref string the reference to use for querying new versions (default "-") --ref string the reference to use for querying new versions (default "-")
--stream string the stream to use for querying new versions (default "stable") --stream string the stream to use for querying new versions (default "stable")
-w, --write-config update the specified config file with the suggested versions -u, --update-config update the specified config file with the suggested versions
``` ```
### Options inherited from parent commands ### Options inherited from parent commands
@ -580,10 +580,9 @@ Create IAM configuration on a cloud platform for your Constellation cluster.
### Options ### Options
``` ```
--generate-config automatically generate a configuration file and fill in the required fields -h, --help help for create
-h, --help help for create --update-config automatically update the config file with the specific IAM information
-k, --kubernetes string Kubernetes version to use in format MAJOR.MINOR - only usable in combination with --generate-config (default "v1.26") -y, --yes create the IAM configuration without further confirmation
-y, --yes create the IAM configuration without further confirmation
``` ```
### Options inherited from parent commands ### Options inherited from parent commands
@ -619,13 +618,12 @@ constellation iam create aws [flags]
### Options inherited from parent commands ### Options inherited from parent commands
``` ```
--config string path to the configuration file (default "constellation-conf.yaml") --config string path to the configuration file (default "constellation-conf.yaml")
--debug enable debug logging --debug enable debug logging
--force disable version compatibility checks - might result in corrupted clusters --force disable version compatibility checks - might result in corrupted clusters
--generate-config automatically generate a configuration file and fill in the required fields --tf-log string sets the Terraform log level (default "NONE" - no logs) (default "NONE")
-k, --kubernetes string Kubernetes version to use in format MAJOR.MINOR - only usable in combination with --generate-config (default "v1.26") --update-config automatically update the config file with the specific IAM information
--tf-log string sets the Terraform log level (default "NONE" - no logs) (default "NONE") -y, --yes create the IAM configuration without further confirmation
-y, --yes create the IAM configuration without further confirmation
``` ```
## constellation iam create azure ## constellation iam create azure
@ -652,13 +650,12 @@ constellation iam create azure [flags]
### Options inherited from parent commands ### Options inherited from parent commands
``` ```
--config string path to the configuration file (default "constellation-conf.yaml") --config string path to the configuration file (default "constellation-conf.yaml")
--debug enable debug logging --debug enable debug logging
--force disable version compatibility checks - might result in corrupted clusters --force disable version compatibility checks - might result in corrupted clusters
--generate-config automatically generate a configuration file and fill in the required fields --tf-log string sets the Terraform log level (default "NONE" - no logs) (default "NONE")
-k, --kubernetes string Kubernetes version to use in format MAJOR.MINOR - only usable in combination with --generate-config (default "v1.26") --update-config automatically update the config file with the specific IAM information
--tf-log string sets the Terraform log level (default "NONE" - no logs) (default "NONE") -y, --yes create the IAM configuration without further confirmation
-y, --yes create the IAM configuration without further confirmation
``` ```
## constellation iam create gcp ## constellation iam create gcp
@ -688,13 +685,12 @@ constellation iam create gcp [flags]
### Options inherited from parent commands ### Options inherited from parent commands
``` ```
--config string path to the configuration file (default "constellation-conf.yaml") --config string path to the configuration file (default "constellation-conf.yaml")
--debug enable debug logging --debug enable debug logging
--force disable version compatibility checks - might result in corrupted clusters --force disable version compatibility checks - might result in corrupted clusters
--generate-config automatically generate a configuration file and fill in the required fields --tf-log string sets the Terraform log level (default "NONE" - no logs) (default "NONE")
-k, --kubernetes string Kubernetes version to use in format MAJOR.MINOR - only usable in combination with --generate-config (default "v1.26") --update-config automatically update the config file with the specific IAM information
--tf-log string sets the Terraform log level (default "NONE" - no logs) (default "NONE") -y, --yes create the IAM configuration without further confirmation
-y, --yes create the IAM configuration without further confirmation
``` ```
## constellation iam destroy ## constellation iam destroy

View File

@ -40,10 +40,6 @@ constellation config generate aws
This creates the file `constellation-conf.yaml` in the current directory. This creates the file `constellation-conf.yaml` in the current directory.
:::tip
You can also automatically generate a configuration file by adding the `--generate-config` flag to the `constellation iam create` command when [creating an IAM configuration](#creating-an-iam-configuration).
:::
## Choosing a VM type ## Choosing a VM type
Constellation supports the following VM types: Constellation supports the following VM types:
@ -92,7 +88,7 @@ See also Constellation's [Kubernetes support policy](../architecture/versions.md
## Creating an IAM configuration ## Creating an IAM configuration
You can create an IAM configuration for your cluster automatically using the `constellation iam create` command. You can create an IAM configuration for your cluster automatically using the `constellation iam create` command.
If you haven't generated a configuration file yet, you can do so by adding the `--generate-config` flag to the command. This creates a configuration file and populates it with the created IAM values. If you already have a constellation configuration file, you can add the `--update-config` flag to the command. This writes the needed IAM fields into your configuration.
<tabs groupId="csp"> <tabs groupId="csp">
<tabItem value="azure" label="Azure"> <tabItem value="azure" label="Azure">

View File

@ -36,10 +36,10 @@ To learn which versions the current CLI can upgrade to and what's installed in y
constellation upgrade check constellation upgrade check
# Show possible upgrades and write them to config file # Show possible upgrades and write them to config file
constellation upgrade check --write-config constellation upgrade check --update-config
``` ```
You can either enter the reported target versions into your config manually or run the above command with the `--write-config` flag. You can either enter the reported target versions into your config manually or run the above command with the `--update-config` flag.
When using this flag, the `kubernetesVersion`, `image`, `microserviceVersion` and `attestation` fields are overwritten with the smallest available upgrade. When using this flag, the `kubernetesVersion`, `image`, `microserviceVersion` and `attestation` fields are overwritten with the smallest available upgrade.
## Apply the upgrade ## Apply the upgrade

View File

@ -23,9 +23,13 @@ spawn asciinema rec --overwrite /recordings/configure-cluster.cast
send "\r" send "\r"
expect_prompt expect_prompt
run_command "# Step 1: Create IAM configuration and Constellation configuration file" run_command "# Step 1: Create a configuration file for Constellation"
expect_prompt expect_prompt
run_command "constellation iam create gcp --generate-config --projectID constellation-331613 --serviceAccountID constellation-demo --zone europe-west3-b" run_command "constellation config generate gcp"
expect_prompt
run_command "# Step 2: Create your cluster's IAM configuration"
expect_prompt
run_command "constellation iam create gcp --update-config --projectID constellation-331613 --serviceAccountID constellation-demo --zone europe-west3-b"
expect -re "y\/n" expect -re "y\/n"
send "y" send "y"
send "\r" send "\r"

View File

@ -10,7 +10,8 @@
# Create IAM configuration # Create IAM configuration
pushd constellation || exit pushd constellation || exit
constellation iam create gcp --generate-config --projectID constellation-331613 --serviceAccountID constellation-demo --zone europe-west3-b --yes constellation config generate gcp
constellation iam create gcp --update-config --projectID constellation-331613 --serviceAccountID constellation-demo --zone europe-west3-b --yes
popd || exit popd || exit
docker build -t screenrecodings docker docker build -t screenrecodings docker

View File

@ -208,7 +208,7 @@ If there are still microservice updates needed with the current CLI, we need to
We also print `In newer CLI versions there are even newer versions available.` if e.g. there is a newer patch version of Kubernetes available in one of the proposed minor versions. We also print `In newer CLI versions there are even newer versions available.` if e.g. there is a newer patch version of Kubernetes available in one of the proposed minor versions.
Executing `constellation upgrade check --write-config` writes all new version values to `constellation-conf.json`. Executing `constellation upgrade check --update-config` updates all new version values to `constellation-conf.json`.
This allows the user to execute `constellation upgrade apply` without manually modifying `constellation-conf.json`. This allows the user to execute `constellation upgrade apply` without manually modifying `constellation-conf.json`.
```bash ```bash