mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-26 19:13:34 +00:00
feat(caddy): order local machine upstreams first in generated Caddyfile
This commit is contained in:
@@ -112,17 +112,23 @@ func NewCaddyfileGenerator(
|
||||
func (g *CaddyfileGenerator) Generate(
|
||||
ctx context.Context, records []store.ContainerRecord, includeCustom bool,
|
||||
) (string, error) {
|
||||
// Sort records by local machine first, then by service name and creation time. Placing containers on the local
|
||||
// machine first lets user-defined Caddy configs pair this ordering with the "first" lb_policy to always send
|
||||
// traffic to the same-host replica (skipping the cross-machine hop) and only fall back to remote upstreams when
|
||||
// the local one is unhealthy.
|
||||
// The service name and creation time tiebreakers keep the generated Caddyfile stable across regenerations.
|
||||
slices.SortStableFunc(records, func(a, b store.ContainerRecord) int {
|
||||
return cmp.Or(
|
||||
g.localMachineRank(a.MachineID)-g.localMachineRank(b.MachineID),
|
||||
strings.Compare(a.Container.ServiceName(), b.Container.ServiceName()),
|
||||
a.Container.CreatedTime().Compare(b.Container.CreatedTime()),
|
||||
)
|
||||
})
|
||||
|
||||
containers := make([]api.ServiceContainer, len(records))
|
||||
for i, cr := range records {
|
||||
containers[i] = cr.Container
|
||||
}
|
||||
// Sort containers by service name and creation time to generate a stable Caddyfile.
|
||||
slices.SortStableFunc(containers, func(a, b api.ServiceContainer) int {
|
||||
return cmp.Or(
|
||||
strings.Compare(a.ServiceName(), b.ServiceName()),
|
||||
a.CreatedTime().Compare(b.CreatedTime()),
|
||||
)
|
||||
})
|
||||
|
||||
caddyfile, err := g.generateBaseFromPorts(containers)
|
||||
if err != nil {
|
||||
@@ -243,6 +249,15 @@ func (g *CaddyfileGenerator) Generate(
|
||||
return caddyfileHeader + "\n" + caddyfile, nil
|
||||
}
|
||||
|
||||
// localMachineRank returns 0 if the given machineID matches the local machine and 1 otherwise.
|
||||
// Useful for sorting containers running locally first.
|
||||
func (g *CaddyfileGenerator) localMachineRank(machineID string) int {
|
||||
if g.machineID == machineID {
|
||||
return 0
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
func (g *CaddyfileGenerator) generateBaseFromPorts(containers []api.ServiceContainer) (string, error) {
|
||||
httpHostUpstreams, httpsHostUpstreams := httpUpstreamsFromPorts(containers)
|
||||
|
||||
|
||||
@@ -159,6 +159,25 @@ https://secure.example.com {
|
||||
}
|
||||
log
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "local machine upstreams listed first",
|
||||
containers: []store.ContainerRecord{
|
||||
newContainerRecord(newContainer("10.210.0.2", "app.example.com:8080/http"), "mach1"),
|
||||
newContainerRecord(newContainer("10.210.1.2", "app.example.com:8080/http"), "test-machine-id"),
|
||||
newContainerRecord(newContainer("10.210.2.2", "app.example.com:8080/http"), "mach2"),
|
||||
newContainerRecord(newContainer("10.210.1.3", "app.example.com:8080/http"), "test-machine-id"),
|
||||
},
|
||||
want: testCaddyfileHeader + `
|
||||
# Sites generated from service ports.
|
||||
|
||||
http://app.example.com {
|
||||
reverse_proxy 10.210.1.2:8080 10.210.1.3:8080 10.210.0.2:8080 10.210.2.2:8080 {
|
||||
import common_proxy
|
||||
}
|
||||
log
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user