start push

This commit is contained in:
jgsqware 2016-06-07 23:30:36 +02:00
parent 06acefc8e7
commit 82cdeb2371
6 changed files with 217 additions and 42 deletions

View File

@ -8,11 +8,12 @@ import (
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/coreos/clair/cmd/clairctl/docker" "github.com/coreos/clair/cmd/clairctl/docker"
"github.com/coreos/clair/cmd/clairctl/dockerdist" "github.com/coreos/clair/cmd/clairctl/dockerdist"
"github.com/docker/distribution/digest"
"github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/manifest/schema1"
"github.com/docker/docker/reference" "github.com/docker/docker/reference"
"github.com/docker/engine-api/client"
"github.com/docker/engine-api/types"
"github.com/spf13/cobra" "github.com/spf13/cobra"
dockercli "github.com/fsouza/go-dockerclient"
) )
const pullDockerTplt = ` const pullDockerTplt = `
@ -34,60 +35,75 @@ var pullDockerCmd = &cobra.Command{
} }
imageName := args[0] imageName := args[0]
var manifest schema1.SignedManifest
var named reference.Named
if !docker.IsLocal { if !docker.IsLocal {
n, manifest, err := dockerdist.DownloadManifest(imageName, true) n, m, err := dockerdist.DownloadManifest(imageName, true)
if err != nil { if err != nil {
fmt.Println(errInternalError) fmt.Println(errInternalError)
logrus.Fatalf("parsing image %q: %v", imageName, err) logrus.Fatalf("parsing image %q: %v", imageName, err)
} }
// Ensure that the manifest type is supported. // Ensure that the manifest type is supported.
switch manifest.(type) { switch m.(type) {
case *schema1.SignedManifest: case *schema1.SignedManifest:
manifest = m.(schema1.SignedManifest)
named = n
break break
default: default:
fmt.Println(errInternalError) fmt.Println(errInternalError)
logrus.Fatalf("only v1 manifests are currently supported") logrus.Fatalf("only v1 manifests are currently supported")
} }
data := struct {
V1Manifest *schema1.SignedManifest
Named reference.Named
}{
V1Manifest: manifest.(*schema1.SignedManifest),
Named: n,
}
err = template.Must(template.New("pull").Parse(pullDockerTplt)).Execute(os.Stdout, data) } else {
var err error
named, manifest, err = LocalManifest(imageName)
if err != nil { if err != nil {
fmt.Println(errInternalError) fmt.Println(errInternalError)
logrus.Fatalf("rendering image: %v", err) logrus.Fatalf("parsing image %q: %v", imageName, err)
} }
} else { }
localManifest(imageName)
data := struct {
V1Manifest schema1.SignedManifest
Named reference.Named
}{
V1Manifest: manifest,
Named: named,
}
err := template.Must(template.New("pull").Parse(pullDockerTplt)).Execute(os.Stdout, data)
if err != nil {
fmt.Println(errInternalError)
logrus.Fatalf("rendering image: %v", err)
} }
}, },
} }
func localManifest(imageName string) { func LocalManifest(imageName string) (reference.Named, schema1.SignedManifest, error) {
defaultHeaders := map[string]string{"User-Agent": "engine-api-cli-1.0"} manifest := schema1.SignedManifest{}
cli, err := client.NewClient("unix:///var/run/docker.sock", "v1.22", nil, defaultHeaders) // Parse the image name as a docker image reference.
named, err := reference.ParseNamed(imageName)
if err != nil { if err != nil {
panic(err) return nil, manifest, err
}
t := types.ImageListOptions{MatchName: imageName}
cli.ImageList(t)
// histories, err := cli.ImageHistory(context.Background(), imageName)
if err != nil {
panic(err)
} }
// for _, history := range histories { endpoint := "unix:///var/run/docker.sock"
// fmt.Println(history) client, _ := dockercli.NewClient(endpoint)
// } histories, _ := client.ImageHistory(imageName)
for _, history := range histories {
var d digest.Digest
d, err := digest.ParseDigest(history.ID)
if err != nil {
return nil, manifest, err
}
manifest.FSLayers = append(manifest.FSLayers, schema1.FSLayer{BlobSum: d})
}
return named, manifest, nil
} }
func init() { func init() {
RootCmd.AddCommand(pullDockerCmd) RootCmd.AddCommand(pullDockerCmd)
pullDockerCmd.Flags().BoolVarP(&docker.IsLocal, "local", "l", false, "Use local images") pullDockerCmd.Flags().BoolVarP(&docker.IsLocal, "local", "l", false, "Use local images")

View File

@ -1,14 +1,27 @@
package cmd package cmd
import ( import (
"bufio"
"compress/bzip2"
"compress/gzip"
"encoding/json"
"fmt" "fmt"
"io"
"os" "os"
"strings"
"syscall"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/artyom/untar"
"github.com/coreos/clair/cmd/clairctl/config"
"github.com/coreos/clair/cmd/clairctl/docker" "github.com/coreos/clair/cmd/clairctl/docker"
"github.com/coreos/clair/cmd/clairctl/dockerdist" "github.com/coreos/clair/cmd/clairctl/dockerdist"
"github.com/docker/distribution/digest"
"github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/manifest/schema1"
"github.com/docker/docker/reference"
"github.com/spf13/cobra" "github.com/spf13/cobra"
dockercli "github.com/fsouza/go-dockerclient"
) )
var pushDockerCmd = &cobra.Command{ var pushDockerCmd = &cobra.Command{
@ -24,7 +37,6 @@ var pushDockerCmd = &cobra.Command{
startLocalServer() startLocalServer()
imageName := args[0] imageName := args[0]
var image docker.Image
if !docker.IsLocal { if !docker.IsLocal {
image, manifest, err := dockerdist.DownloadManifest(imageName, true) image, manifest, err := dockerdist.DownloadManifest(imageName, true)
@ -52,31 +64,170 @@ var pushDockerCmd = &cobra.Command{
} }
} else { } else {
var err error named, err := reference.ParseNamed(imageName)
image, err = docker.Parse(imageName)
if err != nil { if err != nil {
fmt.Println(errInternalError) fmt.Println(errInternalError)
logrus.Fatalf("parsing local image %q: %v", imageName, err) logrus.Fatalf("pushing image %q: %v", imageName, err)
} }
err = docker.Prepare(&image) p, err := save(named)
logrus.Debugf("prepared image layers: %d", len(image.FsLayers))
if err != nil { if err != nil {
fmt.Println(errInternalError) fmt.Println(errInternalError)
logrus.Fatalf("preparing local image %q from history: %v", imageName, err) logrus.Fatalf("saving image %q: %v", imageName, err)
} }
logrus.Info("Pushing Image [OLD WAY] should be deprecated") m, err := historyFromManifest(p)
if err := docker.Push(image); err != nil { if err != nil {
if err != nil { fmt.Println(errInternalError)
fmt.Println(errInternalError) logrus.Fatalf("reading manifest %q: %v", imageName, err)
logrus.Fatalf("pushing image %q: %v", imageName, err)
}
} }
for _, layer := range m.FSLayers {
fmt.Println("ID: ", layer.BlobSum.String())
}
// var err error
// image, err = docker.Parse(imageName)
// if err != nil {
// fmt.Println(errInternalError)
// logrus.Fatalf("parsing local image %q: %v", imageName, err)
// }
// err = docker.Prepare(&image)
// logrus.Debugf("prepared image layers: %d", len(image.FsLayers))
// if err != nil {
// fmt.Println(errInternalError)
// logrus.Fatalf("preparing local image %q from history: %v", imageName, err)
// }
// logrus.Info("Pushing Image [OLD WAY] should be deprecated")
// if err := docker.Push(image); err != nil {
// if err != nil {
// fmt.Println(errInternalError)
// logrus.Fatalf("pushing image %q: %v", imageName, err)
// }
// }
} }
fmt.Printf("%v has been pushed to Clair\n", imageName) fmt.Printf("%v has been pushed to Clair\n", imageName)
}, },
} }
func historyFromManifest(path string) (*schema1.SignedManifest, error) {
mf, err := os.Open(path + "/manifest.json")
if err != nil {
return nil, err
}
defer mf.Close()
// https://github.com/docker/docker/blob/master/image/tarexport/tarexport.go#L17
type manifestItem struct {
Config string
RepoTags []string
Layers []string
}
var manifest []manifestItem
if err = json.NewDecoder(mf).Decode(&manifest); err != nil {
return nil, err
} else if len(manifest) != 1 {
return nil, err
}
var layers []string
for _, layer := range manifest[0].Layers {
layers = append(layers, strings.TrimSuffix(layer, "/layer.tar"))
}
var m schema1.SignedManifest
for _, layer := range manifest[0].Layers {
var d digest.Digest
fmt.Println(strings.TrimSuffix(layer, "/layer.tar"))
d, err := digest.ParseDigest("sha256:" + strings.TrimSuffix(layer, "/layer.tar"))
if err != nil {
return nil, err
}
m.FSLayers = append(m.FSLayers, schema1.FSLayer{BlobSum: d})
}
return &m, nil
}
func save(image reference.Named) (string, error) {
imageName := image.Name()
path := config.TmpLocal() + "/" + strings.Split(imageName, ":")[0] + "/blobs"
if _, err := os.Stat(path); os.IsExist(err) {
err := os.RemoveAll(path)
if err != nil {
return "", err
}
}
err := os.MkdirAll(path, 0755)
if err != nil {
return "", err
}
logrus.Debugln("docker image to save: ", imageName)
logrus.Debugln("saving in: ", path)
// open output file
fo, err := os.Create(path + "/output.tar")
if err != nil {
return "", err
}
// close fo on exit and check for its returned error
defer func() {
if err := fo.Close(); err != nil {
panic(err)
}
}()
// make a write buffer
w := bufio.NewWriter(fo)
endpoint := "unix:///var/run/docker.sock"
client, _ := dockercli.NewClient(endpoint)
err = client.ExportImage(dockercli.ExportImageOptions{Name: imageName, OutputStream: w})
if err != nil {
return "", err
}
err = openAndUntar(path+"/output.tar", path)
if err != nil {
return "", err
}
err = os.Remove(path + "/output.tar")
if err != nil {
return "", err
}
return path, err
}
func openAndUntar(name, dst string) error {
var rd io.Reader
f, err := os.Open(name)
if err != nil {
return err
}
defer f.Close()
rd = f
if strings.HasSuffix(name, ".gz") || strings.HasSuffix(name, ".tgz") {
gr, err := gzip.NewReader(f)
if err != nil {
return err
}
defer gr.Close()
rd = gr
} else if strings.HasSuffix(name, ".bz2") {
rd = bzip2.NewReader(f)
}
if err := os.MkdirAll(dst, os.ModeDir|os.ModePerm); err != nil {
return err
}
// resetting umask is essential to have exact permissions on unpacked
// files; it's not not put inside untar function as it changes
// process-wide umask
mask := syscall.Umask(0)
defer syscall.Umask(mask)
return untar.Untar(rd, dst)
}
func init() { func init() {
RootCmd.AddCommand(pushDockerCmd) RootCmd.AddCommand(pushDockerCmd)
pushDockerCmd.Flags().BoolVarP(&docker.IsLocal, "local", "l", false, "Use local images") pushDockerCmd.Flags().BoolVarP(&docker.IsLocal, "local", "l", false, "Use local images")

View File

@ -103,6 +103,10 @@ func Init(cfgFile string, logLevel string) {
clair.Config() clair.Config()
} }
func TmpLocal() string {
return viper.GetString("clairctl.tempFolder")
}
func values() config { func values() config {
return config{ return config{
Clair: clairConfig{ Clair: clairConfig{

View File

@ -101,3 +101,5 @@ import:
version: ^1.11.2 version: ^1.11.2
subpackages: subpackages:
- api/server/httputils - api/server/httputils
- package: github.com/mholt/archiver
version: ^1.0.0

1
vendor/github.com/fsouza/go-dockerclient generated vendored Submodule

@ -0,0 +1 @@
Subproject commit 9df1f25d542e79d7909ef321b5c13c5d34ea7f1d

1
vendor/github.com/mholt/archiver generated vendored Submodule

@ -0,0 +1 @@
Subproject commit 5374408853604727233976068707eaad9a40291b