package daemon import ( "bytes" "encoding/json" "errors" "fmt" "os" "path/filepath" "reflect" "isle/bootstrap" "isle/garage/garagesrv" "isle/jsonutil" "isle/secrets" ) // JoiningBootstrap wraps a normal Bootstrap to include extra data which a host // might need while joining a network. type JoiningBootstrap struct { Bootstrap bootstrap.Bootstrap Secrets map[secrets.ID]json.RawMessage } func writeBootstrapToStateDir( stateDirPath string, hostBootstrap bootstrap.Bootstrap, ) error { var ( path = bootstrap.StateDirPath(stateDirPath) dirPath = filepath.Dir(path) ) if err := os.MkdirAll(dirPath, 0700); err != nil { return fmt.Errorf("creating directory %q: %w", dirPath, err) } if err := jsonutil.WriteFile(hostBootstrap, path, 0600); err != nil { return fmt.Errorf("writing bootstrap to %q: %w", path, err) } return nil } func coalesceDaemonConfigAndBootstrap( daemonConfig Config, hostBootstrap bootstrap.Bootstrap, ) ( bootstrap.Bootstrap, error, ) { host := bootstrap.Host{ HostAssigned: hostBootstrap.HostAssigned, HostConfigured: bootstrap.HostConfigured{ Nebula: bootstrap.NebulaHost{ PublicAddr: daemonConfig.VPN.PublicAddr, }, }, } if allocs := daemonConfig.Storage.Allocations; len(allocs) > 0 { for i, alloc := range allocs { id, rpcPort, err := garagesrv.InitAlloc(alloc.MetaPath, alloc.RPCPort) if err != nil { return bootstrap.Bootstrap{}, fmt.Errorf( "initializing alloc at %q: %w", alloc.MetaPath, err, ) } host.Garage.Instances = append(host.Garage.Instances, bootstrap.GarageHostInstance{ ID: id, RPCPort: rpcPort, S3APIPort: alloc.S3APIPort, }) allocs[i].RPCPort = rpcPort } } hostBootstrap.Hosts[host.Name] = host return hostBootstrap, nil } type bootstrapDiff struct { hostsChanged bool nebulaChanged bool dnsChanged bool } func calcBootstrapDiff( daemonConfig Config, prevBootstrap, nextBootstrap bootstrap.Bootstrap, ) ( diff bootstrapDiff, err error, ) { { prevHash, prevErr := bootstrap.HostsHash(prevBootstrap.Hosts) nextHash, nextErr := bootstrap.HostsHash(nextBootstrap.Hosts) if err = errors.Join(prevErr, nextErr); err != nil { err = fmt.Errorf("calculating host hashes: %w", err) return } diff.hostsChanged = !bytes.Equal(prevHash, nextHash) } { prevNebulaConfig, prevErr := nebulaConfig(daemonConfig, prevBootstrap) nextNebulaConfig, nextErr := nebulaConfig(daemonConfig, nextBootstrap) if err = errors.Join(prevErr, nextErr); err != nil { err = fmt.Errorf("calculating nebula config: %w", err) return } diff.nebulaChanged = !reflect.DeepEqual( prevNebulaConfig, nextNebulaConfig, ) } { diff.dnsChanged = !reflect.DeepEqual( dnsmasqConfig(daemonConfig, prevBootstrap), dnsmasqConfig(daemonConfig, nextBootstrap), ) } return }