Browse Source

cluster: rework `env` output to qualify zones using the region

Signed-off-by: Alejandro Mery <amery@jpi.io>
Alejandro Mery 2 months ago
parent
commit
3c5e577d47
  1. 12
      go.mod
  2. 25
      go.sum
  3. 124
      pkg/cluster/env.go

12
go.mod

@ -4,7 +4,7 @@ go 1.19
require (
asciigoat.org/ini v0.2.5
darvaza.org/core v0.13.3
darvaza.org/core v0.14.1
darvaza.org/resolver v0.9.2
darvaza.org/sidecar v0.4.0
darvaza.org/slog v0.5.7
@ -15,8 +15,8 @@ require (
github.com/libdns/libdns v0.2.2
github.com/mgechev/revive v1.3.7
github.com/spf13/cobra v1.8.0
golang.org/x/crypto v0.23.0
golang.org/x/net v0.25.0
golang.org/x/crypto v0.25.0
golang.org/x/net v0.27.0
gopkg.in/yaml.v3 v3.0.1
)
@ -46,7 +46,7 @@ require (
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
golang.org/x/tools v0.21.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
)

25
go.sum

@ -4,8 +4,8 @@ asciigoat.org/ini v0.2.5 h1:4gRIp9rU+XQt8+HMqZO5R7GavMv9Yl2+N+je6djDIAE=
asciigoat.org/ini v0.2.5/go.mod h1:gmXzJ9XFqf1NLk5nQkj04USQ4tMtdRJHNQX6vp3DzjU=
darvaza.org/cache/x/simplelru v0.1.8 h1:rvFucut4wKYbsYc994yR3P0M08NqlsvZxr5G4QK82tw=
darvaza.org/cache/x/simplelru v0.1.8/go.mod h1:Mv1isOJTcXYK+aK0AvUe+/3KpRTXDsYga6rdTS/upNs=
darvaza.org/core v0.13.3 h1:DOsidY49WXsWiJulOIxDq578h/3ekgx0trWxbvgv5bc=
darvaza.org/core v0.13.3/go.mod h1:47Ydh67KnzjLNu1mzX3r2zpphbxQqEaihMsUq5GflQ4=
darvaza.org/core v0.14.1 h1:PJXoG4u5gMx8G3zs7VcAIN6bmWTi1yp8vpuikPvDucQ=
darvaza.org/core v0.14.1/go.mod h1:C+B0GRNLB+/asGfxjQ9XZERdk7xaFxzt5xTIBPiNm2M=
darvaza.org/resolver v0.9.2 h1:sUX6LZ1eN5TzJW7L4m7HM+BvwBeWl8dYYDGVSe+AIhk=
darvaza.org/resolver v0.9.2/go.mod h1:XWqPhrxoOKNzRuSozOwmE1M6QVqQL28jEdxylnIO8Nw=
darvaza.org/sidecar v0.4.0 h1:wHghxzLsiT82WDBBUf34aTqtOvRBg4UbxVIJgKNXRVA=
@ -94,24 +94,23 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=
golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

124
pkg/cluster/env.go

@ -7,6 +7,8 @@ import (
"sort"
"strings"
"darvaza.org/core"
"git.jpi.io/amery/jpictl/pkg/rings"
)
@ -36,20 +38,24 @@ func (m *Cluster) Env(export bool) (*Env, error) {
return env, nil
}
// Zones returns the list of Zone IDs
func (m *Env) Zones() []rings.ZoneID {
// Zones returns the list of Zone IDs of a region,
// or from all if none is specified.
func (m *Env) Zones(r *Region) []rings.ZoneID {
var zones []rings.ZoneID
m.ForEachZone(func(z *Zone) bool {
iter := core.IIf[ZoneIterator](r != nil, r, m)
iter.ForEachZone(func(z *Zone) bool {
zones = append(zones, z.ID)
return false
})
core.SliceSort(zones, cmpOrdered[rings.ZoneID])
return zones
}
// Regions returns the list of primary regions
func (m *Env) Regions() []string {
// RegionsNames returns a sorted list of primary regions names
func (m *Env) RegionsNames() []string {
var regions []string
m.ForEachRegion(func(r *Region) bool {
@ -64,6 +70,20 @@ func (m *Env) Regions() []string {
return regions
}
// Regions returns a sorted list of primary regions IDs
func (m *Env) Regions() (regions []rings.RegionID) {
m.ForEachRegion(func(r *Region) bool {
if r.IsPrimary() {
regions = append(regions, r.ID)
}
return false
})
core.SliceSort(regions, cmpOrdered[rings.RegionID])
return regions
}
// WriteTo generates environment variables for shell scripts
func (m *Env) WriteTo(w io.Writer) (int64, error) {
var buf bytes.Buffer
@ -72,41 +92,75 @@ func (m *Env) WriteTo(w io.Writer) (int64, error) {
m.writeEnvVar(&buf, m.cephFSID, "FSID")
}
m.writeEnvVar(&buf, genEnvStrings(m.Regions()), "REGIONS")
m.writeEnvVar(&buf, genEnvInts(m.Zones()), "ZONES")
regions := m.getRegions()
ids := core.SliceMap(regions, func(_ []rings.RegionID, r *Region) (out []rings.RegionID) {
return append(out, r.ID)
})
names := core.SliceMap(regions, func(_ []string, r *Region) (out []string) {
return append(out, r.Name)
})
m.writeEnvVar(&buf, genEnvInts(ids), "REGIONS")
m.writeEnvVar(&buf, genEnvStrings(names), "REGIONS_NAMES")
m.ForEachZone(func(z *Zone) bool {
m.writeEnvZone(&buf, z)
for _, r := range regions {
m.writeEnvRegion(&buf, r)
}
return buf.WriteTo(w)
}
func (m *Env) getRegions() (out []*Region) {
m.ForEachRegion(func(r *Region) bool {
if r.IsPrimary() {
out = append(out, r)
}
return false
})
return buf.WriteTo(w)
core.SliceSort(out, func(a, b *Region) int {
return cmpOrdered(a.ID, b.ID)
})
return out
}
func (m *Env) writeEnvRegion(w io.Writer, r *Region) {
regionID := r.ID
// REGION{regionID}_NAME
m.writeEnvVar(w, r.Name, "REGION%v_%s", regionID, "NAME")
// REGION{regionID}_ZONES
m.writeEnvVar(w, genEnvInts(m.Zones(r)), "REGION%v_%s", regionID, "ZONES")
r.ForEachZone(func(z *Zone) bool {
m.writeEnvZone(w, r, z)
return false
})
}
func (m *Env) writeEnvZone(w io.Writer, z *Zone) {
zoneID := z.ID
func (m *Env) writeEnvZone(w io.Writer, r *Region, z *Zone) {
zonePrefix := fmt.Sprintf("REGION%v_ZONE%v", r.ID, z.ID)
monPrefix := zonePrefix + "_MON"
// ZONE{zoneID}
m.writeEnvVar(w, genEnvZoneNodes(z), "ZONE%v", zoneID)
// REGION{regionID}_ZONE{zoneID}
m.writeEnvVar(w, genEnvZoneNodes(z), zonePrefix)
// ZONE{zoneID}_NAME
m.writeEnvVar(w, z.Name, "ZONE%v_%s", zoneID, "NAME")
// REGION{regionID}_ZONE{zoneID}_NAME
m.writeEnvVar(w, z.Name, zonePrefix+"_NAME")
// ZONE{zoneID}_GW
// REGION{regionID}_ZONE{zoneID}_GW
gateways, _ := z.GatewayIDs()
m.writeEnvVar(w, genEnvInts(gateways), "ZONE%v_%s", zoneID, "GW")
// ZONE{zoneID}_REGION
m.writeEnvVar(w, genEnvZoneRegion(z), "ZONE%v_%s", zoneID, "REGION")
m.writeEnvVar(w, genEnvInts(gateways), zonePrefix+"_GW")
// Ceph
monitors := z.GetCephMonitors()
// MON{zoneID}_NAME
m.writeEnvVar(w, genEnvZoneCephMonNames(monitors), "MON%v_%s", zoneID, "NAME")
// MON{zoneID}_IP
m.writeEnvVar(w, genEnvZoneCephMonIPs(monitors), "MON%v_%s", zoneID, "IP")
// MON{zoneID}_ID
m.writeEnvVar(w, genEnvZoneCephMonIDs(monitors), "MON%v_%s", zoneID, "ID")
// REGION{regionID}_MON{zone_ID}
m.writeEnvVar(w, genEnvZoneCephMonNames(monitors), monPrefix)
// REGION{regionID}_MON{zone_ID}_IP
m.writeEnvVar(w, genEnvZoneCephMonIPs(monitors), monPrefix+"_IP")
// REGION{regionID}_MON{zone_ID}_ID
m.writeEnvVar(w, genEnvZoneCephMonIDs(monitors), monPrefix+"_ID")
}
func (m *Env) writeEnvVar(w io.Writer, value string, name string, args ...any) {
@ -131,14 +185,15 @@ func (m *Env) writeEnvVar(w io.Writer, value string, name string, args ...any) {
}
}
func genEnvInts[T ~int | ~uint](values []T) string {
func genEnvInts[T core.Signed](values []T) string {
var buf bytes.Buffer
for _, v := range values {
if buf.Len() > 0 {
_, _ = buf.WriteRune(' ')
}
_, _ = buf.WriteString(fmt.Sprintf("%v", v))
_, _ = buf.WriteString(fmt.Sprintf("%v", int64(v)))
}
return buf.String()
@ -209,3 +264,14 @@ func genEnvZoneCephMonIDs(m Machines) string {
})
return buf.String()
}
func cmpOrdered[T core.Ordered](a, b T) int {
switch {
case a == b:
return 0
case a < b:
return -1
default:
return 1
}
}

Loading…
Cancel
Save