From ce0edc8c803a3f3e1b0e6238445bb7e44207e2ab Mon Sep 17 00:00:00 2001 From: Nils Hanke Date: Wed, 7 Sep 2022 15:38:29 +0200 Subject: [PATCH] Purge provider argument from constellation create and verify --- cli/internal/cmd/create.go | 29 ++++---------- cli/internal/cmd/create_test.go | 59 +-------------------------- cli/internal/cmd/init.go | 25 ++++-------- cli/internal/cmd/init_test.go | 40 ------------------- cli/internal/cmd/readconfig.go | 12 ++---- cli/internal/cmd/readconfig_test.go | 6 ++- cli/internal/cmd/recover.go | 3 +- cli/internal/cmd/verify.go | 28 +++---------- cli/internal/cmd/verify_test.go | 62 +---------------------------- 9 files changed, 31 insertions(+), 233 deletions(-) diff --git a/cli/internal/cmd/create.go b/cli/internal/cmd/create.go index f80681619..d0f974295 100644 --- a/cli/internal/cmd/create.go +++ b/cli/internal/cmd/create.go @@ -23,16 +23,13 @@ import ( // NewCreateCmd returns a new cobra.Command for the create command. func NewCreateCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "create {aws|azure|gcp}", + Use: "create", Short: "Create instances on a cloud platform for your Constellation cluster", Long: "Create instances on a cloud platform for your Constellation cluster.", Args: cobra.MatchAll( - cobra.ExactArgs(1), - isCloudProvider(0), - warnAWS(0), + cobra.ExactArgs(0), ), - ValidArgsFunction: createCompletion, - RunE: runCreate, + RunE: runCreate, } cmd.Flags().String("name", "constell", "create the cluster with the specified name") cmd.Flags().BoolP("yes", "y", false, "create the cluster without further confirmation") @@ -44,15 +41,13 @@ func NewCreateCmd() *cobra.Command { } func runCreate(cmd *cobra.Command, args []string) error { - provider := cloudprovider.FromString(args[0]) fileHandler := file.NewHandler(afero.NewOsFs()) creator := cloudcmd.NewCreator(cmd.OutOrStdout()) - return create(cmd, creator, fileHandler, provider) + return create(cmd, creator, fileHandler) } -func create(cmd *cobra.Command, creator cloudCreator, fileHandler file.Handler, provider cloudprovider.Provider, -) (retErr error) { +func create(cmd *cobra.Command, creator cloudCreator, fileHandler file.Handler) (retErr error) { flags, err := parseCreateFlags(cmd) if err != nil { return err @@ -62,7 +57,7 @@ func create(cmd *cobra.Command, creator cloudCreator, fileHandler file.Handler, return err } - config, err := readConfig(cmd.OutOrStdout(), fileHandler, flags.configPath, provider) + config, err := readConfig(cmd.OutOrStdout(), fileHandler, flags.configPath) if err != nil { return fmt.Errorf("reading and validating config: %w", err) } @@ -92,6 +87,7 @@ func create(cmd *cobra.Command, creator cloudCreator, fileHandler file.Handler, cmd.Println("") } + provider := config.GetProvider() var instanceType string switch provider { case cloudprovider.Azure: @@ -216,17 +212,6 @@ func writeIPtoIDFile(fileHandler file.Handler, state state.ConstellationState) e return fileHandler.WriteJSON(constants.ClusterIDsFileName, idFile, file.OptNone) } -// createCompletion handles the completion of the create command. It is frequently called -// while the user types arguments of the command to suggest completion. -func createCompletion(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - switch len(args) { - case 0: - return []string{"aws", "gcp", "azure"}, cobra.ShellCompDirectiveNoFileComp - default: - return []string{}, cobra.ShellCompDirectiveError - } -} - func must(err error) { if err != nil { panic(err) diff --git a/cli/internal/cmd/create_test.go b/cli/internal/cmd/create_test.go index 4881e29a2..9f95ceb2c 100644 --- a/cli/internal/cmd/create_test.go +++ b/cli/internal/cmd/create_test.go @@ -18,37 +18,10 @@ import ( "github.com/edgelesssys/constellation/internal/file" "github.com/edgelesssys/constellation/internal/state" "github.com/spf13/afero" - "github.com/spf13/cobra" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -func TestCreateArgumentValidation(t *testing.T) { - testCases := map[string]struct { - args []string - wantErr bool - }{ - "gcp": {[]string{"gcp"}, false}, - "azure": {[]string{"azure"}, false}, - "aws waring": {[]string{"aws"}, true}, - "too many args": {[]string{"gcp", "1", "2"}, true}, - } - - for name, tc := range testCases { - t.Run(name, func(t *testing.T) { - assert := assert.New(t) - - err := NewCreateCmd().ValidateArgs(tc.args) - - if tc.wantErr { - assert.Error(err) - } else { - assert.NoError(err) - } - }) - } -} - func TestCreate(t *testing.T) { testState := state.ConstellationState{Name: "test", LoadBalancerIP: "192.0.2.1"} someErr := errors.New("failed") @@ -242,7 +215,7 @@ func TestCreate(t *testing.T) { fileHandler := file.NewHandler(tc.setupFs(require)) - err := create(cmd, tc.creator, fileHandler, tc.provider) + err := create(cmd, tc.creator, fileHandler) if tc.wantErr { assert.Error(err) @@ -314,36 +287,6 @@ func TestCheckDirClean(t *testing.T) { } } -func TestCreateCompletion(t *testing.T) { - testCases := map[string]struct { - args []string - wantResult []string - wantShellCD cobra.ShellCompDirective - }{ - "first arg": { - args: []string{}, - wantResult: []string{"aws", "gcp", "azure"}, - wantShellCD: cobra.ShellCompDirectiveNoFileComp, - }, - "second arg": { - args: []string{"gcp", "foo"}, - wantResult: []string{}, - wantShellCD: cobra.ShellCompDirectiveError, - }, - } - - for name, tc := range testCases { - t.Run(name, func(t *testing.T) { - assert := assert.New(t) - - cmd := &cobra.Command{} - result, shellCD := createCompletion(cmd, tc.args, "") - assert.Equal(tc.wantResult, result) - assert.Equal(tc.wantShellCD, shellCD) - }) - } -} - func intPtr(i int) *int { return &i } diff --git a/cli/internal/cmd/init.go b/cli/internal/cmd/init.go index 572df5ed1..1aaf11071 100644 --- a/cli/internal/cmd/init.go +++ b/cli/internal/cmd/init.go @@ -47,12 +47,11 @@ import ( // NewInitCmd returns a new cobra.Command for the init command. func NewInitCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "init", - Short: "Initialize the Constellation cluster", - Long: "Initialize the Constellation cluster. Start your confidential Kubernetes.", - ValidArgsFunction: initCompletion, - Args: cobra.ExactArgs(0), - RunE: runInitialize, + Use: "init", + Short: "Initialize the Constellation cluster", + Long: "Initialize the Constellation cluster. Start your confidential Kubernetes.", + Args: cobra.ExactArgs(0), + RunE: runInitialize, } cmd.Flags().String("master-secret", "", "path to base64-encoded master secret") cmd.Flags().String("endpoint", "", "endpoint of the bootstrapper, passed as HOST[:PORT]") @@ -92,9 +91,7 @@ func initialize(cmd *cobra.Command, newDialer func(validator *cloudcmd.Validator return fmt.Errorf("loading Constellation state file: %w", err) } - provider := cloudprovider.FromString(stat.CloudProvider) - - config, err := readConfig(cmd.OutOrStdout(), fileHandler, flags.configPath, provider) + config, err := readConfig(cmd.OutOrStdout(), fileHandler, flags.configPath) if err != nil { return fmt.Errorf("reading and validating config: %w", err) } @@ -107,6 +104,7 @@ func initialize(cmd *cobra.Command, newDialer func(validator *cloudcmd.Validator cmd.Printf("Warning: Constellation with Kubernetes %v is still in preview. Use only for evaluation purposes.\n", k8sVersion) } + provider := config.GetProvider() checker := license.NewChecker(quotaChecker, fileHandler) if err := checker.CheckLicense(cmd.Context(), provider, config.Provider, cmd.Printf); err != nil { cmd.Printf("License check failed: %v", err) @@ -414,15 +412,6 @@ func getScalingGroupsFromState(stat state.ConstellationState, config *config.Con } } -// initCompletion handels the completion of CLI arguments. It is frequently called -// while the user types arguments of the command to suggest completion. -func initCompletion(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - if len(args) != 0 { - return []string{}, cobra.ShellCompDirectiveError - } - return []string{}, cobra.ShellCompDirectiveDefault -} - type grpcDialer interface { Dial(ctx context.Context, target string) (*grpc.ClientConn, error) } diff --git a/cli/internal/cmd/init_test.go b/cli/internal/cmd/init_test.go index 1e0fb7da7..f1c4efa9c 100644 --- a/cli/internal/cmd/init_test.go +++ b/cli/internal/cmd/init_test.go @@ -33,7 +33,6 @@ import ( "github.com/edgelesssys/constellation/internal/oid" "github.com/edgelesssys/constellation/internal/state" "github.com/spf13/afero" - "github.com/spf13/cobra" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" @@ -273,45 +272,6 @@ func TestWriteOutput(t *testing.T) { assert.Equal(expectedIDFile, testIDFile) } -func TestInitCompletion(t *testing.T) { - testCases := map[string]struct { - args []string - toComplete string - wantResult []string - wantShellCD cobra.ShellCompDirective - }{ - "first arg": { - args: []string{}, - toComplete: "hello", - wantResult: []string{}, - wantShellCD: cobra.ShellCompDirectiveDefault, - }, - "secnod arg": { - args: []string{"23"}, - toComplete: "/test/h", - wantResult: []string{}, - wantShellCD: cobra.ShellCompDirectiveError, - }, - "third arg": { - args: []string{"./file", "sth"}, - toComplete: "./file", - wantResult: []string{}, - wantShellCD: cobra.ShellCompDirectiveError, - }, - } - - for name, tc := range testCases { - t.Run(name, func(t *testing.T) { - assert := assert.New(t) - - cmd := &cobra.Command{} - result, shellCD := initCompletion(cmd, tc.args, tc.toComplete) - assert.Equal(tc.wantResult, result) - assert.Equal(tc.wantShellCD, shellCD) - }) - } -} - func TestReadOrGenerateMasterSecret(t *testing.T) { testCases := map[string]struct { filename string diff --git a/cli/internal/cmd/readconfig.go b/cli/internal/cmd/readconfig.go index 528418538..66b9626a1 100644 --- a/cli/internal/cmd/readconfig.go +++ b/cli/internal/cmd/readconfig.go @@ -11,12 +11,11 @@ import ( "fmt" "io" - "github.com/edgelesssys/constellation/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/internal/config" "github.com/edgelesssys/constellation/internal/file" ) -func readConfig(out io.Writer, fileHandler file.Handler, name string, provider cloudprovider.Provider) (*config.Config, error) { +func readConfig(out io.Writer, fileHandler file.Handler, name string) (*config.Config, error) { if name == "" { return config.Default(), nil } @@ -25,13 +24,14 @@ func readConfig(out io.Writer, fileHandler file.Handler, name string, provider c if err != nil { return nil, err } - if err := validateConfig(out, cnf, provider); err != nil { + if err := validateConfig(out, cnf); err != nil { return nil, err } + return cnf, nil } -func validateConfig(out io.Writer, cnf *config.Config, provider cloudprovider.Provider) error { +func validateConfig(out io.Writer, cnf *config.Config) error { msgs, err := cnf.Validate() if err != nil { return fmt.Errorf("performing config validation: %w", err) @@ -46,9 +46,5 @@ func validateConfig(out io.Writer, cnf *config.Config, provider cloudprovider.Pr return errors.New("invalid configuration") } - if provider != cloudprovider.Unknown && !cnf.HasProvider(provider) { - return fmt.Errorf("configuration doesn't contain provider: %v", provider) - } - return nil } diff --git a/cli/internal/cmd/readconfig_test.go b/cli/internal/cmd/readconfig_test.go index 9b2c8ec1a..1b98cdb01 100644 --- a/cli/internal/cmd/readconfig_test.go +++ b/cli/internal/cmd/readconfig_test.go @@ -71,13 +71,15 @@ func TestValidateConfig(t *testing.T) { wantOutput: true, wantErr: true, }, - "config without provider is ok if no provider required": { + "config without provider is not ok": { cnf: func() *config.Config { cnf := config.Default() cnf.Provider = config.ProviderConfig{} return cnf }(), + wantErr: true, }, + "config without required provider": { cnf: func() *config.Config { cnf := config.Default() @@ -96,7 +98,7 @@ func TestValidateConfig(t *testing.T) { out := &bytes.Buffer{} - err := validateConfig(out, tc.cnf, tc.provider) + err := validateConfig(out, tc.cnf) if tc.wantErr { assert.Error(err) diff --git a/cli/internal/cmd/recover.go b/cli/internal/cmd/recover.go index 5d0a6493d..5d9b22226 100644 --- a/cli/internal/cmd/recover.go +++ b/cli/internal/cmd/recover.go @@ -68,8 +68,7 @@ func recover(cmd *cobra.Command, fileHandler file.Handler, recoveryClient recove } provider := cloudprovider.FromString(stat.CloudProvider) - - config, err := readConfig(cmd.OutOrStdout(), fileHandler, flags.configPath, provider) + config, err := readConfig(cmd.OutOrStdout(), fileHandler, flags.configPath) if err != nil { return fmt.Errorf("reading and validating config: %w", err) } diff --git a/cli/internal/cmd/verify.go b/cli/internal/cmd/verify.go index 48fe71f10..e7091ae72 100644 --- a/cli/internal/cmd/verify.go +++ b/cli/internal/cmd/verify.go @@ -17,7 +17,6 @@ import ( "github.com/edgelesssys/constellation/cli/internal/cloudcmd" "github.com/edgelesssys/constellation/internal/atls" - "github.com/edgelesssys/constellation/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/internal/constants" "github.com/edgelesssys/constellation/internal/crypto" "github.com/edgelesssys/constellation/internal/file" @@ -31,15 +30,13 @@ import ( // NewVerifyCmd returns a new cobra.Command for the verify command. func NewVerifyCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "verify {aws|azure|gcp}", + Use: "verify", Short: "Verify the confidential properties of a Constellation cluster", Long: `Verify the confidential properties of a Constellation cluster. If arguments aren't specified, values are read from ` + "`" + constants.ClusterIDsFileName + "`.", Args: cobra.MatchAll( - cobra.ExactArgs(1), - isCloudProvider(0), - warnAWS(0), + cobra.ExactArgs(0), ), RunE: runVerify, } @@ -50,25 +47,23 @@ If arguments aren't specified, values are read from ` + "`" + constants.ClusterI } func runVerify(cmd *cobra.Command, args []string) error { - provider := cloudprovider.FromString(args[0]) fileHandler := file.NewHandler(afero.NewOsFs()) verifyClient := &constellationVerifier{dialer: dialer.New(nil, nil, &net.Dialer{})} - return verify(cmd, provider, fileHandler, verifyClient) + return verify(cmd, fileHandler, verifyClient) } -func verify( - cmd *cobra.Command, provider cloudprovider.Provider, fileHandler file.Handler, verifyClient verifyClient, -) error { +func verify(cmd *cobra.Command, fileHandler file.Handler, verifyClient verifyClient) error { flags, err := parseVerifyFlags(cmd, fileHandler) if err != nil { return err } - config, err := readConfig(cmd.OutOrStdout(), fileHandler, flags.configPath, provider) + config, err := readConfig(cmd.OutOrStdout(), fileHandler, flags.configPath) if err != nil { return fmt.Errorf("reading and validating config: %w", err) } + provider := config.GetProvider() validators, err := cloudcmd.NewValidator(provider, config) if err != nil { return err @@ -181,17 +176,6 @@ func addPortIfMissing(endpoint string, defaultPort int) (string, error) { return "", err } -// verifyCompletion handles the completion of CLI arguments. It is frequently called -// while the user types arguments of the command to suggest completion. -func verifyCompletion(_ *cobra.Command, args []string, _ string) ([]string, cobra.ShellCompDirective) { - switch len(args) { - case 0: - return []string{"gcp", "azure"}, cobra.ShellCompDirectiveNoFileComp - default: - return []string{}, cobra.ShellCompDirectiveError - } -} - type constellationVerifier struct { dialer grpcInsecureDialer } diff --git a/cli/internal/cmd/verify_test.go b/cli/internal/cmd/verify_test.go index c8ecadb31..d62d0b4d7 100644 --- a/cli/internal/cmd/verify_test.go +++ b/cli/internal/cmd/verify_test.go @@ -26,7 +26,6 @@ import ( "github.com/edgelesssys/constellation/internal/oid" "github.com/edgelesssys/constellation/verify/verifyproto" "github.com/spf13/afero" - "github.com/spf13/cobra" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" @@ -34,33 +33,6 @@ import ( rpcStatus "google.golang.org/grpc/status" ) -func TestVerifyCmdArgumentValidation(t *testing.T) { - testCases := map[string]struct { - args []string - wantErr bool - }{ - "no args": {[]string{}, true}, - "valid azure": {[]string{"azure"}, false}, - "valid gcp": {[]string{"gcp"}, false}, - "invalid provider": {[]string{"invalid", "192.0.2.1", "1234"}, true}, - } - - for name, tc := range testCases { - t.Run(name, func(t *testing.T) { - assert := assert.New(t) - - cmd := NewVerifyCmd() - err := cmd.ValidateArgs(tc.args) - - if tc.wantErr { - assert.Error(err) - } else { - assert.NoError(err) - } - }) - } -} - func TestVerify(t *testing.T) { zeroBase64 := base64.StdEncoding.EncodeToString([]byte("00000000000000000000000000000000")) someErr := errors.New("failed") @@ -190,7 +162,7 @@ func TestVerify(t *testing.T) { require.NoError(fileHandler.WriteJSON(constants.ClusterIDsFileName, tc.idFile, file.OptNone)) } - err := verify(cmd, tc.provider, fileHandler, tc.protoClient) + err := verify(cmd, fileHandler, tc.protoClient) if tc.wantErr { assert.Error(err) @@ -203,38 +175,6 @@ func TestVerify(t *testing.T) { } } -func TestVerifyCompletion(t *testing.T) { - testCases := map[string]struct { - args []string - toComplete string - wantResult []string - wantShellCD cobra.ShellCompDirective - }{ - "first arg": { - args: []string{}, - toComplete: "az", - wantResult: []string{"gcp", "azure"}, - wantShellCD: cobra.ShellCompDirectiveNoFileComp, - }, - "additional arg": { - args: []string{"gcp", "foo"}, - wantResult: []string{}, - wantShellCD: cobra.ShellCompDirectiveError, - }, - } - - for name, tc := range testCases { - t.Run(name, func(t *testing.T) { - assert := assert.New(t) - - cmd := &cobra.Command{} - result, shellCD := verifyCompletion(cmd, tc.args, tc.toComplete) - assert.Equal(tc.wantResult, result) - assert.Equal(tc.wantShellCD, shellCD) - }) - } -} - func TestVerifyClient(t *testing.T) { testCases := map[string]struct { attestationDoc atls.FakeAttestationDoc