diff --git a/cmd/installer/cli/install.go b/cmd/installer/cli/install.go index 06f0e9773..7268812ca 100644 --- a/cmd/installer/cli/install.go +++ b/cmd/installer/cli/install.go @@ -230,6 +230,11 @@ func addManagerExperienceFlags(cmd *cobra.Command, flags *InstallCmdFlags) error } func preRunInstall(cmd *cobra.Command, flags *InstallCmdFlags, rc runtimeconfig.RuntimeConfig) error { + // Check for undocumented environment variable if flag not explicitly set + if !cmd.Flags().Changed("skip-host-preflights") && os.Getenv("SKIP_HOST_PREFLIGHTS") != "" { + flags.skipHostPreflights = true + } + if os.Getuid() != 0 { return fmt.Errorf("install command must be run as root") } diff --git a/cmd/installer/cli/install_test.go b/cmd/installer/cli/install_test.go index b63d79813..707860b87 100644 --- a/cmd/installer/cli/install_test.go +++ b/cmd/installer/cli/install_test.go @@ -14,7 +14,9 @@ import ( "github.com/replicatedhq/embedded-cluster/pkg/prompts" "github.com/replicatedhq/embedded-cluster/pkg/prompts/plain" "github.com/replicatedhq/embedded-cluster/pkg/release" + "github.com/replicatedhq/embedded-cluster/pkg/runtimeconfig" kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1" + "github.com/spf13/cobra" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -607,3 +609,91 @@ func Test_verifyProxyConfig(t *testing.T) { }) } } + +func Test_preRunInstall_SkipHostPreflightsEnvVar(t *testing.T) { + tests := []struct { + name string + envVarValue string + flagValue *bool // nil means not set, true/false means explicitly set + expectedSkipPreflights bool + }{ + { + name: "env var set, no flag", + envVarValue: "1", + flagValue: nil, + expectedSkipPreflights: true, + }, + { + name: "env var set, flag explicitly false (flag takes precedence)", + envVarValue: "1", + flagValue: boolPtr(false), + expectedSkipPreflights: false, + }, + { + name: "env var set, flag explicitly true", + envVarValue: "1", + flagValue: boolPtr(true), + expectedSkipPreflights: true, + }, + { + name: "env var not set, no flag", + envVarValue: "", + flagValue: nil, + expectedSkipPreflights: false, + }, + { + name: "env var not set, flag explicitly false", + envVarValue: "", + flagValue: boolPtr(false), + expectedSkipPreflights: false, + }, + { + name: "env var not set, flag explicitly true", + envVarValue: "", + flagValue: boolPtr(true), + expectedSkipPreflights: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Set up environment variable + if tt.envVarValue != "" { + t.Setenv("SKIP_HOST_PREFLIGHTS", tt.envVarValue) + } + + // Create a mock cobra command to simulate flag behavior + cmd := &cobra.Command{} + flags := &InstallCmdFlags{} + + // Add the flag to the command (similar to addInstallFlags) + cmd.Flags().BoolVar(&flags.skipHostPreflights, "skip-host-preflights", false, "Skip host preflight checks") + + // Set the flag if explicitly provided in test + if tt.flagValue != nil { + err := cmd.Flags().Set("skip-host-preflights", fmt.Sprintf("%t", *tt.flagValue)) + require.NoError(t, err) + } + + // Create a minimal runtime config for the test + rc := runtimeconfig.New(nil) + + // Call preRunInstall (this would normally require root, but we're just testing the flag logic) + // We expect this to fail due to non-root execution, but we can check the flag value before it fails + err := preRunInstall(cmd, flags, rc) + + // The function will fail due to non-root check, but we can verify the flag was set correctly + // by checking the flag value before the root check fails + assert.Equal(t, tt.expectedSkipPreflights, flags.skipHostPreflights) + + // We expect an error due to non-root execution + assert.Error(t, err) + assert.Contains(t, err.Error(), "install command must be run as root") + }) + } +} + +// Helper function to create bool pointer +func boolPtr(b bool) *bool { + return &b +}