Skip to content
This repository was archived by the owner on Mar 27, 2024. It is now read-only.

remove ImagePrepper in favor of processing individual preppers directly #101

Merged
merged 7 commits into from
Sep 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ language: go
os: linux
go: 1.8.3

sudo: required

services:
- docker

go_import_path: github.com/GoogleCloudPlatform/container-diff

addons:
Expand Down
4 changes: 1 addition & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ test: $(BUILD_DIR)/$(PROJECT)

.PHONY: integration
integration: $(BUILD_DIR)/$(PROJECT)
go test -v -tags integration $(REPOPATH)/tests
go test -v -tags integration $(REPOPATH)/tests -timeout 20m

.PHONY: release
release: cross
Expand All @@ -71,5 +71,3 @@ release: cross
.PHONY: clean
clean:
rm -rf $(BUILD_DIR)


14 changes: 8 additions & 6 deletions cmd/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,22 +56,24 @@ func checkAnalyzeArgNum(args []string) error {
return nil
}

func analyzeImage(imageArg string, analyzerArgs []string) error {
func analyzeImage(imageName string, analyzerArgs []string) error {
analyzeTypes, err := differs.GetAnalyzers(analyzerArgs)
if err != nil {
return err
}

cli, err := NewClient()
cli, err := pkgutil.NewClient()
if err != nil {
return fmt.Errorf("Error getting docker client: %s", err)
}
defer cli.Close()
ip := pkgutil.ImagePrepper{
Source: imageArg,
Client: cli,

prepper, err := getPrepperForImage(imageName)
if err != nil {
return err
}
image, err := ip.GetImage()

image, err := prepper.GetImage()

if !save {
defer pkgutil.CleanupImage(image)
Expand Down
16 changes: 9 additions & 7 deletions cmd/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func diffImages(image1Arg, image2Arg string, diffArgs []string) error {
return err
}

cli, err := NewClient()
cli, err := pkgutil.NewClient()
if err != nil {
return err
}
Expand All @@ -77,17 +77,20 @@ func diffImages(image1Arg, image2Arg string, diffArgs []string) error {
image1Arg: {},
image2Arg: {},
}
// TODO: fix error handling here
for imageArg := range imageMap {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a TODO or open a bug to fix up this code, the error handling isn't really correct. You're not making it worse here, bu I want to make sure we don't forget.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

go func(imageName string, imageMap map[string]*pkgutil.Image) {
defer wg.Done()
ip := pkgutil.ImagePrepper{
Source: imageName,
Client: cli,

prepper, err := getPrepperForImage(imageName)
if err != nil {
glog.Error(err)
return
}
image, err := ip.GetImage()
image, err := prepper.GetImage()
imageMap[imageName] = &image
if err != nil {
glog.Errorf("Diff may be inaccurate: %s", err.Error())
glog.Warningf("Diff may be inaccurate: %s", err)
}
}(imageArg, imageMap)
}
Expand All @@ -109,7 +112,6 @@ func diffImages(image1Arg, image2Arg string, diffArgs []string) error {
if save {
glog.Infof("Images were saved at %s and %s", imageMap[image1Arg].FSPath,
imageMap[image2Arg].FSPath)

}
return nil
}
Expand Down
49 changes: 38 additions & 11 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ limitations under the License.
package cmd

import (
"context"
"errors"
goflag "flag"
"fmt"
"sort"
"strings"

"github.com/GoogleCloudPlatform/container-diff/differs"
pkgutil "github.com/GoogleCloudPlatform/container-diff/pkg/util"
"github.com/GoogleCloudPlatform/container-diff/util"
"github.com/docker/docker/client"
"github.com/golang/glog"
Expand All @@ -37,20 +38,22 @@ var types string

type validatefxn func(args []string) error

const (
DaemonPrefix = "daemon://"
RemotePrefix = "remote://"
)

var RootCmd = &cobra.Command{
Use: "container-diff",
Short: "container-diff is a tool for analyzing and comparing container images",
Long: `container-diff is a CLI tool for analyzing and comparing container images.`,
}
Long: `container-diff is a CLI tool for analyzing and comparing container images.

func NewClient() (*client.Client, error) {
cli, err := client.NewEnvClient()
if err != nil {
return nil, fmt.Errorf("Error getting docker client: %s", err)
}
cli.NegotiateAPIVersion(context.Background())
Images can be specified from either a local Docker daemon, or from a remote registry.
To specify a local image, prefix the image ID with 'daemon://', e.g. 'daemon://gcr.io/foo/bar'.
To specify a remote image, prefix the image ID with 'remote://', e.g. 'remote://gcr.io/foo/bar'.
If no prefix is specified, the local daemon will be checked first.

return cli, nil
Tarballs can also be specified by simply providing the path to the .tar, .tar.gz, or .tgz file.`,
}

func outputResults(resultMap map[string]util.Result) {
Expand Down Expand Up @@ -92,7 +95,7 @@ func validateArgs(args []string, validatefxns ...validatefxn) error {

func checkIfValidAnalyzer(flagtypes string) error {
if flagtypes == "" {
return nil
return errors.New("Please provide at least one analyzer to run")
}
analyzers := strings.Split(flagtypes, ",")
for _, name := range analyzers {
Expand All @@ -103,6 +106,30 @@ func checkIfValidAnalyzer(flagtypes string) error {
return nil
}

func getPrepperForImage(image string) (pkgutil.Prepper, error) {
cli, err := client.NewEnvClient()
if err != nil {
return nil, err
}
if pkgutil.IsTar(image) {
return pkgutil.TarPrepper{
Source: image,
Client: cli,
}, nil

} else if strings.HasPrefix(image, DaemonPrefix) {
return pkgutil.DaemonPrepper{
Source: strings.Replace(image, DaemonPrefix, "", -1),
Client: cli,
}, nil
}
// either has remote prefix or has no prefix, in which case we force remote
return pkgutil.CloudPrepper{
Source: strings.Replace(image, RemotePrefix, "", -1),
Client: cli,
}, nil
}

func init() {
pflag.CommandLine.AddGoFlagSet(goflag.CommandLine)
}
Expand Down
1 change: 0 additions & 1 deletion pkg/util/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ go_library(
"docker_utils.go",
"fs_utils.go",
"image_prep_utils.go",
"image_prepper.go",
"image_utils.go",
"tar_prepper.go",
"tar_utils.go",
Expand Down
17 changes: 6 additions & 11 deletions pkg/util/cloud_prepper.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,26 @@ limitations under the License.
package util

import (
"regexp"

"github.com/containers/image/docker"
"github.com/docker/docker/client"
)

// CloudPrepper prepares images sourced from a Cloud registry
type CloudPrepper struct {
ImagePrepper
Source string
Client *client.Client
}

func (p CloudPrepper) Name() string {
return "Cloud Registry"
}

func (p CloudPrepper) GetSource() string {
return p.ImagePrepper.Source
return p.Source
}

func (p CloudPrepper) SupportsImage() bool {
pattern := regexp.MustCompile("^.+/.+(:.+){0,1}$")
image := p.ImagePrepper.Source
if exp := pattern.FindString(image); exp != image || CheckTar(image) {
return false
}
return true
func (p CloudPrepper) GetImage() (Image, error) {
return getImage(p)
}

func (p CloudPrepper) GetFileSystem() (string, error) {
Expand Down
16 changes: 7 additions & 9 deletions pkg/util/daemon_prepper.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,28 @@ package util

import (
"context"
"regexp"

"github.com/containers/image/docker/daemon"

"github.com/docker/docker/client"
"github.com/golang/glog"
)

type DaemonPrepper struct {
ImagePrepper
Source string
Client *client.Client
}

func (p DaemonPrepper) Name() string {
return "Local Daemon"
}

func (p DaemonPrepper) GetSource() string {
return p.ImagePrepper.Source
return p.Source
}

func (p DaemonPrepper) SupportsImage() bool {
pattern := regexp.MustCompile("[a-z|0-9]{12}")
if exp := pattern.FindString(p.ImagePrepper.Source); exp != p.ImagePrepper.Source {
return false
}
return true
func (p DaemonPrepper) GetImage() (Image, error) {
return getImage(p)
}

func (p DaemonPrepper) GetFileSystem() (string, error) {
Expand Down
10 changes: 10 additions & 0 deletions pkg/util/docker_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@ type Event struct {
} `json:"progressDetail"`
}

func NewClient() (*client.Client, error) {
cli, err := client.NewEnvClient()
if err != nil {
return nil, fmt.Errorf("Error getting docker client: %s", err)
}
cli.NegotiateAPIVersion(context.Background())

return cli, nil
}

func getLayersFromManifest(manifestPath string) ([]string, error) {
type Manifest struct {
Layers []string
Expand Down
32 changes: 28 additions & 4 deletions pkg/util/image_prep_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"archive/tar"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
Expand All @@ -30,10 +31,12 @@ import (
"github.com/golang/glog"
)

var orderedPreppers = []func(ip ImagePrepper) Prepper{
func(ip ImagePrepper) Prepper { return DaemonPrepper{ImagePrepper: ip} },
func(ip ImagePrepper) Prepper { return CloudPrepper{ImagePrepper: ip} },
func(ip ImagePrepper) Prepper { return TarPrepper{ImagePrepper: ip} },
type Prepper interface {
Name() string
GetConfig() (ConfigSchema, error)
GetFileSystem() (string, error)
GetImage() (Image, error)
GetSource() string
}

type Image struct {
Expand All @@ -55,6 +58,27 @@ type ConfigSchema struct {
History []ImageHistoryItem `json:"history"`
}

func getImage(p Prepper) (Image, error) {
glog.Infof("Retrieving image %s from source %s", p.GetSource(), p.Name())
imgPath, err := p.GetFileSystem()
if err != nil {
return Image{}, err
}

config, err := p.GetConfig()
if err != nil {
glog.Error("Error retrieving History: ", err)
}

glog.Infof("Finished prepping image %s", p.GetSource())
return Image{
Source: p.GetSource(),
FSPath: imgPath,
Config: config,
}, nil
return Image{}, fmt.Errorf("Could not retrieve image %s from source", p.GetSource())
}

func getImageFromTar(tarPath string) (string, error) {
glog.Info("Extracting image tar to obtain image file system")
path := strings.TrimSuffix(tarPath, filepath.Ext(tarPath))
Expand Down
Loading