Updated vendor, for container-diff

This commit is contained in:
Priya Wadhwa
2018-04-11 14:06:23 -07:00
parent ce2b515d49
commit 4d048d1607
181 changed files with 3326 additions and 1841 deletions
@@ -1,5 +1,5 @@
/*
Copyright 2017 Google, Inc. All rights reserved.
Copyright 2018 Google, Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -20,13 +20,14 @@ import (
"bytes"
"compress/gzip"
"encoding/json"
img "github.com/containers/image/image"
"github.com/containers/image/types"
"io"
"io/ioutil"
"strings"
"time"
"github.com/containers/image/manifest"
"github.com/containers/image/types"
digest "github.com/opencontainers/go-digest"
)
@@ -76,28 +77,46 @@ func (m *MutableSource) GetManifest(_ *digest.Digest) ([]byte, string, error) {
// populateManifestAndConfig parses the raw manifest and configs, storing them on the struct.
func (m *MutableSource) populateManifestAndConfig() error {
mfstBytes, _, err := m.ProxySource.GetManifest(nil)
context := &types.SystemContext{
OSChoice: "linux",
ArchitectureChoice: "amd64",
}
image, err := m.ProxySource.Ref.NewImage(context)
if err != nil {
return err
}
defer image.Close()
// First get manifest
mfstBytes, mfstType, err := image.Manifest()
if err != nil {
return err
}
if mfstType == manifest.DockerV2ListMediaType {
// We need to select a manifest digest from the manifest list
unparsedImage := img.UnparsedInstance(m.ImageSource, nil)
mfstDigest, err := img.ChooseManifestInstanceFromManifestList(context, unparsedImage)
if err != nil {
return err
}
mfstBytes, _, err = m.ProxySource.GetManifest(&mfstDigest)
if err != nil {
return err
}
}
m.mfst, err = manifest.Schema2FromManifest(mfstBytes)
if err != nil {
return err
}
bi := types.BlobInfo{Digest: m.mfst.ConfigDescriptor.Digest}
r, _, err := m.GetBlob(bi)
// Now, get config
configBlob, err := image.ConfigBlob()
if err != nil {
return err
}
cfgBytes, err := ioutil.ReadAll(r)
if err != nil {
return err
}
return json.Unmarshal(cfgBytes, &m.cfg)
return json.Unmarshal(configBlob, &m.cfg)
}
// GetBlob first checks the stored "extra" blobs, then proxies the call to the original source.
@@ -1,5 +1,5 @@
/*
Copyright 2017 Google, Inc. All rights reserved.
Copyright 2018 Google, Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -32,6 +32,7 @@ func NewProxySource(ref types.ImageReference) (*ProxySource, error) {
if err != nil {
return nil, err
}
defer src.Close()
img, err := ref.NewImage(nil)
if err != nil {
return nil, err
@@ -1,5 +1,5 @@
/*
Copyright 2017 Google, Inc. All rights reserved.
Copyright 2018 Google, Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -32,21 +32,25 @@ type CloudPrepper struct {
ImageSource types.ImageSource
}
func (p CloudPrepper) Name() string {
func (p *CloudPrepper) Name() string {
return "Cloud Registry"
}
func (p CloudPrepper) GetSource() string {
func (p *CloudPrepper) GetSource() string {
return p.Source
}
func (p CloudPrepper) GetImage() (Image, error) {
func (p *CloudPrepper) SetSource(source string) {
p.Source = source
}
func (p *CloudPrepper) GetImage() (Image, error) {
image, err := getImage(p)
image.Type = ImageTypeCloud
return image, err
}
func (p CloudPrepper) GetFileSystem() (string, error) {
func (p *CloudPrepper) GetFileSystem() (string, error) {
ref, err := docker.ParseReference("//" + p.Source)
if err != nil {
return "", err
@@ -62,7 +66,7 @@ func (p CloudPrepper) GetFileSystem() (string, error) {
return path, GetFileSystemFromReference(ref, p.ImageSource, path, nil)
}
func (p CloudPrepper) GetConfig() (ConfigSchema, error) {
func (p *CloudPrepper) GetConfig() (ConfigSchema, error) {
ref, err := docker.ParseReference("//" + p.Source)
if err != nil {
return ConfigSchema{}, err
@@ -1,5 +1,5 @@
/*
Copyright 2017 Google, Inc. All rights reserved.
Copyright 2018 Google, Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -32,21 +32,25 @@ type DaemonPrepper struct {
Client *client.Client
}
func (p DaemonPrepper) Name() string {
func (p *DaemonPrepper) Name() string {
return "Local Daemon"
}
func (p DaemonPrepper) GetSource() string {
func (p *DaemonPrepper) GetSource() string {
return p.Source
}
func (p DaemonPrepper) GetImage() (Image, error) {
func (p *DaemonPrepper) SetSource(source string) {
p.Source = source
}
func (p *DaemonPrepper) GetImage() (Image, error) {
image, err := getImage(p)
image.Type = ImageTypeDaemon
return image, err
}
func (p DaemonPrepper) GetFileSystem() (string, error) {
func (p *DaemonPrepper) GetFileSystem() (string, error) {
ref, err := daemon.ParseReference(p.Source)
if err != nil {
return "", err
@@ -56,6 +60,7 @@ func (p DaemonPrepper) GetFileSystem() (string, error) {
if err != nil {
return "", err
}
defer src.Close()
sanitizedName := strings.Replace(p.Source, ":", "", -1)
sanitizedName = strings.Replace(sanitizedName, "/", "", -1)
@@ -67,7 +72,7 @@ func (p DaemonPrepper) GetFileSystem() (string, error) {
return path, GetFileSystemFromReference(ref, src, path, nil)
}
func (p DaemonPrepper) GetConfig() (ConfigSchema, error) {
func (p *DaemonPrepper) GetConfig() (ConfigSchema, error) {
ref, err := daemon.ParseReference(p.Source)
if err != nil {
return ConfigSchema{}, err
@@ -75,7 +80,7 @@ func (p DaemonPrepper) GetConfig() (ConfigSchema, error) {
return getConfigFromReference(ref, p.Source)
}
func (p DaemonPrepper) GetHistory() []ImageHistoryItem {
func (p *DaemonPrepper) GetHistory() []ImageHistoryItem {
history, err := p.Client.ImageHistory(context.Background(), p.Source)
if err != nil {
logrus.Errorf("Could not obtain image history for %s: %s", p.Source, err)
@@ -1,5 +1,5 @@
/*
Copyright 2017 Google, Inc. All rights reserved.
Copyright 2018 Google, Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,5 +1,5 @@
/*
Copyright 2017 Google, Inc. All rights reserved.
Copyright 2018 Google, Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/*
Copyright 2017 Google, Inc. All rights reserved.
Copyright 2018 Google, Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -20,8 +20,10 @@ import (
"archive/tar"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"sort"
"strings"
"github.com/GoogleCloudPlatform/container-diff/cmd/util/output"
@@ -38,6 +40,7 @@ type Prepper interface {
GetFileSystem() (string, error)
GetImage() (Image, error)
GetSource() string
SetSource(string)
}
type ImageType int
@@ -84,13 +87,60 @@ type ImageHistoryItem struct {
}
type ConfigObject struct {
Env []string `json:"Env"`
Entrypoint []string `json:"Entrypoint"`
Hostname string
Domainname string
User string
AttachStdin bool
AttachStdout bool
AttachStderr bool
ExposedPorts map[string]struct{} `json:"ExposedPorts"`
Cmd []string `json:"Cmd"`
Volumes map[string]struct{} `json:"Volumes"`
Workdir string `json:"WorkingDir"`
Labels map[string]string `json:"Labels"`
Tty bool
OpenStdin bool
StdinOnce bool
Env []string `json:"Env"`
Cmd []string `json:"Cmd"`
// Healthcheck *HealthConfig
ArgsEscaped bool `json:",omitempty"`
Image string
Volumes map[string]struct{} `json:"Volumes"`
Workdir string `json:"WorkingDir"`
Entrypoint []string `json:"Entrypoint"`
NetworkDisabled bool `json:",omitempty"`
MacAddress string `json:",omitempty"`
OnBuild []string
Labels map[string]string `json:"Labels"`
StopSignal string `json:",omitempty"`
StopTimeout *int `json:",omitempty"`
Shell []string `json:",omitempty"`
}
func (c ConfigObject) AsList() []string {
return []string{
fmt.Sprintf("Hostname: %s", c.Hostname),
fmt.Sprintf("Domainname: %s", c.Domainname),
fmt.Sprintf("User: %s", c.User),
fmt.Sprintf("AttachStdin: %t", c.AttachStdin),
fmt.Sprintf("AttachStdout: %t", c.AttachStdout),
fmt.Sprintf("AttachStderr: %t", c.AttachStderr),
fmt.Sprintf("ExposedPorts: %v", sortMap(c.ExposedPorts)),
fmt.Sprintf("Tty: %t", c.Tty),
fmt.Sprintf("OpenStdin: %t", c.OpenStdin),
fmt.Sprintf("StdinOnce: %t", c.StdinOnce),
fmt.Sprintf("Env: %s", strings.Join(c.Env, ",")),
fmt.Sprintf("Cmd: %s", strings.Join(c.Cmd, ",")),
fmt.Sprintf("ArgsEscaped: %t", c.ArgsEscaped),
fmt.Sprintf("Image: %s", c.Image),
fmt.Sprintf("Volumes: %v", sortMap(c.Volumes)),
fmt.Sprintf("Workdir: %s", c.Workdir),
fmt.Sprintf("Entrypoint: %s", strings.Join(c.Entrypoint, ",")),
fmt.Sprintf("NetworkDisabled: %t", c.NetworkDisabled),
fmt.Sprintf("MacAddress: %s", c.MacAddress),
fmt.Sprintf("OnBuild: %s", strings.Join(c.OnBuild, ",")),
fmt.Sprintf("Labels: %v", c.Labels),
fmt.Sprintf("StopSignal: %s", c.StopSignal),
fmt.Sprintf("StopTimeout: %d", c.StopTimeout),
fmt.Sprintf("Shell: %s", strings.Join(c.Shell, ",")),
}
}
type ConfigSchema struct {
@@ -99,10 +149,17 @@ type ConfigSchema struct {
}
func getImage(p Prepper) (Image, error) {
// see if the image name has tag provided, if not add latest as tag
if !IsTar(p.GetSource()) && !HasTag(p.GetSource()) {
p.SetSource(p.GetSource() + LatestTag)
}
output.PrintToStdErr("Retrieving image %s from source %s\n", p.GetSource(), p.Name())
imgPath, err := p.GetFileSystem()
if err != nil {
return Image{}, err
// return image with FSPath so it can be cleaned up
return Image{
FSPath: imgPath,
}, err
}
config, err := p.GetConfig()
@@ -128,6 +185,14 @@ func getImageFromTar(tarPath string) (string, error) {
}
func GetFileSystemFromReference(ref types.ImageReference, imgSrc types.ImageSource, path string, whitelist []string) error {
var err error
if imgSrc == nil {
imgSrc, err = ref.NewImageSource(nil)
}
if err != nil {
return err
}
defer imgSrc.Close()
img, err := ref.NewImage(nil)
if err != nil {
return err
@@ -208,7 +273,16 @@ func CleanupImage(image Image) {
if image.FSPath != "" {
logrus.Infof("Removing image filesystem directory %s from system", image.FSPath)
if err := os.RemoveAll(image.FSPath); err != nil {
logrus.Error(err.Error())
logrus.Warn(err.Error())
}
}
}
func sortMap(m map[string]struct{}) string {
pairs := make([]string, 0)
for key := range m {
pairs = append(pairs, fmt.Sprintf("%s:%s", key, m[key]))
}
sort.Strings(pairs)
return strings.Join(pairs, " ")
}
@@ -1,5 +1,5 @@
/*
Copyright 2017 Google, Inc. All rights reserved.
Copyright 2018 Google, Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -21,11 +21,14 @@ import (
"io/ioutil"
"os"
"path/filepath"
"regexp"
"github.com/docker/docker/pkg/system"
"github.com/sirupsen/logrus"
)
const LatestTag string = ":latest"
func GetImageLayers(pathToImage string) []string {
layers := []string{}
contents, err := ioutil.ReadDir(pathToImage)
@@ -67,3 +70,9 @@ func copyToFile(outfile string, r io.Reader) error {
return nil
}
// checks to see if an image string contains a tag.
func HasTag(image string) bool {
tagRegex := regexp.MustCompile(".*:[^/]+$")
return tagRegex.MatchString(image)
}
@@ -1,5 +1,5 @@
/*
Copyright 2017 Google, Inc. All rights reserved.
Copyright 2018 Google, Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -32,25 +32,29 @@ type TarPrepper struct {
Client *client.Client
}
func (p TarPrepper) Name() string {
func (p *TarPrepper) Name() string {
return "Tar Archive"
}
func (p TarPrepper) GetSource() string {
func (p *TarPrepper) GetSource() string {
return p.Source
}
func (p TarPrepper) GetImage() (Image, error) {
func (p *TarPrepper) SetSource(source string) {
p.Source = source
}
func (p *TarPrepper) GetImage() (Image, error) {
image, err := getImage(p)
image.Type = ImageTypeTar
return image, err
}
func (p TarPrepper) GetFileSystem() (string, error) {
func (p *TarPrepper) GetFileSystem() (string, error) {
return getImageFromTar(p.Source)
}
func (p TarPrepper) GetConfig() (ConfigSchema, error) {
func (p *TarPrepper) GetConfig() (ConfigSchema, error) {
tempDir, err := ioutil.TempDir("", ".container-diff")
if err != nil {
return ConfigSchema{}, nil
+62 -4
View File
@@ -1,5 +1,5 @@
/*
Copyright 2017 Google, Inc. All rights reserved.
Copyright 2018 Google, Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,14 +18,26 @@ package util
import (
"archive/tar"
"github.com/sirupsen/logrus"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
// Map of target:linkname
var hardlinks = make(map[string]string)
type OriginalPerm struct {
path string
perm os.FileMode
}
func unpackTar(tr *tar.Reader, path string, whitelist []string) error {
originalPerms := make([]OriginalPerm, 0)
for {
header, err := tr.Next()
if err == io.EOF {
@@ -37,7 +49,7 @@ func unpackTar(tr *tar.Reader, path string, whitelist []string) error {
return err
}
if strings.Contains(header.Name, ".wh.") {
rmPath := filepath.Join(path, header.Name)
rmPath := filepath.Clean(filepath.Join(path, header.Name))
// Remove the .wh file if it was extracted.
if _, err := os.Stat(rmPath); !os.IsNotExist(err) {
if err := os.Remove(rmPath); err != nil {
@@ -52,7 +64,7 @@ func unpackTar(tr *tar.Reader, path string, whitelist []string) error {
}
continue
}
target := filepath.Join(path, header.Name)
target := filepath.Clean(filepath.Join(path, header.Name))
// Make sure the target isn't part of the whitelist
if checkWhitelist(target, whitelist) {
continue
@@ -63,6 +75,17 @@ func unpackTar(tr *tar.Reader, path string, whitelist []string) error {
// if its a dir and it doesn't exist create it
case tar.TypeDir:
if _, err := os.Stat(target); os.IsNotExist(err) {
if mode.Perm()&(1<<(uint(7))) == 0 {
logrus.Debugf("Write permission bit not set on %s by default; setting manually", target)
originalMode := mode
mode = mode | (1 << uint(7))
// keep track of original file permission to reset later
originalPerms = append(originalPerms, OriginalPerm{
path: target,
perm: originalMode,
})
}
logrus.Debugf("Creating directory %s with permissions %v", target, mode)
if err := os.MkdirAll(target, mode); err != nil {
return err
}
@@ -91,6 +114,7 @@ func unpackTar(tr *tar.Reader, path string, whitelist []string) error {
}
}
logrus.Debugf("Creating file %s with permissions %v", target, mode)
currFile, err := os.Create(target)
if err != nil {
logrus.Errorf("Error creating file %s %s", target, err)
@@ -119,8 +143,42 @@ func unpackTar(tr *tar.Reader, path string, whitelist []string) error {
if err = os.Symlink(header.Linkname, target); err != nil {
logrus.Errorf("Failed to create symlink between %s and %s: %s", header.Linkname, target, err)
}
case tar.TypeLink:
linkname := filepath.Clean(filepath.Join(path, header.Linkname))
// Check if the linkname already exists
if _, err := os.Stat(linkname); !os.IsNotExist(err) {
// If it exists, create the hard link
resolveHardlink(linkname, target)
} else {
hardlinks[target] = linkname
}
}
}
for target, linkname := range hardlinks {
logrus.Info("Resolving hard links.")
if _, err := os.Stat(linkname); !os.IsNotExist(err) {
// If it exists, create the hard link
if err := resolveHardlink(linkname, target); err != nil {
return errors.Wrap(err, fmt.Sprintf("Unable to create hard link from %s to %s", linkname, target))
}
}
}
// reset all original file
for _, perm := range originalPerms {
if err := os.Chmod(perm.path, perm.perm); err != nil {
return err
}
}
return nil
}
func resolveHardlink(linkname, target string) error {
if err := os.Link(linkname, target); err != nil {
return err
}
logrus.Debugf("Created hard link from %s to %s", linkname, target)
return nil
}