diff --git a/cmd/run.go b/cmd/run.go index 6feaf20b..29b06d37 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -20,6 +20,7 @@ import ( "os" "path/filepath" "runtime" + "slices" "strconv" "strings" "time" @@ -27,6 +28,7 @@ import ( "golang.org/x/mod/semver" "github.com/spf13/cobra" + "github.com/spf13/pflag" "github.com/spf13/viper" daprRuntime "github.com/dapr/dapr/pkg/runtime" @@ -78,6 +80,15 @@ const ( runtimeWaitTimeoutInSeconds = 60 ) +// Flags that are compatible with --run-file +var runFileCompatibleFlags = []string{ + "kubernetes", + "help", + "version", + "runtime-path", + "log-as-json", +} + var RunCmd = &cobra.Command{ Use: "run", Short: "Run Dapr and (optionally) your application side by side. Supported platforms: Self-hosted", @@ -128,6 +139,14 @@ dapr run --run-file /path/to/directory -k }, Run: func(cmd *cobra.Command, args []string) { if len(runFilePath) > 0 { + // Check for incompatible flags + incompatibleFlags := detectIncompatibleFlags(cmd) + if len(incompatibleFlags) > 0 { + // Print warning message about incompatible flags + warningMsg := "The following flags are ignored when using --run-file and should be configured in the run file instead: " + strings.Join(incompatibleFlags, ", ") + print.WarningStatusEvent(os.Stdout, warningMsg) + } + runConfigFilePath, err := getRunFilePath(runFilePath) if err != nil { print.FailureStatusEvent(os.Stderr, "Failed to get run file path: %v", err) @@ -1061,3 +1080,26 @@ func getRunFilePath(path string) (string, error) { } return path, nil } + +// getConflictingFlags checks if any flags are set other than the ones passed in the excludedFlags slice. +// Used for logic or notifications when any of the flags are conflicting and should not be used together. +func getConflictingFlags(cmd *cobra.Command, excludedFlags ...string) []string { + var conflictingFlags []string + cmd.Flags().Visit(func(f *pflag.Flag) { + if !slices.Contains(excludedFlags, f.Name) { + conflictingFlags = append(conflictingFlags, f.Name) + } + }) + return conflictingFlags +} + +// detectIncompatibleFlags checks if any incompatible flags are used with --run-file +// and returns a slice of the flag names that were used +func detectIncompatibleFlags(cmd *cobra.Command) []string { + if runFilePath == "" { + return nil // No run file specified, so no incompatibilities + } + + // Get all flags that are not in the compatible list + return getConflictingFlags(cmd, append(runFileCompatibleFlags, "run-file")...) +} diff --git a/cmd/run_test.go b/cmd/run_test.go index 9403a718..5ac0796f 100644 --- a/cmd/run_test.go +++ b/cmd/run_test.go @@ -3,6 +3,7 @@ package cmd import ( "testing" + "github.com/spf13/cobra" "github.com/stretchr/testify/assert" ) @@ -17,3 +18,61 @@ func TestValidateSchedulerHostAddress(t *testing.T) { assert.Equal(t, "localhost:50006", address) }) } + +func TestDetectIncompatibleFlags(t *testing.T) { + // Setup a temporary run file path to trigger the incompatible flag check + originalRunFilePath := runFilePath + runFilePath = "some/path" + defer func() { + // Restore the original runFilePath + runFilePath = originalRunFilePath + }() + + t.Run("detect incompatible flags", func(t *testing.T) { + // Create a test command with flags + cmd := &cobra.Command{Use: "test"} + cmd.Flags().String("app-id", "", "") + cmd.Flags().String("dapr-http-port", "", "") + cmd.Flags().String("kubernetes", "", "") // Compatible flag + cmd.Flags().String("runtime-path", "", "") // Compatible flag + cmd.Flags().String("log-as-json", "", "") // Compatible flag + + // Mark flags as changed + cmd.Flags().Set("app-id", "myapp") + cmd.Flags().Set("dapr-http-port", "3500") + cmd.Flags().Set("kubernetes", "true") + cmd.Flags().Set("runtime-path", "/path/to/runtime") + cmd.Flags().Set("log-as-json", "true") + + // Test detection + incompatibleFlags := detectIncompatibleFlags(cmd) + assert.Len(t, incompatibleFlags, 2) + assert.Contains(t, incompatibleFlags, "app-id") + assert.Contains(t, incompatibleFlags, "dapr-http-port") + assert.NotContains(t, incompatibleFlags, "kubernetes") + assert.NotContains(t, incompatibleFlags, "runtime-path") + assert.NotContains(t, incompatibleFlags, "log-as-json") + }) + + t.Run("no incompatible flags when run file not specified", func(t *testing.T) { + // Create a test command with flags + cmd := &cobra.Command{Use: "test"} + cmd.Flags().String("app-id", "", "") + cmd.Flags().String("dapr-http-port", "", "") + + // Mark flags as changed + cmd.Flags().Set("app-id", "myapp") + cmd.Flags().Set("dapr-http-port", "3500") + + // Temporarily clear runFilePath + originalRunFilePath := runFilePath + runFilePath = "" + defer func() { + runFilePath = originalRunFilePath + }() + + // Test detection + incompatibleFlags := detectIncompatibleFlags(cmd) + assert.Nil(t, incompatibleFlags) + }) +} diff --git a/go.mod b/go.mod index ca2ad965..343f95cc 100644 --- a/go.mod +++ b/go.mod @@ -24,6 +24,7 @@ require ( github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c github.com/shirou/gopsutil v3.21.11+incompatible github.com/spf13/cobra v1.8.1 + github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.13.0 github.com/stretchr/testify v1.10.0 golang.org/x/mod v0.22.0 @@ -186,7 +187,6 @@ require ( github.com/spf13/afero v1.8.2 // indirect github.com/spf13/cast v1.7.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect github.com/spiffe/go-spiffe/v2 v2.1.7 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect github.com/subosito/gotenv v1.4.1 // indirect