Skip to content

Commit 3f24ead

Browse files
assume host mode for postgres short ports (#1445)
* assume host mode for postgres short ports * include redis * avoid replacing app_protocol * fixup project before validate * fixupPort after managed service fixups * fixup mongo too; fix ingress warnings --------- Co-authored-by: Lionello Lunesu <[email protected]>
1 parent bcaabd3 commit 3f24ead

22 files changed

+146
-34
lines changed

src/pkg/cli/compose/fixup.go

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,6 @@ func FixupServices(ctx context.Context, provider client.Provider, project *compo
2727
}
2828
slices.Sort(config.Names) // sort for binary search
2929

30-
// Fixup ports first (which affects service name replacement by ReplaceServiceNameWithDNS)
31-
for _, svccfg := range project.Services {
32-
for i, port := range svccfg.Ports {
33-
svccfg.Ports[i] = fixupPort(port)
34-
}
35-
}
36-
3730
// Fixup any pseudo services (this might create port configs, which will affect service name replacement by ReplaceServiceNameWithDNS)
3831
for _, svccfg := range project.Services {
3932
repo := GetImageRepo(svccfg.Image)
@@ -67,6 +60,11 @@ func FixupServices(ctx context.Context, provider client.Provider, project *compo
6760
fixupLLM(&svccfg)
6861
}
6962

63+
// Fixup ports, which affects service name replacement by ReplaceServiceNameWithDNS below
64+
for i, port := range svccfg.Ports {
65+
svccfg.Ports[i] = fixupPort(port)
66+
}
67+
7068
// update the concrete service with the fixed up object
7169
project.Services[svccfg.Name] = svccfg
7270
}
@@ -241,6 +239,8 @@ func fixupPostgresService(svccfg *composeTypes.ServiceConfig, provider client.Pr
241239
}
242240
term.Debugf("service %q: adding postgres host port %d", svccfg.Name, port)
243241
svccfg.Ports = []composeTypes.ServicePortConfig{{Target: port, Mode: Mode_HOST, Protocol: Protocol_TCP}}
242+
} else {
243+
fixupIngressPorts(svccfg)
244244
}
245245
return nil
246246
}
@@ -277,6 +277,8 @@ func fixupMongoService(svccfg *composeTypes.ServiceConfig, provider client.Provi
277277
}
278278
term.Debugf("service %q: adding mongodb host port %d", svccfg.Name, port)
279279
svccfg.Ports = []composeTypes.ServicePortConfig{{Target: port, Mode: Mode_HOST, Protocol: Protocol_TCP}}
280+
} else {
281+
fixupIngressPorts(svccfg)
280282
}
281283
return nil
282284
}
@@ -303,10 +305,21 @@ func fixupRedisService(svccfg *composeTypes.ServiceConfig, provider client.Provi
303305
}
304306
term.Debugf("service %q: adding redis host port %d", svccfg.Name, port)
305307
svccfg.Ports = []composeTypes.ServicePortConfig{{Target: port, Mode: Mode_HOST, Protocol: Protocol_TCP}}
308+
} else {
309+
fixupIngressPorts(svccfg)
306310
}
307311
return nil
308312
}
309313

314+
func fixupIngressPorts(svccfg *composeTypes.ServiceConfig) {
315+
for i, port := range svccfg.Ports {
316+
if port.Mode == Mode_INGRESS || port.Mode == "" {
317+
term.Debugf("service %q: changing port %d to host mode", svccfg.Name, port.Target)
318+
svccfg.Ports[i].Mode = Mode_HOST
319+
}
320+
}
321+
}
322+
310323
// Declare a private network for the model provider
311324
const modelProviderNetwork = "model_provider_private"
312325

@@ -415,17 +428,17 @@ func fixupPort(port composeTypes.ServicePortConfig) composeTypes.ServicePortConf
415428
fallthrough
416429
case Mode_INGRESS:
417430
// This code is unnecessarily complex because compose-go silently converts short `ports:` syntax to ingress+tcp
418-
if port.Protocol != Protocol_UDP {
431+
if port.Protocol == Protocol_UDP {
432+
term.Warnf("port %d: UDP ports default to 'host' mode (add 'mode: host' to silence)", port.Target)
433+
port.Mode = Mode_HOST
434+
} else {
419435
if port.Published != "" {
420436
term.Debugf("port %d: ignoring 'published: %s' in 'ingress' mode", port.Target, port.Published)
421437
}
422438
if port.AppProtocol == "" {
423439
// TCP ingress is not supported; assuming HTTP (add 'app_protocol: http' to silence)"
424440
port.AppProtocol = "http"
425441
}
426-
} else {
427-
term.Warnf("port %d: UDP ports default to 'host' mode (add 'mode: host' to silence)", port.Target)
428-
port.Mode = Mode_HOST
429442
}
430443
case Mode_HOST:
431444
// no-op

src/pkg/cli/compose/validation.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,8 @@ func validateService(svccfg *composeTypes.ServiceConfig, project *composeTypes.P
234234
if svccfg.HealthCheck == nil || svccfg.HealthCheck.Disable {
235235
// Show a warning when we have ingress ports but no explicit healthcheck
236236
for _, port := range svccfg.Ports {
237-
if port.Mode == "ingress" {
238-
term.Warnf("service %q: ingress port without healthcheck defaults to GET / HTTP/1.1", svccfg.Name)
237+
if port.Mode == Mode_INGRESS {
238+
term.Warnf("service %q: ingress port %d without healthcheck; defaults to GET / HTTP/1.1", svccfg.Name, port.Target)
239239
break
240240
}
241241
}

src/pkg/cli/compose/validation_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ func TestValidationAndConvert(t *testing.T) {
4646
t.Fatal(err)
4747
}
4848

49+
if err := FixupServices(context.Background(), mockClient, project, UploadModeIgnore); err != nil {
50+
t.Logf("Service conversion failed: %v", err)
51+
logs.WriteString(err.Error() + "\n")
52+
}
53+
4954
if err := ValidateProjectConfig(context.Background(), project, listConfigNamesFunc); err != nil {
5055
t.Logf("Project config validation failed: %v", err)
5156
logs.WriteString(err.Error() + "\n")
@@ -56,11 +61,6 @@ func TestValidationAndConvert(t *testing.T) {
5661
logs.WriteString(err.Error() + "\n")
5762
}
5863

59-
if err := FixupServices(context.Background(), mockClient, project, UploadModeIgnore); err != nil {
60-
t.Logf("Service conversion failed: %v", err)
61-
logs.WriteString(err.Error() + "\n")
62-
}
63-
6464
// The order of the services is not guaranteed, so we sort the logs before comparing
6565
logLines := strings.SplitAfter(logs.String(), "\n")
6666
slices.Sort(logLines)

src/pkg/cli/composeUp.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,6 @@ func ComposeUp(ctx context.Context, project *compose.Project, fabric client.Fabr
4747
}
4848
}
4949

50-
if err := compose.ValidateProject(project); err != nil {
51-
return nil, project, &ComposeError{err}
52-
}
53-
5450
// Create a new project with only the necessary resources.
5551
// Do not modify the original project, because the caller needs it for debugging.
5652
fixedProject := project.WithoutUnnecessaryResources()
@@ -59,6 +55,10 @@ func ComposeUp(ctx context.Context, project *compose.Project, fabric client.Fabr
5955
return nil, project, err
6056
}
6157

58+
if err := compose.ValidateProject(fixedProject); err != nil {
59+
return nil, project, &ComposeError{err}
60+
}
61+
6262
bytes, err := fixedProject.MarshalYAML()
6363
if err != nil {
6464
return nil, project, err
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
! "yes" for boolean is not supported by YAML 1.2, please use `true`
2-
! service "echo": ingress port without healthcheck defaults to GET / HTTP/1.1
2+
! service "echo": ingress port 80 without healthcheck; defaults to GET / HTTP/1.1
33
! service "echo": missing memory reservation; using provider-specific defaults. Specify deploy.resources.reservations.memory to avoid out-of-memory errors

src/testdata/fixupenv/compose.yaml.warnings

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
! service "env-in-config": environment variable(s) ["CONFIG1"] will use the `defang config` value instead of adjusted service name
33
! service "env-in-config": missing memory reservation; using provider-specific defaults. Specify deploy.resources.reservations.memory to avoid out-of-memory errors
44
! service "fixup-args": missing memory reservation; using provider-specific defaults. Specify deploy.resources.reservations.memory to avoid out-of-memory errors
5-
! service "ingress-service": ingress port without healthcheck defaults to GET / HTTP/1.1
5+
! service "ingress-service": ingress port 5432 without healthcheck; defaults to GET / HTTP/1.1
66
! service "ingress-service": missing memory reservation; using provider-specific defaults. Specify deploy.resources.reservations.memory to avoid out-of-memory errors
77
! service "ui": missing memory reservation; using provider-specific defaults. Specify deploy.resources.reservations.memory to avoid out-of-memory errors
88
! service "use-ingress-service": missing memory reservation; using provider-specific defaults. Specify deploy.resources.reservations.memory to avoid out-of-memory errors
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
! service "alt-repo": missing memory reservation; using provider-specific defaults. Specify deploy.resources.reservations.memory to avoid out-of-memory errors
2-
! service "gateway-with-ports": ingress port without healthcheck defaults to GET / HTTP/1.1
2+
! service "gateway-with-ports": ingress port 5678 without healthcheck; defaults to GET / HTTP/1.1
33
! service "gateway-with-ports": missing memory reservation; using provider-specific defaults. Specify deploy.resources.reservations.memory to avoid out-of-memory errors
44
! service "gateway-without-ports": missing memory reservation; using provider-specific defaults. Specify deploy.resources.reservations.memory to avoid out-of-memory errors
55
! service "llm": missing memory reservation; using provider-specific defaults. Specify deploy.resources.reservations.memory to avoid out-of-memory errors
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1+
! service "ai_model": missing memory reservation; using provider-specific defaults. Specify deploy.resources.reservations.memory to avoid out-of-memory errors
12
! service "app": missing memory reservation; using provider-specific defaults. Specify deploy.resources.reservations.memory to avoid out-of-memory errors
3+
! service "my_model": missing memory reservation; using provider-specific defaults. Specify deploy.resources.reservations.memory to avoid out-of-memory errors
24
! service "withendpoint": missing memory reservation; using provider-specific defaults. Specify deploy.resources.reservations.memory to avoid out-of-memory errors

src/testdata/mongo/compose.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,8 @@ services:
7777
mongo-wrong-image:
7878
image: example
7979
x-defang-mongodb: true
80+
81+
short-ports:
82+
image: mongo
83+
ports:
84+
- 27017:27017

src/testdata/mongo/compose.yaml.fixup

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,5 +230,21 @@
230230
"protocol": "tcp"
231231
}
232232
]
233+
},
234+
"short-ports": {
235+
"command": null,
236+
"entrypoint": null,
237+
"image": "mongo",
238+
"networks": {
239+
"default": null
240+
},
241+
"ports": [
242+
{
243+
"mode": "host",
244+
"target": 27017,
245+
"published": "27017",
246+
"protocol": "tcp"
247+
}
248+
]
233249
}
234250
}

0 commit comments

Comments
 (0)