mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-19 17:26:28 +00:00
Add linuxkit build, using vendored moby/tool as a library
Signed-off-by: Justin Cormack <justin.cormack@docker.com>
This commit is contained in:
parent
c928acf73e
commit
eef8ab7757
215
src/cmd/linuxkit/build.go
Normal file
215
src/cmd/linuxkit/build.go
Normal file
@ -0,0 +1,215 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/moby/tool/src/moby"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const defaultNameForStdin = "moby"
|
||||
|
||||
type formatList []string
|
||||
|
||||
func (f *formatList) String() string {
|
||||
return fmt.Sprint(*f)
|
||||
}
|
||||
|
||||
func (f *formatList) Set(value string) error {
|
||||
// allow comma separated options or multiple options
|
||||
for _, cs := range strings.Split(value, ",") {
|
||||
*f = append(*f, cs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Process the build arguments and execute build
|
||||
func build(args []string) {
|
||||
var buildFormats formatList
|
||||
|
||||
outputTypes := moby.OutputTypes()
|
||||
|
||||
buildCmd := flag.NewFlagSet("build", flag.ExitOnError)
|
||||
buildCmd.Usage = func() {
|
||||
fmt.Printf("USAGE: %s build [options] <file>[.yml] | -\n\n", os.Args[0])
|
||||
fmt.Printf("Options:\n")
|
||||
buildCmd.PrintDefaults()
|
||||
}
|
||||
buildName := buildCmd.String("name", "", "Name to use for output files")
|
||||
buildDir := buildCmd.String("dir", "", "Directory for output files, default current directory")
|
||||
buildOutputFile := buildCmd.String("o", "", "File to use for a single output, or '-' for stdout")
|
||||
buildSize := buildCmd.String("size", "1024M", "Size for output image, if supported and fixed size")
|
||||
buildPull := buildCmd.Bool("pull", false, "Always pull images")
|
||||
buildDisableTrust := buildCmd.Bool("disable-content-trust", false, "Skip image trust verification specified in trust section of config (default false)")
|
||||
buildCmd.Var(&buildFormats, "format", "Formats to create [ "+strings.Join(outputTypes, " ")+" ]")
|
||||
|
||||
if err := buildCmd.Parse(args); err != nil {
|
||||
log.Fatal("Unable to parse args")
|
||||
}
|
||||
remArgs := buildCmd.Args()
|
||||
|
||||
if len(remArgs) == 0 {
|
||||
fmt.Println("Please specify a configuration file")
|
||||
buildCmd.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
name := *buildName
|
||||
if name == "" {
|
||||
conf := remArgs[len(remArgs)-1]
|
||||
if conf == "-" {
|
||||
name = defaultNameForStdin
|
||||
} else {
|
||||
name = strings.TrimSuffix(filepath.Base(conf), filepath.Ext(conf))
|
||||
}
|
||||
}
|
||||
|
||||
// There are two types of output, they will probably be split into "build" and "package" later
|
||||
// the basic outputs are tarballs, while the packaged ones are the LinuxKit out formats that
|
||||
// cannot be streamed but we do allow multiple ones to be built.
|
||||
|
||||
if len(buildFormats) == 0 {
|
||||
if *buildOutputFile == "" {
|
||||
buildFormats = formatList{"kernel+initrd"}
|
||||
} else {
|
||||
buildFormats = formatList{"tar"}
|
||||
}
|
||||
}
|
||||
|
||||
log.Debugf("Formats selected: %s", buildFormats.String())
|
||||
|
||||
if len(buildFormats) > 1 {
|
||||
for _, o := range buildFormats {
|
||||
if moby.Streamable(o) {
|
||||
log.Fatalf("Format type %s must be the only format specified", o)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(buildFormats) == 1 && moby.Streamable(buildFormats[0]) {
|
||||
if *buildOutputFile == "" {
|
||||
*buildOutputFile = filepath.Join(*buildDir, name+"."+buildFormats[0])
|
||||
// stop the errors in the validation below
|
||||
*buildName = ""
|
||||
*buildDir = ""
|
||||
}
|
||||
} else {
|
||||
err := moby.ValidateFormats(buildFormats)
|
||||
if err != nil {
|
||||
log.Errorf("Error parsing formats: %v", err)
|
||||
buildCmd.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
var outputFile *os.File
|
||||
if *buildOutputFile != "" {
|
||||
if len(buildFormats) > 1 {
|
||||
log.Fatal("The -output option can only be specified when generating a single output format")
|
||||
}
|
||||
if *buildName != "" {
|
||||
log.Fatal("The -output option cannot be specified with -name")
|
||||
}
|
||||
if *buildDir != "" {
|
||||
log.Fatal("The -output option cannot be specified with -dir")
|
||||
}
|
||||
if !moby.Streamable(buildFormats[0]) {
|
||||
log.Fatalf("The -output option cannot be specified for build type %s as it cannot be streamed", buildFormats[0])
|
||||
}
|
||||
if *buildOutputFile == "-" {
|
||||
outputFile = os.Stdout
|
||||
} else {
|
||||
var err error
|
||||
outputFile, err = os.Create(*buildOutputFile)
|
||||
if err != nil {
|
||||
log.Fatalf("Cannot open output file: %v", err)
|
||||
}
|
||||
defer outputFile.Close()
|
||||
}
|
||||
}
|
||||
|
||||
size, err := getDiskSizeMB(*buildSize)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to parse disk size: %v", err)
|
||||
}
|
||||
|
||||
var m moby.Moby
|
||||
for _, arg := range remArgs {
|
||||
var config []byte
|
||||
if conf := arg; conf == "-" {
|
||||
var err error
|
||||
config, err = ioutil.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
log.Fatalf("Cannot read stdin: %v", err)
|
||||
}
|
||||
} else if strings.HasPrefix(arg, "http://") || strings.HasPrefix(arg, "https://") {
|
||||
buffer := new(bytes.Buffer)
|
||||
response, err := http.Get(arg)
|
||||
if err != nil {
|
||||
log.Fatalf("Cannot fetch remote yaml file: %v", err)
|
||||
}
|
||||
defer response.Body.Close()
|
||||
_, err = io.Copy(buffer, response.Body)
|
||||
if err != nil {
|
||||
log.Fatalf("Error reading http body: %v", err)
|
||||
}
|
||||
config = buffer.Bytes()
|
||||
} else {
|
||||
var err error
|
||||
config, err = ioutil.ReadFile(conf)
|
||||
if err != nil {
|
||||
log.Fatalf("Cannot open config file: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
c, err := moby.NewConfig(config)
|
||||
if err != nil {
|
||||
log.Fatalf("Invalid config: %v", err)
|
||||
}
|
||||
m, err = moby.AppendConfig(m, c)
|
||||
if err != nil {
|
||||
log.Fatalf("Cannot append config files: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if *buildDisableTrust {
|
||||
log.Debugf("Disabling content trust checks for this build")
|
||||
m.Trust = moby.TrustConfig{}
|
||||
}
|
||||
|
||||
var buf *bytes.Buffer
|
||||
var w io.Writer
|
||||
if outputFile != nil {
|
||||
w = outputFile
|
||||
} else {
|
||||
buf = new(bytes.Buffer)
|
||||
w = buf
|
||||
}
|
||||
// this is a weird interface, but currently only streamable types can have additional files
|
||||
// need to split up the base tarball outputs from the secondary stages
|
||||
var tp string
|
||||
if moby.Streamable(buildFormats[0]) {
|
||||
tp = buildFormats[0]
|
||||
}
|
||||
err = moby.Build(m, w, *buildPull, tp)
|
||||
if err != nil {
|
||||
log.Fatalf("%v", err)
|
||||
}
|
||||
|
||||
if outputFile == nil {
|
||||
image := buf.Bytes()
|
||||
log.Infof("Create outputs:")
|
||||
err = moby.Formats(filepath.Join(*buildDir, name), image, buildFormats, size)
|
||||
if err != nil {
|
||||
log.Fatalf("Error writing outputs: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
@ -75,6 +75,7 @@ func main() {
|
||||
flag.Usage = func() {
|
||||
fmt.Printf("USAGE: %s [options] COMMAND\n\n", filepath.Base(os.Args[0]))
|
||||
fmt.Printf("Commands:\n")
|
||||
fmt.Printf(" build Build an image from a YAML file\n")
|
||||
fmt.Printf(" metadata Metadata utilities\n")
|
||||
fmt.Printf(" pkg Package building\n")
|
||||
fmt.Printf(" push Push a VM image to a cloud or image store\n")
|
||||
@ -117,6 +118,8 @@ func main() {
|
||||
}
|
||||
|
||||
switch args[0] {
|
||||
case "build":
|
||||
build(args[1:])
|
||||
case "metadata":
|
||||
metadata(args[1:])
|
||||
case "pkg":
|
||||
|
Loading…
Reference in New Issue
Block a user