From 883180f13aa8678227fcfa67ae967049fef454b2 Mon Sep 17 00:00:00 2001 From: Albert Callarisa Date: Wed, 9 Jul 2025 14:22:59 +0200 Subject: [PATCH 1/3] feat: Allow configuring the scheduler advertised address on init Signed-off-by: Albert Callarisa --- README.md | 19 +++++++++++---- cmd/init.go | 4 +++- pkg/standalone/standalone.go | 6 +++-- pkg/standalone/standalone_test.go | 2 +- tests/e2e/standalone/init_test.go | 39 +++++++++++++++++++++++++++++++ 5 files changed, 62 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index b5670956c..35f9ee898 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ Runtime version: v1.0.0 #### Install with mariner images -You can install Dapr Runtime using mariner images using the `--image-variant` flag. +You can install Dapr Runtime using mariner images using the `--image-variant` flag. ```bash # Installing Dapr with Mariner images @@ -158,6 +158,17 @@ You can install Dapr runtime by pulling docker images from a given private regis dapr init --image-registry example.io/ ``` +#### Install with a custom scheduler host + +You can install Dapr runtime with a custom scheduler host by using `--scheduler-host` flag. + +```bash +dapr init --scheduler-host 192.168.42.42 +``` + +> Note: The default host is `localhost`. + + #### Install in airgap environment You can install Dapr runtime in airgap (offline) environment using a pre-downloaded [installer bundle](https://github.com/dapr/installer-bundle/releases). You need to download the archived bundle for your OS beforehand (e.g., daprbundle_linux_amd64.tar.gz,) and unpack it. Thereafter use the local Dapr CLI binary in the bundle with `--from-dir` flag in the init command to point to the extracted bundle location to initialize Dapr. @@ -180,7 +191,7 @@ docker run --name "dapr_zipkin" --restart always -d -p 9411:9411 openzipkin/zipk docker run --name "dapr_redis" --restart always -d -p 6379:6379 redis ``` -Alternatively to the above, you can also have slim installation as well to install dapr without running any Docker containers in airgap mode. +Alternatively to the above, you can also have slim installation as well to install dapr without running any Docker containers in airgap mode. ```bash ./dapr init --slim --from-dir . @@ -297,7 +308,7 @@ Output should look like as follows: All available [Helm Chart values](https://github.com/dapr/dapr/tree/master/charts/dapr#configuration) can be set by using the `--set` flag: ```bash -dapr init -k --set global.tag=1.0.0 --set dapr_operator.logLevel=error +dapr init -k --set global.tag=1.0.0 --set dapr_operator.logLevel=error ``` #### Installing to a custom namespace @@ -363,7 +374,7 @@ The example above shows how to upgrade from your current version to version `1.0 All available [Helm Chart values](https://github.com/dapr/dapr/tree/master/charts/dapr#configuration) can be set by using the `--set` flag: ```bash -dapr upgrade -k --runtime-version=1.0.0 --set global.tag=my-tag --set dapr_operator.logLevel=error +dapr upgrade -k --runtime-version=1.0.0 --set global.tag=my-tag --set dapr_operator.logLevel=error ``` *Note: do not use the `dapr upgrade` command if you're upgrading from 0.x versions of Dapr* diff --git a/cmd/init.go b/cmd/init.go index e3b5c0d6e..b38e69699 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -46,6 +46,7 @@ var ( containerRuntime string imageVariant string schedulerVolume string + schedulerHost string ) var InitCmd = &cobra.Command{ @@ -171,7 +172,7 @@ dapr init --runtime-path print.FailureStatusEvent(os.Stdout, "Invalid container runtime. Supported values are docker and podman.") os.Exit(1) } - err := standalone.Init(runtimeVersion, dashboardVersion, dockerNetwork, slimMode, imageRegistryURI, fromDir, containerRuntime, imageVariant, daprRuntimePath, &schedulerVolume) + err := standalone.Init(runtimeVersion, dashboardVersion, dockerNetwork, slimMode, imageRegistryURI, fromDir, containerRuntime, imageVariant, daprRuntimePath, &schedulerVolume, schedulerHost) if err != nil { print.FailureStatusEvent(os.Stderr, err.Error()) os.Exit(1) @@ -221,6 +222,7 @@ func init() { InitCmd.Flags().StringVarP(&fromDir, "from-dir", "", "", "Use Dapr artifacts from local directory for self-hosted installation") InitCmd.Flags().StringVarP(&imageVariant, "image-variant", "", "", "The image variant to use for the Dapr runtime, for example: mariner") InitCmd.Flags().StringVarP(&schedulerVolume, "scheduler-volume", "", "dapr_scheduler", "Self-hosted only. Specify a volume for the scheduler service data directory.") + InitCmd.Flags().StringVarP(&schedulerHost, "scheduler-host", "", "localhost", "Self-hosted only. Specify the host address for the scheduler service. If not specified, it uses localhost.") InitCmd.Flags().BoolP("help", "h", false, "Print this help message") InitCmd.Flags().StringArrayVar(&values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") InitCmd.Flags().String("image-registry", "", "Custom/private docker image repository URL") diff --git a/pkg/standalone/standalone.go b/pkg/standalone/standalone.go index 239188f7f..e554e65fc 100644 --- a/pkg/standalone/standalone.go +++ b/pkg/standalone/standalone.go @@ -144,6 +144,7 @@ type initInfo struct { containerRuntime string imageVariant string schedulerVolume *string + schedulerHost string } type daprImageInfo struct { @@ -185,7 +186,7 @@ func isSchedulerIncluded(runtimeVersion string) (bool, error) { } // Init installs Dapr on a local machine using the supplied runtimeVersion. -func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMode bool, imageRegistryURL string, fromDir string, containerRuntime string, imageVariant string, daprInstallPath string, schedulerVolume *string) error { +func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMode bool, imageRegistryURL string, fromDir string, containerRuntime string, imageVariant string, daprInstallPath string, schedulerVolume *string, schedulerHost string) error { var err error var bundleDet bundleDetails containerRuntime = strings.TrimSpace(containerRuntime) @@ -307,6 +308,7 @@ func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMod containerRuntime: containerRuntime, imageVariant: imageVariant, schedulerVolume: schedulerVolume, + schedulerHost: schedulerHost, } for _, step := range initSteps { // Run init on the configurations and containers. @@ -684,7 +686,7 @@ func runSchedulerService(wg *sync.WaitGroup, errorChan chan<- error, info initIn } if schedulerOverrideHostPort(info) { - args = append(args, fmt.Sprintf("--override-broadcast-host-port=localhost:%v", osPort)) + args = append(args, fmt.Sprintf("--override-broadcast-host-port=%s:%v", info.schedulerHost, osPort)) } _, err = utils.RunCmdAndWait(runtimeCmd, args...) diff --git a/pkg/standalone/standalone_test.go b/pkg/standalone/standalone_test.go index 98b8a7cd5..c8dd7445f 100644 --- a/pkg/standalone/standalone_test.go +++ b/pkg/standalone/standalone_test.go @@ -325,7 +325,7 @@ func TestInitLogActualContainerRuntimeName(t *testing.T) { t.Skip("Skipping test as container runtime is available") } - err := Init(latestVersion, latestVersion, "", false, "", "", test.containerRuntime, "", "", nil) + err := Init(latestVersion, latestVersion, "", false, "", "", test.containerRuntime, "", "", nil, "localhost") assert.Error(t, err) assert.Contains(t, err.Error(), test.containerRuntime) }) diff --git a/tests/e2e/standalone/init_test.go b/tests/e2e/standalone/init_test.go index 3a9d8cb9d..4db19f8d4 100644 --- a/tests/e2e/standalone/init_test.go +++ b/tests/e2e/standalone/init_test.go @@ -210,6 +210,26 @@ func TestStandaloneInit(t *testing.T) { verifyTCPLocalhost(t, schedulerPort) }) + t.Run("init with custom scheduler host", func(t *testing.T) { + if isSlimMode() { + t.Skip("Skipping scheduler host test because of slim installation") + } + + // Ensure a clean environment + must(t, cmdUninstall, "failed to uninstall Dapr") + + customHost := "192.168.42.42" + args := []string{ + "--scheduler-host", customHost, + } + output, err := cmdInit(args...) + t.Log(output) + require.NoError(t, err, "init failed") + assert.Contains(t, output, "Success! Dapr is up and running.") + + verifySchedulerHost(t, customHost) + }) + t.Run("init without runtime-version flag with mariner images", func(t *testing.T) { // Ensure a clean environment must(t, cmdUninstall, "failed to uninstall Dapr") @@ -440,3 +460,22 @@ func verifyTCPLocalhost(t *testing.T, port int) { } }, time.Second*10, time.Millisecond*10) } + +// verifySchedulerHost verifies that the scheduler container was started with the correct host. +func verifySchedulerHost(t *testing.T, expectedHost string) { + t.Helper() + + cli, err := dockerClient.NewClientWithOpts(dockerClient.FromEnv) + require.NoError(t, err) + + containerInfo, err := cli.ContainerInspect(context.Background(), "dapr_scheduler") + require.NoError(t, err) + + expectedPort := 50006 + if runtime.GOOS == "windows" { + expectedPort = 6060 + } + + expectedArg := "--override-broadcast-host-port=" + expectedHost + ":" + strconv.Itoa(expectedPort) + assert.Contains(t, containerInfo.Args, expectedArg, "Expected scheduler argument %s not found in container args: %v", expectedArg, containerInfo.Args) +} From 847ed81c98895fd7985751ef8d3f86c9ccf1d594 Mon Sep 17 00:00:00 2001 From: Albert Callarisa Date: Thu, 10 Jul 2025 07:30:39 +0200 Subject: [PATCH 2/3] Rename field to make it clearer Signed-off-by: Albert Callarisa --- README.md | 6 ++-- cmd/init.go | 46 ++++++++++++++----------- pkg/standalone/standalone.go | 56 +++++++++++++++++-------------- pkg/standalone/standalone_test.go | 3 +- tests/e2e/standalone/init_test.go | 17 ++++------ 5 files changed, 67 insertions(+), 61 deletions(-) diff --git a/README.md b/README.md index 35f9ee898..71d193a22 100644 --- a/README.md +++ b/README.md @@ -158,12 +158,12 @@ You can install Dapr runtime by pulling docker images from a given private regis dapr init --image-registry example.io/ ``` -#### Install with a custom scheduler host +#### Install with a custom scheduler host and port -You can install Dapr runtime with a custom scheduler host by using `--scheduler-host` flag. +You can install Dapr runtime with a custom scheduler host and port by using `--scheduler-override-broadcast-host-port` flag. ```bash -dapr init --scheduler-host 192.168.42.42 +dapr init --scheduler-override-broadcast-host-port 192.168.42.42:50006 ``` > Note: The default host is `localhost`. diff --git a/cmd/init.go b/cmd/init.go index b38e69699..cd9664fd3 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -29,24 +29,24 @@ import ( ) var ( - kubernetesMode bool - wait bool - timeout uint - slimMode bool - devMode bool - runtimeVersion string - dashboardVersion string - allNamespaces bool - initNamespace string - resourceNamespace string - enableMTLS bool - enableHA bool - values []string - fromDir string - containerRuntime string - imageVariant string - schedulerVolume string - schedulerHost string + kubernetesMode bool + wait bool + timeout uint + slimMode bool + devMode bool + runtimeVersion string + dashboardVersion string + allNamespaces bool + initNamespace string + resourceNamespace string + enableMTLS bool + enableHA bool + values []string + fromDir string + containerRuntime string + imageVariant string + schedulerVolume string + schedulerOverrideBroadcastHostPort string ) var InitCmd = &cobra.Command{ @@ -172,7 +172,13 @@ dapr init --runtime-path print.FailureStatusEvent(os.Stdout, "Invalid container runtime. Supported values are docker and podman.") os.Exit(1) } - err := standalone.Init(runtimeVersion, dashboardVersion, dockerNetwork, slimMode, imageRegistryURI, fromDir, containerRuntime, imageVariant, daprRuntimePath, &schedulerVolume, schedulerHost) + + schedulerHostPort := &schedulerOverrideBroadcastHostPort + if schedulerOverrideBroadcastHostPort == "" { + schedulerHostPort = nil + } + + err := standalone.Init(runtimeVersion, dashboardVersion, dockerNetwork, slimMode, imageRegistryURI, fromDir, containerRuntime, imageVariant, daprRuntimePath, &schedulerVolume, schedulerHostPort) if err != nil { print.FailureStatusEvent(os.Stderr, err.Error()) os.Exit(1) @@ -222,7 +228,7 @@ func init() { InitCmd.Flags().StringVarP(&fromDir, "from-dir", "", "", "Use Dapr artifacts from local directory for self-hosted installation") InitCmd.Flags().StringVarP(&imageVariant, "image-variant", "", "", "The image variant to use for the Dapr runtime, for example: mariner") InitCmd.Flags().StringVarP(&schedulerVolume, "scheduler-volume", "", "dapr_scheduler", "Self-hosted only. Specify a volume for the scheduler service data directory.") - InitCmd.Flags().StringVarP(&schedulerHost, "scheduler-host", "", "localhost", "Self-hosted only. Specify the host address for the scheduler service. If not specified, it uses localhost.") + InitCmd.Flags().StringVarP(&schedulerOverrideBroadcastHostPort, "scheduler-override-broadcast-host-port", "", "", "Self-hosted only. Specify the scheduler broadcast host and port, for example: 192.168.42.42:50006. If not specified, it uses localhost:50006 (6060 for Windows).") InitCmd.Flags().BoolP("help", "h", false, "Print this help message") InitCmd.Flags().StringArrayVar(&values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") InitCmd.Flags().String("image-registry", "", "Custom/private docker image repository URL") diff --git a/pkg/standalone/standalone.go b/pkg/standalone/standalone.go index e554e65fc..769c79d38 100644 --- a/pkg/standalone/standalone.go +++ b/pkg/standalone/standalone.go @@ -133,18 +133,18 @@ type componentMetadataItem struct { } type initInfo struct { - fromDir string - installDir string - bundleDet *bundleDetails - slimMode bool - runtimeVersion string - dashboardVersion string - dockerNetwork string - imageRegistryURL string - containerRuntime string - imageVariant string - schedulerVolume *string - schedulerHost string + fromDir string + installDir string + bundleDet *bundleDetails + slimMode bool + runtimeVersion string + dashboardVersion string + dockerNetwork string + imageRegistryURL string + containerRuntime string + imageVariant string + schedulerVolume *string + schedulerOverrideBroadcastHostPort *string } type daprImageInfo struct { @@ -186,7 +186,7 @@ func isSchedulerIncluded(runtimeVersion string) (bool, error) { } // Init installs Dapr on a local machine using the supplied runtimeVersion. -func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMode bool, imageRegistryURL string, fromDir string, containerRuntime string, imageVariant string, daprInstallPath string, schedulerVolume *string, schedulerHost string) error { +func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMode bool, imageRegistryURL string, fromDir string, containerRuntime string, imageVariant string, daprInstallPath string, schedulerVolume *string, schedulerOverrideBroadcastHostPort *string) error { var err error var bundleDet bundleDetails containerRuntime = strings.TrimSpace(containerRuntime) @@ -297,18 +297,18 @@ func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMod info := initInfo{ // values in bundleDet can be nil if fromDir is empty, so must be used in conjunction with fromDir. - bundleDet: &bundleDet, - fromDir: fromDir, - installDir: installDir, - slimMode: slimMode, - runtimeVersion: runtimeVersion, - dashboardVersion: dashboardVersion, - dockerNetwork: dockerNetwork, - imageRegistryURL: imageRegistryURL, - containerRuntime: containerRuntime, - imageVariant: imageVariant, - schedulerVolume: schedulerVolume, - schedulerHost: schedulerHost, + bundleDet: &bundleDet, + fromDir: fromDir, + installDir: installDir, + slimMode: slimMode, + runtimeVersion: runtimeVersion, + dashboardVersion: dashboardVersion, + dockerNetwork: dockerNetwork, + imageRegistryURL: imageRegistryURL, + containerRuntime: containerRuntime, + imageVariant: imageVariant, + schedulerVolume: schedulerVolume, + schedulerOverrideBroadcastHostPort: schedulerOverrideBroadcastHostPort, } for _, step := range initSteps { // Run init on the configurations and containers. @@ -686,7 +686,11 @@ func runSchedulerService(wg *sync.WaitGroup, errorChan chan<- error, info initIn } if schedulerOverrideHostPort(info) { - args = append(args, fmt.Sprintf("--override-broadcast-host-port=%s:%v", info.schedulerHost, osPort)) + if info.schedulerOverrideBroadcastHostPort != nil { + args = append(args, fmt.Sprintf("--override-broadcast-host-port=%s", *info.schedulerOverrideBroadcastHostPort)) + } else { + args = append(args, fmt.Sprintf("--override-broadcast-host-port=localhost:%v", osPort)) + } } _, err = utils.RunCmdAndWait(runtimeCmd, args...) diff --git a/pkg/standalone/standalone_test.go b/pkg/standalone/standalone_test.go index c8dd7445f..f44089da1 100644 --- a/pkg/standalone/standalone_test.go +++ b/pkg/standalone/standalone_test.go @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/dapr/cli/utils" + "github.com/dapr/kit/ptr" ) func TestStandaloneConfig(t *testing.T) { @@ -325,7 +326,7 @@ func TestInitLogActualContainerRuntimeName(t *testing.T) { t.Skip("Skipping test as container runtime is available") } - err := Init(latestVersion, latestVersion, "", false, "", "", test.containerRuntime, "", "", nil, "localhost") + err := Init(latestVersion, latestVersion, "", false, "", "", test.containerRuntime, "", "", nil, ptr.Of("localhost:50006")) assert.Error(t, err) assert.Contains(t, err.Error(), test.containerRuntime) }) diff --git a/tests/e2e/standalone/init_test.go b/tests/e2e/standalone/init_test.go index 4db19f8d4..c1ec0924a 100644 --- a/tests/e2e/standalone/init_test.go +++ b/tests/e2e/standalone/init_test.go @@ -218,16 +218,16 @@ func TestStandaloneInit(t *testing.T) { // Ensure a clean environment must(t, cmdUninstall, "failed to uninstall Dapr") - customHost := "192.168.42.42" + customBroadcastHostPort := "192.168.42.42:50006" args := []string{ - "--scheduler-host", customHost, + "--scheduler-override-broadcast-host-port", customBroadcastHostPort, } output, err := cmdInit(args...) t.Log(output) require.NoError(t, err, "init failed") assert.Contains(t, output, "Success! Dapr is up and running.") - verifySchedulerHost(t, customHost) + verifySchedulerBroadcastHostPort(t, customBroadcastHostPort) }) t.Run("init without runtime-version flag with mariner images", func(t *testing.T) { @@ -461,8 +461,8 @@ func verifyTCPLocalhost(t *testing.T, port int) { }, time.Second*10, time.Millisecond*10) } -// verifySchedulerHost verifies that the scheduler container was started with the correct host. -func verifySchedulerHost(t *testing.T, expectedHost string) { +// verifySchedulerBroadcastHostPort verifies that the scheduler container was started with the correct broadcast host and port. +func verifySchedulerBroadcastHostPort(t *testing.T, expectedBroadcastHostPort string) { t.Helper() cli, err := dockerClient.NewClientWithOpts(dockerClient.FromEnv) @@ -471,11 +471,6 @@ func verifySchedulerHost(t *testing.T, expectedHost string) { containerInfo, err := cli.ContainerInspect(context.Background(), "dapr_scheduler") require.NoError(t, err) - expectedPort := 50006 - if runtime.GOOS == "windows" { - expectedPort = 6060 - } - - expectedArg := "--override-broadcast-host-port=" + expectedHost + ":" + strconv.Itoa(expectedPort) + expectedArg := "--override-broadcast-host-port=" + expectedBroadcastHostPort assert.Contains(t, containerInfo.Args, expectedArg, "Expected scheduler argument %s not found in container args: %v", expectedArg, containerInfo.Args) } From d4731e507ab07e69e469ed39044d976d2307a5df Mon Sep 17 00:00:00 2001 From: Albert Callarisa Date: Thu, 10 Jul 2025 07:53:46 +0200 Subject: [PATCH 3/3] Replace SprintF with concatenation as per linter recommendation. Signed-off-by: Albert Callarisa --- pkg/standalone/standalone.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/standalone/standalone.go b/pkg/standalone/standalone.go index 769c79d38..bd4cb86f2 100644 --- a/pkg/standalone/standalone.go +++ b/pkg/standalone/standalone.go @@ -687,7 +687,7 @@ func runSchedulerService(wg *sync.WaitGroup, errorChan chan<- error, info initIn if schedulerOverrideHostPort(info) { if info.schedulerOverrideBroadcastHostPort != nil { - args = append(args, fmt.Sprintf("--override-broadcast-host-port=%s", *info.schedulerOverrideBroadcastHostPort)) + args = append(args, "--override-broadcast-host-port="+*info.schedulerOverrideBroadcastHostPort) } else { args = append(args, fmt.Sprintf("--override-broadcast-host-port=localhost:%v", osPort)) }