tools/lib/image/image.go (68 lines of code) (raw):
// Copyright (c) 2016-2019 Uber Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package image
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"log"
"math/rand"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
)
func run(name string, args ...string) error {
stderr := new(bytes.Buffer)
cmd := exec.Command(name, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = stderr
if err := cmd.Run(); err != nil {
return fmt.Errorf("exec `%s`: %s, stderr:\n%s",
strings.Join(cmd.Args, " "), err, stderr.String())
}
return nil
}
// Generate creates a random image.
func Generate(size uint64, numLayers int) (name string, err error) {
dir, err := ioutil.TempDir("", "")
if err != nil {
return "", fmt.Errorf("temp dir: %s", err)
}
defer os.RemoveAll(dir)
name = fmt.Sprintf("kraken-test-image-%s", filepath.Base(dir))
dockerfile, err := os.Create(fmt.Sprintf("%s/Dockerfile", dir))
if err != nil {
return "", fmt.Errorf("create dockerfile: %s", err)
}
log.Printf("Generating dockerfile %s", dockerfile.Name())
if _, err := fmt.Fprintln(dockerfile, "FROM scratch"); err != nil {
return "", fmt.Errorf("fprint dockerfile: %s", err)
}
layerSize := size / uint64(numLayers)
for i := 0; i < numLayers; i++ {
f, err := os.Create(fmt.Sprintf("%s/file_%d", dir, i))
if err != nil {
return "", fmt.Errorf("create file: %s", err)
}
r := io.LimitReader(rand.New(rand.NewSource(time.Now().Unix())), int64(layerSize))
if _, err := io.Copy(f, r); err != nil {
return "", fmt.Errorf("copy rand: %s", err)
}
layerName := filepath.Base(f.Name())
if _, err := fmt.Fprintf(dockerfile, "COPY %s /\n", layerName); err != nil {
return "", fmt.Errorf("fprint dockerfile: %s", err)
}
}
if err := run("sudo", "docker", "build", "-t", name, dir); err != nil {
return "", err
}
return name + ":latest", nil
}
// Push pushes an image to a Kraken proxy.
func Push(name string, proxy string) error {
proxyName := proxy + "/" + name
log.Printf("Pushing %s to %s", name, proxyName)
if err := run("sudo", "docker", "tag", name, proxyName); err != nil {
return err
}
return run("sudo", "docker", "push", proxyName)
}