Skip to content

Commit

Permalink
introduce linuxkit pkg collect
Browse files Browse the repository at this point in the history
Signed-off-by: Robin Winkelewski <w9ncontact@gmail.com>
  • Loading branch information
w9n committed Dec 17, 2017
1 parent e62756f commit 557bb5c
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/cmd/linuxkit/pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ func pkgUsage() {

fmt.Printf("'subcommand' is one of:\n")
fmt.Printf(" build\n")
fmt.Printf(" collect\n")
fmt.Printf(" push\n")
fmt.Printf(" show-tag\n")
fmt.Printf("\n")
Expand Down Expand Up @@ -52,6 +53,8 @@ func pkg(args []string) {
switch args[0] {
case "build":
pkgBuild(args[1:])
case "collect":
pkgCollect(args[1:])
case "push":
pkgPush(args[1:])
case "show-tag":
Expand Down
46 changes: 46 additions & 0 deletions src/cmd/linuxkit/pkg_collect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package main

import (
"flag"
"fmt"
"os"
"path/filepath"

"github.com/linuxkit/linuxkit/src/cmd/linuxkit/pkglib"
log "github.com/sirupsen/logrus"
)

func pkgCollect(args []string) {
flags := flag.NewFlagSet("pkg collect", flag.ExitOnError)
flags.Usage = func() {
invoked := filepath.Base(os.Args[0])
fmt.Fprintf(os.Stderr, "USAGE: %s pkg collect [options] <file>[.yml]\n", invoked)
fmt.Fprintf(os.Stderr, "\n")
flags.PrintDefaults()
}

buildPkg := flags.String("pkgroot", "", "path to pkg source of moby config")
if err := flags.Parse(args); err != nil {
log.Fatal("Unable to parse args")
}

remArgs := flags.Args()

if len(remArgs) == 0 {
fmt.Println("Please specify a moby configuration file")
flags.Usage()
os.Exit(1)
}
m := GetMoby(remArgs)

if info, err := os.Stat(*buildPkg); err == nil && info.IsDir() {
err := pkglib.Collect(m, *buildPkg)
if err != nil {
log.Fatalln(err.Error())
}

} else {
log.Fatalf("Pkg dir is not valid: %v", err)
}

}
151 changes: 151 additions & 0 deletions src/cmd/linuxkit/pkglib/collect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package pkglib

import (
"crypto/sha1"
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"

moby "github.com/moby/tool/src/moby"

yaml "gopkg.in/yaml.v2"
)

const pkgFile = "build.yml"

type imageInfo struct {
repo, name, tag string
value *string
}

//Collect searches for placeHolder in configs image label and replaces it with its package hash if found in pkgDir. If none pkg is found it errors
func Collect(m moby.Moby, pkgDir string) error {

imageTemplates := getImageTemplates(m)

err := walkDir(pkgDir, imageTemplates)
if err != nil {
return err
}

bytes, err := yaml.Marshal(&m)
if err != nil {
return err
}

h := sha1.New()
h.Write(bytes)
if err != nil {
return err
}
filename := fmt.Sprintf("%x.yml", h.Sum(nil))

err = ioutil.WriteFile(filename, bytes, 0644)
if err != nil {
return err
}
fmt.Println("created " + filename)
return nil
}

//this should not go deeper into a dir when build.yml is found.
func walkDir(pkgDir string, imageTemplates []imageInfo) error {
err := filepath.Walk(pkgDir, func(path string, f os.FileInfo, err error) error {
if f.Name() == pkgFile {

b, err := ioutil.ReadFile(path)
if err != nil {
return err
}
pi := pkgInfo{}
if err := yaml.Unmarshal(b, &pi); err != nil {
return err
}

if pi.Image == "" {
return fmt.Errorf("Image field is required")
}
for i := len(imageTemplates) - 1; i >= 0; i-- {
if imageTemplates[i].name == pi.Image {
err = substitute(imageTemplates[i], path, pi)
if err != nil {
return err
}
imageTemplates = append(imageTemplates[:i], imageTemplates[i+1:]...)
}
}
}
return err
})
if err != nil {
return err
}

var errs []string
for _, imageString := range imageTemplates {
errs = append(errs, fmt.Sprintln("could not find pkg for:", *imageString.value))
}
if len(errs) != 0 {
return errors.New(strings.Join(errs, ""))
}
return nil
}

func substitute(imageString imageInfo, path string, pi pkgInfo) error {
path = filepath.Dir(path)
git, err := newGit(path)
if err != nil {
return err
}
commit, err := git.commitHash("HEAD")
if err != nil {
return err
}

treeHash, err := git.treeHash(path, commit)
if err != nil {
return err
}

old := *imageString.value
*imageString.value = fmt.Sprintf("%v/%v:%v", imageString.repo, imageString.name, treeHash)
fmt.Println("template: " + old)
fmt.Println(" hashed: " + *imageString.value)
return nil
}

func getImageTemplates(m moby.Moby) []imageInfo {
var images []*moby.Image
var imageStrings []*string
var tagTemplates []imageInfo

images = append(images, m.Onboot...)
images = append(images, m.Services...)
images = append(images, m.Onshutdown...)

for _, v := range images {
imageStrings = append(imageStrings, &v.Image)
}
for i := range m.Init {
imageStrings = append(imageStrings, &m.Init[i])
}

for _, imageString := range imageStrings {
tagSplit := strings.Split(*imageString, ":")
tag := tagSplit[len(tagSplit)-1]
if isTagTemplate(tag) {
imageSplit := strings.Split(tagSplit[0], "/")
name := imageSplit[1]
repo := imageSplit[0]
tagTemplates = append(tagTemplates, imageInfo{tag: tag, name: name, repo: repo, value: imageString})
}
}
return tagTemplates
}

func isTagTemplate(tag string) bool {
return tag[:1] == "<" && tag[len(tag)-1:] == ">"
}

0 comments on commit 557bb5c

Please sign in to comment.