diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 3296f89..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Launch", - "type": "go", - "request": "launch", - "mode": "debug", - "remotePath": "", - "port": 2345, - "host": "127.0.0.1", - "program": "${workspaceRoot}/cmd/die/main.go", - "externalConsole": true, - "env": { - "TERM": "xterm-256color" - }, - "args": ["die-test"], - "showLog": true - } - ] -} \ No newline at end of file diff --git a/Gopkg.lock b/Gopkg.lock deleted file mode 100644 index 5166b9e..0000000 --- a/Gopkg.lock +++ /dev/null @@ -1,104 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - name = "github.com/Microsoft/go-winio" - packages = ["."] - revision = "7da180ee92d8bd8bb8c37fc560e673e6557c392f" - version = "v0.4.7" - -[[projects]] - name = "github.com/docker/distribution" - packages = [ - "digest", - "reference" - ] - revision = "48294d928ced5dd9b378f7fd7c6f5da3ff3f2c89" - version = "v2.6.2" - -[[projects]] - name = "github.com/docker/docker" - packages = [ - "api/types", - "api/types/blkiodev", - "api/types/container", - "api/types/events", - "api/types/filters", - "api/types/mount", - "api/types/network", - "api/types/reference", - "api/types/registry", - "api/types/strslice", - "api/types/swarm", - "api/types/time", - "api/types/versions", - "api/types/volume", - "client", - "pkg/tlsconfig" - ] - revision = "092cba3727bb9b4a2f0e922cd6c0f93ea270e363" - version = "v1.13.1" - -[[projects]] - name = "github.com/docker/go-connections" - packages = [ - "nat", - "sockets", - "tlsconfig" - ] - revision = "3ede32e2033de7505e6500d6c868c2b9ed9f169d" - version = "v0.3.0" - -[[projects]] - name = "github.com/docker/go-units" - packages = ["."] - revision = "47565b4f722fb6ceae66b95f853feed578a4a51c" - version = "v0.3.3" - -[[projects]] - branch = "master" - name = "github.com/jroimartin/gocui" - packages = ["."] - revision = "c055c87ae801372cd74a0839b972db4f7697ae5f" - -[[projects]] - name = "github.com/mattn/go-runewidth" - packages = ["."] - revision = "9e777a8366cce605130a531d2cd6363d07ad7317" - version = "v0.0.2" - -[[projects]] - branch = "master" - name = "github.com/nsf/termbox-go" - packages = ["."] - revision = "21a4d435a86280a2927985fd6296de56cbce453e" - -[[projects]] - name = "github.com/pkg/errors" - packages = ["."] - revision = "645ef00459ed84a119197bfb8d8205042c6df63d" - version = "v0.8.0" - -[[projects]] - branch = "master" - name = "golang.org/x/net" - packages = [ - "context", - "context/ctxhttp", - "internal/socks", - "proxy" - ] - revision = "1e491301e022f8f977054da4c2d852decd59571f" - -[[projects]] - branch = "master" - name = "golang.org/x/sys" - packages = ["windows"] - revision = "c11f84a56e43e20a78cee75a7c034031ecf57d1f" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - inputs-digest = "73c0fae1988538f4def02f2bd28830793264b4260b25d078b561413085a81845" - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml deleted file mode 100644 index 2fa2eba..0000000 --- a/Gopkg.toml +++ /dev/null @@ -1,43 +0,0 @@ -# Gopkg.toml example -# -# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" -# -# [prune] -# non-go = false -# go-tests = true -# unused-packages = true - - -[[constraint]] - name = "github.com/docker/docker" - version = "1.13.1" - -[[constraint]] - name = "github.com/jroimartin/gocui" - # version = "0.3.0" - branch = "master" - -[[constraint]] - branch = "master" - name = "golang.org/x/net" - -[prune] - go-tests = true - unused-packages = true diff --git a/Makefile b/Makefile index 5af1d41..0aea4cd 100644 --- a/Makefile +++ b/Makefile @@ -1,35 +1,26 @@ -BIN = die +BIN = dive all: clean build run: build - docker image ls | grep "die-test" >/dev/null || docker build -t die-test:latest . + docker image ls | grep "dive-test" >/dev/null || docker build -t dive-test:latest . ./build/$(BIN) die-test -build: #deps - go build -o build/$(BIN) ./cmd/... +build: + go build -o build/$(BIN) -install: deps +install: go install ./... -deps: - command -v $(GOPATH)/bin/dep >/dev/null || go get -u github.com/golang/dep/cmd/dep - $(GOPATH)/bin/dep ensure - test: build - @! git grep tcell -- ':!tui/' ':!Gopkg.lock' ':!Gopkg.toml' ':!Makefile' go test -v ./... -lint: lintdeps build - golint -set_exit_status $$(go list ./... | grep -v /vendor/) - -lintdeps: - go get -d -v -t ./... - command -v golint >/dev/null || go get -u github.com/golang/lint/golint +lint: build + golint -set_exit_status $$(go list ./...) clean: rm -rf build rm -rf vendor go clean -.PHONY: build install deps test lint lintdeps clean +.PHONY: build install test lint clean diff --git a/README.md b/README.md index e4b803e..cc94dc0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ -# docker-image-explorer +# dive + +A tool for interrogating docker images. + ``` docker build -t die-test:latest . go run main.go @@ -6,9 +9,6 @@ go run main.go # TODO: -- [x] Extract docker layers from api -- [x] Represent layers as generic tree -- [x] Stack ordere tree list together as fake unionfs tree - [ ] Diff trees -- [ ] Add ui for browsing layers + - [ ] Add ui for diffing stack to layer diff --git a/cmd/analyze.go b/cmd/analyze.go new file mode 100644 index 0000000..88745e3 --- /dev/null +++ b/cmd/analyze.go @@ -0,0 +1,39 @@ +// Copyright © 2018 Alex Goodman +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package cmd + +import ( + "github.com/spf13/cobra" + "fmt" + "os" + "github.com/wagoodman/dive/image" + "github.com/wagoodman/dive/ui" +) + +func analyze(cmd *cobra.Command, args []string) { + userImage := args[0] + if userImage == "" { + fmt.Println("No image argument given") + os.Exit(1) + } + manifest, refTrees := image.InitializeData(userImage) + ui.Run(manifest, refTrees) +} \ No newline at end of file diff --git a/cmd/build.go b/cmd/build.go new file mode 100644 index 0000000..99ebdd8 --- /dev/null +++ b/cmd/build.go @@ -0,0 +1,51 @@ +// Copyright © 2018 Alex Goodman +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +// buildCmd represents the build command +var buildCmd = &cobra.Command{ + Use: "build", + Short: "Build and analyze a docker image", + Long: `Build and analyze a docker image`, + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("build called") + }, +} + +func init() { + rootCmd.AddCommand(buildCmd) + + // Here you will define your flags and configuration settings. + + // Cobra supports Persistent Flags which will work for this command + // and all subcommands, e.g.: + // buildCmd.PersistentFlags().String("foo", "", "A help for foo") + + // Cobra supports local flags which will only run when this command + // is called directly, e.g.: + // buildCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} diff --git a/cmd/die/main.go b/cmd/die/main.go deleted file mode 100644 index fa9b019..0000000 --- a/cmd/die/main.go +++ /dev/null @@ -1,36 +0,0 @@ -package main - -import ( - "fmt" - "log" - "os" - - "github.com/urfave/cli" - "github.com/wagoodman/docker-image-explorer/image" - "github.com/wagoodman/docker-image-explorer/ui" -) - -const name = "die" -const version = "v0.0.0" -const author = "wagoodman" - -func main() { - app := cli.NewApp() - app.Name = "die" - app.Usage = "Explore your docker images" - app.Action = func(c *cli.Context) error { - userImage := c.Args().Get(0) - if userImage == "" { - fmt.Println("No image argument given") - os.Exit(1) - } - manifest, refTrees := image.InitializeData(userImage) - ui.Run(manifest, refTrees) - return nil - } - - err := app.Run(os.Args) - if err != nil { - log.Fatal(err) - } -} diff --git a/cmd/root.go b/cmd/root.go new file mode 100644 index 0000000..91d46a7 --- /dev/null +++ b/cmd/root.go @@ -0,0 +1,89 @@ +// Copyright © 2018 Alex Goodman +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package cmd + +import ( + "fmt" + "os" + + homedir "github.com/mitchellh/go-homedir" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var cfgFile string + +// rootCmd represents the base command when called without any subcommands +var rootCmd = &cobra.Command{ + Use: "dive", + Short: "Docker Image Visualizer & Explorer", + Long: `Docker Image Visualizer & Explorer`, + Args: cobra.ExactArgs(1), + Run: analyze, +} + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func Execute() { + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} + +func init() { + cobra.OnInitialize(initConfig) + + // Here you will define your flags and configuration settings. + // Cobra supports persistent flags, which, if defined here, + // will be global for your application. + rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.dive.yaml)") + + // Cobra also supports local flags, which will only run + // when this action is called directly. + rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} + +// initConfig reads in config file and ENV variables if set. +func initConfig() { + if cfgFile != "" { + // Use config file from the flag. + viper.SetConfigFile(cfgFile) + } else { + // Find home directory. + home, err := homedir.Dir() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + // Search config in home directory with name ".dive" (without extension). + viper.AddConfigPath(home) + viper.SetConfigName(".dive") + } + + viper.AutomaticEnv() // read in environment variables that match + + // If a config file is found, read it in. + if err := viper.ReadInConfig(); err == nil { + fmt.Println("Using config file:", viper.ConfigFileUsed()) + } +} diff --git a/image/image.go b/image/image.go index 6560d49..b45c980 100644 --- a/image/image.go +++ b/image/image.go @@ -12,10 +12,10 @@ import ( "path/filepath" "strings" - "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/image" "github.com/docker/docker/client" humanize "github.com/dustin/go-humanize" - "github.com/wagoodman/docker-image-explorer/filetree" + "github.com/wagoodman/dive/filetree" "golang.org/x/net/context" "strconv" ) @@ -53,7 +53,7 @@ func NewManifest(reader *tar.Reader, header *tar.Header) ImageManifest { type Layer struct { TarPath string - History types.ImageHistory + History image.HistoryResponseItem Index int Tree *filetree.FileTree RefTrees []*filetree.FileTree diff --git a/main.go b/main.go new file mode 100644 index 0000000..d6e186f --- /dev/null +++ b/main.go @@ -0,0 +1,27 @@ +// Copyright © 2018 Alex Goodman +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package main + +import "github.com/wagoodman/dive/cmd" + +func main() { + cmd.Execute() +} diff --git a/ui/filetreeview.go b/ui/filetreeview.go index 49c80ee..05eb56a 100644 --- a/ui/filetreeview.go +++ b/ui/filetreeview.go @@ -6,7 +6,7 @@ import ( "strings" "github.com/jroimartin/gocui" - "github.com/wagoodman/docker-image-explorer/filetree" + "github.com/wagoodman/dive/filetree" "github.com/lunixbochs/vtclean" ) diff --git a/ui/layerview.go b/ui/layerview.go index b4558a3..d83822c 100644 --- a/ui/layerview.go +++ b/ui/layerview.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/jroimartin/gocui" - "github.com/wagoodman/docker-image-explorer/image" + "github.com/wagoodman/dive/image" "github.com/lunixbochs/vtclean" ) diff --git a/ui/ui.go b/ui/ui.go index e8b4168..f9458ec 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -6,8 +6,8 @@ import ( "log" "github.com/jroimartin/gocui" - "github.com/wagoodman/docker-image-explorer/filetree" - "github.com/wagoodman/docker-image-explorer/image" + "github.com/wagoodman/dive/filetree" + "github.com/wagoodman/dive/image" "github.com/fatih/color" )