diff --git a/pkg/cluster/hosts.go b/pkg/cluster/hosts.go new file mode 100644 index 0000000..359aa75 --- /dev/null +++ b/pkg/cluster/hosts.go @@ -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() +}