Compare commits
8 Commits
a0cc698a39
...
v0.6.4
| Author | SHA1 | Date | |
|---|---|---|---|
| f62a47003d | |||
| 5abaed9047 | |||
| c702d649e0 | |||
| e9f9d474dc | |||
| e2941cf2c0 | |||
| ea755113a8 | |||
| 1c199ed923 | |||
| 5dc5c95aa1 |
+1
-1
@@ -37,5 +37,5 @@ func setVerbosity(_ *cobra.Command, _ []string) {
|
||||
if desired > 6 {
|
||||
desired = 6
|
||||
}
|
||||
log = log.WithLevel(slog.LogLevel(desired))
|
||||
log = zerolog.New(nil, slog.LogLevel(desired))
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@ type Cluster struct {
|
||||
Domain string `json:"domain,omitempty" yaml:"domain,omitempty"`
|
||||
|
||||
CephFSID uuid.UUID `json:"ceph_fsid,omitempty" yaml:"ceph_fsid,omitempty"`
|
||||
Zones []*Zone `json:"zones,omitempty" yaml:"zones,omitempty"`
|
||||
Regions []Region `json:",omitempty" yaml:",omitempty"`
|
||||
Zones []*Zone `json:",omitempty" yaml:",omitempty"`
|
||||
}
|
||||
|
||||
// revive:enable:line-length-limit
|
||||
|
||||
@@ -14,6 +14,7 @@ func (m *Cluster) init(opts *ScanOptions) error {
|
||||
m.scanZoneIDs,
|
||||
m.scanSort,
|
||||
m.scanGateways,
|
||||
m.initRegions,
|
||||
} {
|
||||
if err := fn(opts); err != nil {
|
||||
return err
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
package cluster
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
type hostsFile struct {
|
||||
Ring0 []hostsEntry
|
||||
Ring1 []hostsEntry
|
||||
}
|
||||
|
||||
type hostsEntry struct {
|
||||
Addr string
|
||||
Names []string
|
||||
}
|
||||
|
||||
var hostsTemplate = template.Must(template.New("hosts").Funcs(template.FuncMap{
|
||||
"StringsJoin": strings.Join,
|
||||
}).Parse(`127.0.0.1 localhost
|
||||
|
||||
# The following lines are desirable for IPv6 capable hosts
|
||||
::1 ip6-localhost ip6-loopback
|
||||
fe00::0 ip6-localnet
|
||||
ff00::0 ip6-mcastprefix
|
||||
ff02::1 ip6-allnodes
|
||||
ff02::2 ip6-allrouters
|
||||
ff02::3 ip6-allhosts
|
||||
|
||||
{{range .Ring1 -}}
|
||||
{{.Addr}} {{StringsJoin .Names " "}}
|
||||
{{end}}
|
||||
{{range .Ring0 -}}
|
||||
{{.Addr}} {{StringsJoin .Names " "}}
|
||||
{{end -}}
|
||||
`))
|
||||
|
||||
// WriteHosts rewrites all hosts files on the tree
|
||||
func (m *Cluster) WriteHosts() error {
|
||||
var err error
|
||||
|
||||
m.ForEachZone(func(z *Zone) bool {
|
||||
err = z.WriteHosts()
|
||||
return err != nil
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// WriteHosts rewrites all hosts files in the zone
|
||||
func (z *Zone) WriteHosts() error {
|
||||
var err error
|
||||
|
||||
s := z.Hosts()
|
||||
z.ForEachMachine(func(p *Machine) bool {
|
||||
err = p.WriteStringFile(s, "hosts")
|
||||
return err != nil
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// WriteHosts rewrites the hosts file
|
||||
func (p *Machine) WriteHosts() error {
|
||||
s := p.zone.Hosts()
|
||||
return p.WriteStringFile(s, "hosts")
|
||||
}
|
||||
|
||||
func (z *Zone) genHosts(out *hostsFile, p *Machine) {
|
||||
var names []string
|
||||
|
||||
ip, _ := RingOneAddress(p.zone.ID, p.ID)
|
||||
names = append(names, p.Name)
|
||||
|
||||
if p.CephMonitor {
|
||||
names = append(names, fmt.Sprintf("%s-%s", p.zone.Name, "ceph"))
|
||||
names = append(names, fmt.Sprintf("%s-%s", p.zone.Name, "k3s"))
|
||||
|
||||
if z.ID == p.zone.ID {
|
||||
names = append(names, "ceph")
|
||||
names = append(names, "k3s")
|
||||
}
|
||||
}
|
||||
|
||||
entry := hostsEntry{
|
||||
Addr: ip.String(),
|
||||
Names: names,
|
||||
}
|
||||
|
||||
out.Ring1 = append(out.Ring1, entry)
|
||||
|
||||
if p.IsGateway() {
|
||||
var s string
|
||||
|
||||
ip, _ = RingZeroAddress(p.zone.ID, p.ID)
|
||||
s = fmt.Sprintf("%s-%v", p.Name, 0)
|
||||
|
||||
entry = hostsEntry{
|
||||
Addr: ip.String(),
|
||||
Names: []string{s},
|
||||
}
|
||||
|
||||
out.Ring0 = append(out.Ring0, entry)
|
||||
}
|
||||
}
|
||||
|
||||
// Hosts renders the /etc/hosts to be used on this zone
|
||||
func (z *Zone) Hosts() string {
|
||||
var buf bytes.Buffer
|
||||
var out hostsFile
|
||||
|
||||
z.zones.ForEachZone(func(z2 *Zone) bool {
|
||||
z2.ForEachMachine(func(p *Machine) bool {
|
||||
z.genHosts(&out, p)
|
||||
|
||||
return false
|
||||
})
|
||||
return false
|
||||
})
|
||||
|
||||
if err := hostsTemplate.Execute(&buf, &out); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package cluster
|
||||
|
||||
// Region represents a group of zones geographically related
|
||||
type Region struct {
|
||||
m *Cluster
|
||||
zones []*Zone
|
||||
|
||||
Name string
|
||||
Regions []string `json:",omitempty" yaml:",omitempty"`
|
||||
}
|
||||
|
||||
func (m *Cluster) initRegions(_ *ScanOptions) error {
|
||||
regions := make(map[string][]*Zone)
|
||||
|
||||
// first regions defined by zones
|
||||
m.ForEachZone(func(z *Zone) bool {
|
||||
for _, region := range z.Regions {
|
||||
regions[region] = append(regions[region], z)
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
// bind first level regions and their zones
|
||||
for name, zones := range regions {
|
||||
m.syncRegions(name, zones...)
|
||||
}
|
||||
|
||||
// and combine zones to produce larger regions
|
||||
for i := range m.Regions {
|
||||
r := &m.Regions[i]
|
||||
m.finishRegion(r)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Cluster) syncRegions(name string, zones ...*Zone) {
|
||||
for _, r := range m.Regions {
|
||||
if r.Name == name {
|
||||
// found
|
||||
r.m = m
|
||||
r.zones = zones
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// new
|
||||
m.Regions = append(m.Regions, Region{
|
||||
m: m,
|
||||
zones: zones,
|
||||
Name: name,
|
||||
})
|
||||
}
|
||||
|
||||
func (m *Cluster) finishRegion(r *Region) {
|
||||
if r.m != nil {
|
||||
// ready
|
||||
return
|
||||
}
|
||||
|
||||
r.m = m
|
||||
sub := []string{}
|
||||
for _, name := range r.Regions {
|
||||
r2, ok := m.getRegion(name)
|
||||
if !ok {
|
||||
m.warn(nil).WithField("region", name).Print("unknown region")
|
||||
continue
|
||||
}
|
||||
|
||||
sub = append(sub, r2.Name)
|
||||
r.zones = append(r.zones, r2.zones...)
|
||||
}
|
||||
r.Regions = sub
|
||||
}
|
||||
|
||||
func (m *Cluster) getRegion(name string) (*Region, bool) {
|
||||
for i := range m.Regions {
|
||||
r := &m.Regions[i]
|
||||
|
||||
if name == r.Name {
|
||||
m.finishRegion(r)
|
||||
return r, true
|
||||
}
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
||||
@@ -5,6 +5,7 @@ func (m *Cluster) SyncAll() error {
|
||||
for _, fn := range []func() error{
|
||||
m.SyncAllWireguard,
|
||||
m.SyncAllCeph,
|
||||
m.WriteHosts,
|
||||
} {
|
||||
if err := fn(); err != nil {
|
||||
return err
|
||||
|
||||
@@ -19,8 +19,9 @@ type Zone struct {
|
||||
zones *Cluster
|
||||
logger `json:"-" yaml:"-"`
|
||||
|
||||
ID int
|
||||
Name string
|
||||
ID int
|
||||
Name string
|
||||
Regions []string `json:",omitempty" yaml:",omitempty"`
|
||||
|
||||
Machines
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user