141 lines
2.5 KiB
Go
141 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"archive/tar"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
|
|
yaml "gopkg.in/yaml.v2"
|
|
|
|
"novit.tech/direktil/pkg/cpiocat"
|
|
)
|
|
|
|
func renderBootstrapConfig(w http.ResponseWriter, r *http.Request, ctx *renderContext, asJson bool) (err error) {
|
|
log.Printf("sending bootstrap config for %q", ctx.Host.Name)
|
|
|
|
_, cfg, err := ctx.BootstrapConfig()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if asJson {
|
|
err = json.NewEncoder(w).Encode(cfg)
|
|
} else {
|
|
err = yaml.NewEncoder(w).Encode(cfg)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func buildInitrdV2(out io.Writer, ctx *renderContext) (err error) {
|
|
_, cfg, err := ctx.Config()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
cat := cpiocat.New(out)
|
|
|
|
// initrd
|
|
initrdPath, err := ctx.distFetch("initrd", "2.0.0" /* FIXME */)
|
|
if err != nil {
|
|
return
|
|
}
|
|
cat.AppendArchFile(initrdPath)
|
|
|
|
// embedded layers (modules)
|
|
for _, layer := range cfg.Layers {
|
|
switch layer {
|
|
case "modules":
|
|
|
|
layerVersion := ctx.Host.Versions[layer]
|
|
modulesPath, err := ctx.distFetch("layers", layer, layerVersion)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cat.AppendFile(modulesPath, "modules.sqfs")
|
|
}
|
|
}
|
|
|
|
// config
|
|
cfgBytes, _, err := ctx.BootstrapConfig()
|
|
if err != nil {
|
|
return
|
|
}
|
|
cat.AppendBytes(cfgBytes, "config.yaml", 0600)
|
|
|
|
// ssh keys
|
|
// FIXME we want a bootstrap-stage key instead of the real host key
|
|
cat.AppendBytes(cfg.FileContent("/etc/ssh/ssh_host_rsa_key"), "id_rsa", 0600)
|
|
|
|
return cat.Close()
|
|
}
|
|
|
|
func buildBootstrap(out io.Writer, ctx *renderContext) (err error) {
|
|
arch := tar.NewWriter(out)
|
|
defer arch.Close()
|
|
|
|
// config
|
|
cfgBytes, cfg, err := ctx.Config()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = arch.WriteHeader(&tar.Header{Name: "config.yaml", Size: int64(len(cfgBytes))})
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
_, err = arch.Write(cfgBytes)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// layers
|
|
for _, layer := range cfg.Layers {
|
|
if layer == "modules" {
|
|
continue // modules are with the kernel in boot v2
|
|
}
|
|
|
|
layerVersion := ctx.Host.Versions[layer]
|
|
if layerVersion == "" {
|
|
return fmt.Errorf("layer %q not mapped to a version", layer)
|
|
}
|
|
|
|
outPath, err := ctx.distFetch("layers", layer, layerVersion)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
f, err := os.Open(outPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
stat, err := f.Stat()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = arch.WriteHeader(&tar.Header{
|
|
Name: layer + ".fs",
|
|
Size: stat.Size(),
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = io.Copy(arch, f)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|