bladerunner/packer/packerlib/ubuntu.go

146 lines
3.1 KiB
Go

package packerlib
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"path/filepath"
"strings"
"gopkg.in/yaml.v2"
)
type urlSet struct {
FileURLs []string
ChecksumURL string
}
// ubuntuImage returns a local cache path and a remote fetch path for an
// Ubuntu image for a given version.
func ubuntuImage(version string) urlSet {
imageBase := fmt.Sprintf("ubuntu-%s-preinstalled-server-arm64+raspi.img.xz", version)
imageDir := fmt.Sprintf("https://cdimage.ubuntu.com/releases/%s/release/", version)
checksumURL := fmt.Sprintf("http://cdimage.ubuntu.com/releases/%s/release/SHA256SUMS", version)
localImage := "build/" + imageBase
remoteImage := imageDir + imageBase
return urlSet{
FileURLs: []string{
localImage,
remoteImage,
},
ChecksumURL: checksumURL,
}
}
func UbuntuBuilder(version, size, outputPath string) Builder {
urlSet := ubuntuImage(version)
outputPath = "build/" + outputPath
b := NewBuilder(urlSet.FileURLs)
return b.
WithSHA256Checksum(urlSet.ChecksumURL).
WithUnarchiver("xz").
WithStandardImage(size, outputPath).
WithQemuDefaults()
}
type UbuntuBoardSpec struct {
Version string `yaml:"version"`
Size string `yaml:"size"`
ImageName string `yaml:"name"`
LocalScripts []string `yaml:"local-scripts"`
Files []FileSet `yaml:"files"`
Scripts []string `yaml:"scripts"`
}
func (spec UbuntuBoardSpec) JSONPath(base string) string {
dest := spec.ImageName
ext := filepath.Ext(dest)
if ext != "" {
dest = strings.TrimSuffix(dest, ext)
}
dest += ".json"
if base != "" {
dest = filepath.Join(base, dest)
}
return dest
}
func (spec UbuntuBoardSpec) Board() Board {
board := Board{
Variables: map[string]string{},
Builders: []Builder{
UbuntuBuilder(spec.Version, spec.Size, spec.ImageName),
},
}
if len(spec.LocalScripts) != 0 {
board = board.WithShellLocalProvisioner(spec.LocalScripts...)
}
if len(spec.Files) != 0 {
board = board.WithFileSetsProvisioner(spec.Files)
}
if len(spec.Scripts) != 0 {
board = board.WithShellProvisioner(spec.Scripts...)
}
return board
}
func LoadUbuntuSpecs(path string) (specFile UbuntuBoardSpecFile, err error) {
log.Println("loading from", path)
data, err := ioutil.ReadFile(path)
if err != nil {
return
}
log.Println("parsing specs")
err = yaml.Unmarshal(data, &specFile)
if err != nil {
return
}
return specFile, nil
}
// UbuntuBoardSpecFile describes a set of specifications for Ubuntu boards.
//
// In the future, this may include additional data.
type UbuntuBoardSpecFile struct {
Boards []UbuntuBoardSpec `yaml:"boards"`
}
func (specFile UbuntuBoardSpecFile) WriteBoards(outputDir string) error {
for _, spec := range specFile.Boards {
board := spec.Board()
dest := spec.JSONPath(outputDir)
contents, err := json.Marshal(board)
if err != nil {
return err
}
buf := &bytes.Buffer{}
err = json.Indent(buf, contents, "", " ")
if err != nil {
return err
}
contents = buf.Bytes()
log.Println("writing spec to", dest)
err = ioutil.WriteFile(dest, contents, 0644)
if err != nil {
return err
}
}
return nil
}