Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 62 additions & 48 deletions cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,21 @@ import (
)

var (
backend string
awsProfile string
awsEndpointURL string
vmDriver string
cpu int
disk int
memory int
arch string
docker bool
gitLivereload bool
blueprint string
toolsManager string
platform string
endpoint string
initBackend string
initAwsProfile string
initAwsEndpointURL string
initVmDriver string
initCpu int
initDisk int
initMemory int
initArch string
initDocker bool
initGitLivereload bool
initBlueprint string
initToolsManager string
initPlatform string
initEndpoint string
initSetFlags []string
)

var initCmd = &cobra.Command{
Expand Down Expand Up @@ -73,7 +74,7 @@ var initCmd = &cobra.Command{
}

// Determine the default vm driver to use if not set
vmDriverConfig := vmDriver
vmDriverConfig := initVmDriver
if vmDriverConfig == "" {
vmDriverConfig = configHandler.GetString("vm.driver")
if vmDriverConfig == "" && (contextName == "local" || strings.HasPrefix(contextName, "local-")) {
Expand All @@ -97,32 +98,25 @@ var initCmd = &cobra.Command{
return fmt.Errorf("Error setting default config: %w", err)
}

// Set the vm driver only if it's configured
if vmDriverConfig != "" {
if err := configHandler.SetContextValue("vm.driver", vmDriverConfig); err != nil {
return fmt.Errorf("Error setting vm driver: %w", err)
}
}

// Create the flag to config path mapping and set the configurations
configurations := []struct {
flagName string
configPath string
value any
}{
{"aws-endpoint-url", "aws.aws_endpoint_url", awsEndpointURL},
{"aws-profile", "aws.aws_profile", awsProfile},
{"docker", "docker.enabled", docker},
{"backend", "terraform.backend", backend},
{"vm-cpu", "vm.cpu", cpu},
{"vm-disk", "vm.disk", disk},
{"vm-memory", "vm.memory", memory},
{"vm-arch", "vm.arch", arch},
{"tools-manager", "toolsManager", toolsManager},
{"git-livereload", "git.livereload.enabled", gitLivereload},
{"blueprint", "blueprint", blueprint},
{"endpoint", "cluster.endpoint", endpoint},
{"platform", "cluster.platform", platform},
{"aws-endpoint-url", "aws.aws_endpoint_url", initAwsEndpointURL},
{"aws-profile", "aws.aws_profile", initAwsProfile},
{"docker", "docker.enabled", initDocker},
{"backend", "terraform.backend", initBackend},
{"vm-cpu", "vm.cpu", initCpu},
{"vm-disk", "vm.disk", initDisk},
{"vm-memory", "vm.memory", initMemory},
{"vm-arch", "vm.arch", initArch},
{"tools-manager", "toolsManager", initToolsManager},
{"git-livereload", "git.livereload.enabled", initGitLivereload},
{"blueprint", "blueprint", initBlueprint},
{"endpoint", "cluster.endpoint", initEndpoint},
{"platform", "cluster.platform", initPlatform},
}

for _, config := range configurations {
Expand All @@ -134,6 +128,25 @@ var initCmd = &cobra.Command{
}
}

// Process all set flags after other flags
for _, setFlag := range initSetFlags {
parts := strings.SplitN(setFlag, "=", 2)
if len(parts) != 2 {
return fmt.Errorf("Invalid format for --set flag. Expected key=value")
}
key, value := parts[0], parts[1]
if err := configHandler.SetContextValue(key, value); err != nil {
return fmt.Errorf("Error setting config override %s: %w", key, err)
}
}

// Set the vm driver only if it's configured and not overridden by --set flag
if vmDriverConfig != "" && configHandler.GetString("vm.driver") == "" {
if err := configHandler.SetContextValue("vm.driver", vmDriverConfig); err != nil {
return fmt.Errorf("Error setting vm driver: %w", err)
}
}

// Determine the cli configuration path
projectRoot, err := shell.GetProjectRoot()
if err != nil {
Expand Down Expand Up @@ -191,18 +204,19 @@ var initCmd = &cobra.Command{
}

func init() {
initCmd.Flags().StringVar(&backend, "backend", "", "Specify the terraform backend to use")
initCmd.Flags().StringVar(&awsProfile, "aws-profile", "", "Specify the AWS profile to use")
initCmd.Flags().StringVar(&awsEndpointURL, "aws-endpoint-url", "", "Specify the AWS endpoint URL to use")
initCmd.Flags().StringVar(&vmDriver, "vm-driver", "", "Specify the VM driver. Only Colima is supported for now.")
initCmd.Flags().IntVar(&cpu, "vm-cpu", 0, "Specify the number of CPUs for Colima")
initCmd.Flags().IntVar(&disk, "vm-disk", 0, "Specify the disk size for Colima")
initCmd.Flags().IntVar(&memory, "vm-memory", 0, "Specify the memory size for Colima")
initCmd.Flags().StringVar(&arch, "vm-arch", "", "Specify the architecture for Colima")
initCmd.Flags().BoolVar(&docker, "docker", false, "Enable Docker")
initCmd.Flags().BoolVar(&gitLivereload, "git-livereload", false, "Enable Git Livereload")
initCmd.Flags().StringVar(&platform, "platform", "", "Specify the platform to use [local|metal]")
initCmd.Flags().StringVar(&blueprint, "blueprint", "", "Specify the blueprint to use")
initCmd.Flags().StringVar(&endpoint, "endpoint", "", "Specify the kubernetes API endpoint")
initCmd.Flags().StringVar(&initBackend, "backend", "", "Specify the terraform backend to use")
initCmd.Flags().StringVar(&initAwsProfile, "aws-profile", "", "Specify the AWS profile to use")
initCmd.Flags().StringVar(&initAwsEndpointURL, "aws-endpoint-url", "", "Specify the AWS endpoint URL to use")
initCmd.Flags().StringVar(&initVmDriver, "vm-driver", "", "Specify the VM driver. Only Colima is supported for now.")
initCmd.Flags().IntVar(&initCpu, "vm-cpu", 0, "Specify the number of CPUs for Colima")
initCmd.Flags().IntVar(&initDisk, "vm-disk", 0, "Specify the disk size for Colima")
initCmd.Flags().IntVar(&initMemory, "vm-memory", 0, "Specify the memory size for Colima")
initCmd.Flags().StringVar(&initArch, "vm-arch", "", "Specify the architecture for Colima")
initCmd.Flags().BoolVar(&initDocker, "docker", false, "Enable Docker")
initCmd.Flags().BoolVar(&initGitLivereload, "git-livereload", false, "Enable Git Livereload")
initCmd.Flags().StringVar(&initPlatform, "platform", "", "Specify the platform to use [local|metal]")
initCmd.Flags().StringVar(&initBlueprint, "blueprint", "", "Specify the blueprint to use")
initCmd.Flags().StringVar(&initEndpoint, "endpoint", "", "Specify the kubernetes API endpoint")
initCmd.Flags().StringSliceVar(&initSetFlags, "set", []string{}, "Override configuration values. Example: --set dns.enabled=false --set cluster.endpoint=https://localhost:6443")
rootCmd.AddCommand(initCmd)
}
200 changes: 193 additions & 7 deletions cmd/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ func setupInitMocks(t *testing.T, opts *SetupOptions) *Mocks {
mocks.Controller.ResolveShellFunc = func() shell.Shell {
return mockShell
}
mocks.Controller.ResolveConfigHandlerFunc = func() config.ConfigHandler {
return mocks.ConfigHandler
}
mocks.Controller.SetEnvironmentVariablesFunc = func() error {
return nil
}
Expand Down Expand Up @@ -197,7 +200,7 @@ func TestInitCmd(t *testing.T) {
mockConfigHandler.SetDefaultFunc = func(config v1alpha1.Context) error {
return nil
}
mockConfigHandler.SetContextValueFunc = func(key string, value interface{}) error {
mockConfigHandler.SetContextValueFunc = func(key string, value any) error {
return nil
}
mockConfigHandler.SaveConfigFunc = func(path string) error {
Expand Down Expand Up @@ -244,7 +247,7 @@ func TestInitCmd(t *testing.T) {
mockConfigHandler.SetDefaultFunc = func(config v1alpha1.Context) error {
return nil
}
mockConfigHandler.SetContextValueFunc = func(key string, value interface{}) error {
mockConfigHandler.SetContextValueFunc = func(key string, value any) error {
return nil
}
mockConfigHandler.SaveConfigFunc = func(path string) error {
Expand Down Expand Up @@ -516,26 +519,44 @@ func TestInitCmd(t *testing.T) {
})

t.Run("SetVMDriverError", func(t *testing.T) {
// Create a mock config handler that returns an error for vm.driver
mockConfigHandler := config.NewMockConfigHandler()
mockConfigHandler.SetContextValueFunc = func(key string, value interface{}) error {
if key == "vm.driver" {
return fmt.Errorf("failed to set vm driver")
}
return nil
}
opts := &SetupOptions{
ConfigHandler: mockConfigHandler,
mockConfigHandler.GetContextFunc = func() string {
return "local"
}
mocks := setupInitMocks(t, opts)
mockConfigHandler.GetStringFunc = func(key string, defaultValue ...string) string {
return ""
}
mockConfigHandler.SetDefaultFunc = func(config v1alpha1.Context) error {
return nil
}

// Given a set of mocks with the error-returning config handler
mocks := setupInitMocks(t, &SetupOptions{
ConfigHandler: mockConfigHandler,
})

// Set up command arguments
rootCmd.SetArgs([]string{"init", "--vm-driver", "docker-desktop"})

// When executing the command
err := Execute(mocks.Controller)

// Then error should occur
if err == nil {
t.Error("Expected error, got nil")
}
if err != nil && !strings.Contains(err.Error(), "failed to set vm driver") {
t.Errorf("Expected error containing 'failed to set vm driver', got: %v", err)

// And error should contain vm driver error message
expectedError := "Error setting vm driver: failed to set vm driver"
if err.Error() != expectedError {
t.Errorf("Expected error %q, got %q", expectedError, err.Error())
}
})

Expand Down Expand Up @@ -616,4 +637,169 @@ func TestInitCmd(t *testing.T) {
t.Errorf("Expected VM driver to be empty, got '%s'", vmDriver)
}
})

t.Run("SetFlagSuccess", func(t *testing.T) {
// Given a set of mocks with proper configuration
mocks := setupInitMocks(t, nil)

// Set up command arguments with multiple --set flags
rootCmd.SetArgs([]string{"init", "--set", "dns.enabled=false", "--set", "cluster.endpoint=https://localhost:6443"})

// When executing the command
err := Execute(mocks.Controller)

// Then no error should occur
if err != nil {
t.Errorf("Expected success, got error: %v", err)
}

// And values should be set correctly
expectedValues := map[string]any{
"dns.enabled": "false",
"cluster.endpoint": "https://localhost:6443",
}
for key, expected := range expectedValues {
actual := mocks.ConfigHandler.GetString(key)
if actual != expected {
t.Errorf("Expected %s=%v, got %v", key, expected, actual)
}
}
})

t.Run("SetFlagInvalidFormat", func(t *testing.T) {
// Given a set of mocks with proper configuration
mocks := setupInitMocks(t, nil)

// Set up command arguments with invalid --set flag format
rootCmd.SetArgs([]string{"init", "--set", "invalid-format"})

// When executing the command
err := Execute(mocks.Controller)

// Then error should occur
if err == nil {
t.Error("Expected error, got nil")
}

// And error should contain invalid format message
expectedError := "Invalid format for --set flag. Expected key=value"
if !strings.Contains(err.Error(), expectedError) {
t.Errorf("Expected error containing %q, got %q", expectedError, err.Error())
}
})

t.Run("SetFlagError", func(t *testing.T) {
// Create a mock config handler that returns an error
mockConfigHandler := config.NewMockConfigHandler()
mockConfigHandler.SetContextValueFunc = func(key string, value interface{}) error {
return fmt.Errorf("failed to set config value for %s", key)
}
mockConfigHandler.GetContextFunc = func() string {
return "local"
}
mockConfigHandler.GetStringFunc = func(key string, defaultValue ...string) string {
return ""
}
mockConfigHandler.SetDefaultFunc = func(config v1alpha1.Context) error {
return nil
}

// Given a set of mocks with the error-returning config handler
mocks := setupInitMocks(t, &SetupOptions{
ConfigHandler: mockConfigHandler,
})

// Reset and reinitialize flags
rootCmd.ResetFlags()
initCmd.ResetFlags()
initCmd.Flags().StringSliceVar(&initSetFlags, "set", []string{}, "Override configuration values")
initCmd.Flags().StringVar(&initVmDriver, "vm-driver", "", "Specify the VM driver")

// Set up command arguments
rootCmd.SetArgs([]string{"init", "--set", "test.key=value"})

// When executing the command
err := Execute(mocks.Controller)

// Then error should occur
if err == nil {
t.Error("Expected error, got nil")
}

// And error should contain set error message
expectedError := "Error setting config override test.key: failed to set config value for test.key"
if err.Error() != expectedError {
t.Errorf("Expected error %q, got %q", expectedError, err.Error())
}
})

t.Run("VMDriverSelectionWithSetFlag", func(t *testing.T) {
// Given a set of mocks with proper configuration
mocks := setupInitMocks(t, nil)

// Reset and reinitialize flags
rootCmd.ResetFlags()
initCmd.ResetFlags()
initCmd.Flags().StringSliceVar(&initSetFlags, "set", []string{}, "Override configuration values")
initCmd.Flags().StringVar(&initVmDriver, "vm-driver", "", "Specify the VM driver")

// Set up command arguments to override vm.driver
rootCmd.SetArgs([]string{"init", "--set", "vm.driver=custom-driver"})

// When executing the command
err := Execute(mocks.Controller)

// Then no error should occur
if err != nil {
t.Errorf("Expected success, got error: %v", err)
}

// And vm.driver should be set to custom value
actual := mocks.ConfigHandler.GetString("vm.driver")
if actual != "custom-driver" {
t.Errorf("Expected vm.driver=custom-driver, got %v", actual)
}
})

t.Run("SetFlagWithExistingConfig", func(t *testing.T) {
// Create a mock config handler with proper context
mockConfigHandler := config.NewMockConfigHandler()
mockConfigHandler.GetContextFunc = func() string {
return "local"
}
mockConfigHandler.GetStringFunc = func(key string, defaultValue ...string) string {
if key == "new.key" {
return "new-value"
}
return ""
}

// Given a set of mocks with the mock config handler
mocks := setupInitMocks(t, &SetupOptions{
ConfigHandler: mockConfigHandler,
})

// Reset and reinitialize flags
rootCmd.ResetFlags()
initCmd.ResetFlags()
initCmd.Flags().StringSliceVar(&initSetFlags, "set", []string{}, "Override configuration values")
initCmd.Flags().StringVar(&initVmDriver, "vm-driver", "", "Specify the VM driver")

// Set up command arguments
rootCmd.SetArgs([]string{"init", "--set", "new.key=new-value"})

// When executing the command
err := Execute(mocks.Controller)

// Then no error should occur
if err != nil {
t.Errorf("Expected success, got error: %v", err)
}

// And new value should be set correctly
actual := mockConfigHandler.GetString("new.key")
if actual != "new-value" {
t.Errorf("Expected new.key=new-value, got %v", actual)
}
})
}
Loading
Loading