Skip to content

Commit 8a2f022

Browse files
authored
fix: allow explicit disable of placement with empty host (v1.16) (#1535)
* fix: allow explicit disable of placement with empty host fixes: dapr/dapr#9000 Signed-off-by: inishchith <[email protected]> * fix: treat whitespace-only placement/scheduler addresses as empty Signed-off-by: inishchith <[email protected]> * fix: move scheduler and placement flags to pointer-aware Signed-off-by: inishchith <[email protected]> --------- Signed-off-by: inishchith <[email protected]>
1 parent edb70cf commit 8a2f022

File tree

3 files changed

+163
-38
lines changed

3 files changed

+163
-38
lines changed

cmd/run.go

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -189,26 +189,42 @@ dapr run --run-file /path/to/directory -k
189189
}
190190

191191
sharedRunConfig := &standalone.SharedRunConfig{
192-
ConfigFile: configFile,
193-
EnableProfiling: enableProfiling,
194-
LogLevel: logLevel,
195-
MaxConcurrency: maxConcurrency,
196-
AppProtocol: protocol,
197-
PlacementHostAddr: viper.GetString("placement-host-address"),
198-
ComponentsPath: componentsPath,
199-
ResourcesPaths: resourcesPaths,
200-
AppSSL: appSSL,
201-
MaxRequestBodySize: maxRequestBodySize,
202-
HTTPReadBufferSize: readBufferSize,
203-
EnableAppHealth: enableAppHealth,
204-
AppHealthPath: appHealthPath,
205-
AppHealthInterval: appHealthInterval,
206-
AppHealthTimeout: appHealthTimeout,
207-
AppHealthThreshold: appHealthThreshold,
208-
EnableAPILogging: enableAPILogging,
209-
APIListenAddresses: apiListenAddresses,
210-
SchedulerHostAddress: schedulerHostAddress,
211-
DaprdInstallPath: daprRuntimePath,
192+
ConfigFile: configFile,
193+
EnableProfiling: enableProfiling,
194+
LogLevel: logLevel,
195+
MaxConcurrency: maxConcurrency,
196+
AppProtocol: protocol,
197+
ComponentsPath: componentsPath,
198+
ResourcesPaths: resourcesPaths,
199+
AppSSL: appSSL,
200+
MaxRequestBodySize: maxRequestBodySize,
201+
HTTPReadBufferSize: readBufferSize,
202+
EnableAppHealth: enableAppHealth,
203+
AppHealthPath: appHealthPath,
204+
AppHealthInterval: appHealthInterval,
205+
AppHealthTimeout: appHealthTimeout,
206+
AppHealthThreshold: appHealthThreshold,
207+
EnableAPILogging: enableAPILogging,
208+
APIListenAddresses: apiListenAddresses,
209+
DaprdInstallPath: daprRuntimePath,
210+
}
211+
212+
// placement-host-address flag handling: only set pointer if flag was explicitly changed
213+
if cmd.Flags().Changed("placement-host-address") {
214+
val := viper.GetString("placement-host-address")
215+
sharedRunConfig.PlacementHostAddr = &val // may be empty => disable
216+
}
217+
218+
// scheduler-host-address defaulting/handling
219+
if cmd.Flags().Changed("scheduler-host-address") {
220+
val := schedulerHostAddress
221+
sharedRunConfig.SchedulerHostAddress = &val // may be empty => disable
222+
} else {
223+
// Apply version-based defaulting used previously
224+
addr := validateSchedulerHostAddress(daprVer.RuntimeVersion, schedulerHostAddress)
225+
if addr != "" {
226+
sharedRunConfig.SchedulerHostAddress = &addr
227+
}
212228
}
213229
output, err := runExec.NewOutput(&standalone.RunConfig{
214230
AppID: appID,
@@ -487,8 +503,8 @@ func init() {
487503
// TODO: Remove below line once the flag is removed in the future releases.
488504
// By marking this as deprecated, the flag will be hidden from the help menu, but will continue to work. It will show a warning message when used.
489505
RunCmd.Flags().MarkDeprecated("components-path", "This flag is deprecated and will be removed in the future releases. Use \"resources-path\" flag instead")
490-
RunCmd.Flags().String("placement-host-address", "localhost", "The address of the placement service. Format is either <hostname> for default port or <hostname>:<port> for custom port")
491-
RunCmd.Flags().StringVarP(&schedulerHostAddress, "scheduler-host-address", "", "localhost", "The address of the scheduler service. Format is either <hostname> for default port or <hostname>:<port> for custom port")
506+
RunCmd.Flags().String("placement-host-address", "localhost", "The address of the placement service. Format is either <hostname> for default port or <hostname>:<port> for custom port. Set to an empty string to disable placement")
507+
RunCmd.Flags().StringVarP(&schedulerHostAddress, "scheduler-host-address", "", "localhost", "The address of the scheduler service. Format is either <hostname> for default port or <hostname>:<port> for custom port. Set to an empty string to disable scheduler")
492508
// TODO: Remove below flag once the flag is removed in runtime in future release.
493509
RunCmd.Flags().BoolVar(&appSSL, "app-ssl", false, "Enable https when Dapr invokes the application")
494510
RunCmd.Flags().MarkDeprecated("app-ssl", "This flag is deprecated and will be removed in the future releases. Use \"app-protocol\" flag with https or grpcs values instead")
@@ -529,7 +545,15 @@ func executeRun(runTemplateName, runFilePath string, apps []runfileconfig.App) (
529545
// Set defaults if zero value provided in config yaml.
530546
app.RunConfig.SetDefaultFromSchema()
531547

532-
app.RunConfig.SchedulerHostAddress = validateSchedulerHostAddress(daprVer.RuntimeVersion, app.RunConfig.SchedulerHostAddress)
548+
// Adjust scheduler host address defaults for run-file apps (pointer-aware)
549+
var schedIn string
550+
if app.RunConfig.SchedulerHostAddress != nil {
551+
schedIn = *app.RunConfig.SchedulerHostAddress
552+
}
553+
schedOut := validateSchedulerHostAddress(daprVer.RuntimeVersion, schedIn)
554+
if schedOut != "" {
555+
app.RunConfig.SchedulerHostAddress = &schedOut
556+
}
533557

534558
// Validate validates the configs and modifies the ports to free ports, appId etc.
535559
err := app.RunConfig.Validate()
@@ -1012,7 +1036,7 @@ func putAppProcessIDInMeta(runE *runExec.RunExec) {
10121036
func putAppCommandInMeta(runConfig standalone.RunConfig, runE *runExec.RunExec) {
10131037
appCommand := strings.Join(runConfig.Command, " ")
10141038
print.StatusEvent(runE.DaprCMD.OutputWriter, print.LogInfo, "Updating metadata for app command: %s", appCommand)
1015-
err := metadata.Put(runE.DaprHTTPPort, "appCommand", appCommand, runE.AppID, runConfig.UnixDomainSocket)
1039+
err := metadata.Put(runE.DaprHTTPPort, "appCommand", appCommand, runE.AppID, unixDomainSocket)
10161040
if err != nil {
10171041
print.StatusEvent(runE.DaprCMD.OutputWriter, print.LogWarning, "Could not update sidecar metadata for appCommand: %s", err.Error())
10181042
return

pkg/standalone/run.go

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ type SharedRunConfig struct {
7272
LogLevel string `arg:"log-level" annotation:"dapr.io.log-level" yaml:"logLevel"`
7373
MaxConcurrency int `arg:"app-max-concurrency" annotation:"dapr.io/app-max-concurrerncy" yaml:"appMaxConcurrency" default:"-1"`
7474
// Speicifcally omitted from annotations similar to config file path above.
75-
PlacementHostAddr string `arg:"placement-host-address" yaml:"placementHostAddress"`
75+
// Pointer string to distinguish omitted (nil) vs explicitly empty (disable) vs value provided
76+
PlacementHostAddr *string `arg:"placement-host-address" yaml:"placementHostAddress"`
7677
// Speicifcally omitted from annotations similar to config file path above.
7778
ComponentsPath string `arg:"components-path"` // Deprecated in run template file: use ResourcesPaths instead.
7879
// Speicifcally omitted from annotations similar to config file path above.
@@ -90,11 +91,12 @@ type SharedRunConfig struct {
9091
AppHealthThreshold int `arg:"app-health-threshold" annotation:"dapr.io/app-health-threshold" ifneq:"0" yaml:"appHealthThreshold"`
9192
EnableAPILogging bool `arg:"enable-api-logging" annotation:"dapr.io/enable-api-logging" yaml:"enableApiLogging"`
9293
// Specifically omitted from annotations see https://github.com/dapr/cli/issues/1324 .
93-
DaprdInstallPath string `yaml:"runtimePath"`
94-
Env map[string]string `yaml:"env"`
95-
DaprdLogDestination LogDestType `yaml:"daprdLogDestination"`
96-
AppLogDestination LogDestType `yaml:"appLogDestination"`
97-
SchedulerHostAddress string `arg:"scheduler-host-address" yaml:"schedulerHostAddress"`
94+
DaprdInstallPath string `yaml:"runtimePath"`
95+
Env map[string]string `yaml:"env"`
96+
DaprdLogDestination LogDestType `yaml:"daprdLogDestination"`
97+
AppLogDestination LogDestType `yaml:"appLogDestination"`
98+
// Pointer string to distinguish omitted (nil) vs explicitly empty (disable) vs value provided
99+
SchedulerHostAddress *string `arg:"scheduler-host-address" yaml:"schedulerHostAddress"`
98100
}
99101

100102
func (meta *DaprMeta) newAppID() string {
@@ -125,9 +127,22 @@ func (config *RunConfig) validateResourcesPaths() error {
125127
}
126128

127129
func (config *RunConfig) validatePlacementHostAddr() error {
128-
placementHostAddr := config.PlacementHostAddr
130+
// nil => default localhost:port; empty => disable; non-empty => ensure port
131+
if config.PlacementHostAddr == nil {
132+
addr := "localhost"
133+
if runtime.GOOS == daprWindowsOS {
134+
addr += ":6050"
135+
} else {
136+
addr += ":50005"
137+
}
138+
config.PlacementHostAddr = &addr
139+
return nil
140+
}
141+
placementHostAddr := strings.TrimSpace(*config.PlacementHostAddr)
129142
if len(placementHostAddr) == 0 {
130-
placementHostAddr = "localhost"
143+
empty := ""
144+
config.PlacementHostAddr = &empty
145+
return nil
131146
}
132147
if indx := strings.Index(placementHostAddr, ":"); indx == -1 {
133148
if runtime.GOOS == daprWindowsOS {
@@ -136,26 +151,29 @@ func (config *RunConfig) validatePlacementHostAddr() error {
136151
placementHostAddr += ":50005"
137152
}
138153
}
139-
config.PlacementHostAddr = placementHostAddr
154+
config.PlacementHostAddr = &placementHostAddr
140155
return nil
141156
}
142157

143158
func (config *RunConfig) validateSchedulerHostAddr() error {
144-
schedulerHostAddr := config.SchedulerHostAddress
159+
// nil => leave as-is (set later based on version), empty => disable; non-empty => ensure port
160+
if config.SchedulerHostAddress == nil {
161+
return nil
162+
}
163+
schedulerHostAddr := strings.TrimSpace(*config.SchedulerHostAddress)
145164
if len(schedulerHostAddr) == 0 {
165+
empty := ""
166+
config.SchedulerHostAddress = &empty
146167
return nil
147168
}
148-
149169
if indx := strings.Index(schedulerHostAddr, ":"); indx == -1 {
150170
if runtime.GOOS == daprWindowsOS {
151171
schedulerHostAddr += ":6060"
152172
} else {
153173
schedulerHostAddr += ":50006"
154174
}
155175
}
156-
157-
config.SchedulerHostAddress = schedulerHostAddr
158-
176+
config.SchedulerHostAddress = &schedulerHostAddr
159177
return nil
160178
}
161179

@@ -405,6 +423,13 @@ func getArgsFromSchema(schema reflect.Value, args []string) []string {
405423
args = append(args, key, val)
406424
}
407425
}
426+
case *string:
427+
if vType != nil {
428+
val := strings.TrimSpace(*vType)
429+
if len(val) != 0 && (!hasIfneq || val != ifneq) {
430+
args = append(args, key, val)
431+
}
432+
}
408433
default:
409434
value := fmt.Sprintf("%v", reflect.ValueOf(valueField))
410435
if len(value) != 0 && (!hasIfneq || value != ifneq) {

pkg/standalone/run_test.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,16 @@ limitations under the License.
1414
package standalone
1515

1616
import (
17+
"runtime"
1718
"sort"
19+
"strings"
1820
"testing"
1921

2022
"github.com/stretchr/testify/assert"
2123
)
2224

25+
func strPtr(s string) *string { return &s }
26+
2327
func TestGetEnv(t *testing.T) {
2428
config := &RunConfig{
2529
SharedRunConfig: SharedRunConfig{},
@@ -139,3 +143,75 @@ func TestGetEnv(t *testing.T) {
139143
assert.Equal(t, expect, got)
140144
})
141145
}
146+
147+
func TestValidatePlacementHostAddr(t *testing.T) {
148+
t.Run("empty disables placement", func(t *testing.T) {
149+
cfg := &RunConfig{SharedRunConfig: SharedRunConfig{PlacementHostAddr: strPtr("")}}
150+
err := cfg.validatePlacementHostAddr()
151+
assert.NoError(t, err)
152+
assert.NotNil(t, cfg.PlacementHostAddr)
153+
assert.Equal(t, "", *cfg.PlacementHostAddr)
154+
})
155+
156+
t.Run("whitespace disables placement", func(t *testing.T) {
157+
cfg := &RunConfig{SharedRunConfig: SharedRunConfig{PlacementHostAddr: strPtr(" ")}}
158+
err := cfg.validatePlacementHostAddr()
159+
assert.NoError(t, err)
160+
assert.NotNil(t, cfg.PlacementHostAddr)
161+
assert.Equal(t, "", *cfg.PlacementHostAddr)
162+
})
163+
164+
t.Run("default port appended when hostname provided without port", func(t *testing.T) {
165+
cfg := &RunConfig{SharedRunConfig: SharedRunConfig{PlacementHostAddr: strPtr("localhost")}}
166+
err := cfg.validatePlacementHostAddr()
167+
assert.NoError(t, err)
168+
if runtime.GOOS == daprWindowsOS {
169+
assert.True(t, strings.HasSuffix(*cfg.PlacementHostAddr, ":6050"))
170+
} else {
171+
assert.True(t, strings.HasSuffix(*cfg.PlacementHostAddr, ":50005"))
172+
}
173+
})
174+
175+
t.Run("custom port preserved when provided", func(t *testing.T) {
176+
cfg := &RunConfig{SharedRunConfig: SharedRunConfig{PlacementHostAddr: strPtr("1.2.3.4:12345")}}
177+
err := cfg.validatePlacementHostAddr()
178+
assert.NoError(t, err)
179+
assert.Equal(t, "1.2.3.4:12345", *cfg.PlacementHostAddr)
180+
})
181+
}
182+
183+
func TestValidateSchedulerHostAddr(t *testing.T) {
184+
t.Run("empty disables scheduler", func(t *testing.T) {
185+
cfg := &RunConfig{SharedRunConfig: SharedRunConfig{SchedulerHostAddress: strPtr("")}}
186+
err := cfg.validateSchedulerHostAddr()
187+
assert.NoError(t, err)
188+
assert.NotNil(t, cfg.SchedulerHostAddress)
189+
assert.Equal(t, "", *cfg.SchedulerHostAddress)
190+
})
191+
192+
t.Run("whitespace disables scheduler", func(t *testing.T) {
193+
cfg := &RunConfig{SharedRunConfig: SharedRunConfig{SchedulerHostAddress: strPtr(" ")}}
194+
err := cfg.validateSchedulerHostAddr()
195+
assert.NoError(t, err)
196+
assert.NotNil(t, cfg.SchedulerHostAddress)
197+
assert.Equal(t, "", *cfg.SchedulerHostAddress)
198+
})
199+
200+
t.Run("default port appended when hostname provided without port", func(t *testing.T) {
201+
cfg := &RunConfig{SharedRunConfig: SharedRunConfig{SchedulerHostAddress: strPtr("localhost")}}
202+
err := cfg.validateSchedulerHostAddr()
203+
assert.NoError(t, err)
204+
if runtime.GOOS == daprWindowsOS {
205+
assert.True(t, strings.HasSuffix(*cfg.SchedulerHostAddress, ":6060"))
206+
} else {
207+
assert.True(t, strings.HasSuffix(*cfg.SchedulerHostAddress, ":50006"))
208+
}
209+
})
210+
211+
t.Run("custom port preserved when provided", func(t *testing.T) {
212+
cfg := &RunConfig{SharedRunConfig: SharedRunConfig{SchedulerHostAddress: strPtr("1.2.3.4:45678")}}
213+
err := cfg.validateSchedulerHostAddr()
214+
assert.NoError(t, err)
215+
assert.Equal(t, "1.2.3.4:45678", *cfg.SchedulerHostAddress)
216+
})
217+
}

0 commit comments

Comments
 (0)