Skip to content

Commit

Permalink
clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelmota committed Feb 16, 2019
1 parent dbb42ac commit 9f96c44
Show file tree
Hide file tree
Showing 12 changed files with 106 additions and 405 deletions.
6 changes: 2 additions & 4 deletions cmd/ipdr/main.go
Expand Up @@ -13,12 +13,10 @@ import (
var green = color.New(color.FgGreen)

var (
// ErrImageIDRequired ...
// ErrImageIDRequired is error for when image ID is required
ErrImageIDRequired = errors.New("image hash or name is required")
// ErrOnlyOneArgumentRequired ...
// ErrOnlyOneArgumentRequired is error for when one argument only is required
ErrOnlyOneArgumentRequired = errors.New("only one argument is required")
// ErrSubCommandRequired ...
ErrSubCommandRequired = errors.New("sub command is required")
)

func main() {
Expand Down
251 changes: 16 additions & 235 deletions docker/client.go
@@ -1,84 +1,30 @@
package docker

import (
"bufio"
"context"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"os/exec"
"path/filepath"
"strings"

container "github.com/docker/docker/api/types/container"
log "github.com/sirupsen/logrus"

types "github.com/docker/docker/api/types"
filters "github.com/docker/docker/api/types/filters"
mount "github.com/docker/docker/api/types/mount"
client "github.com/docker/docker/client"
nat "github.com/docker/go-connections/nat"
tlsconfig "github.com/docker/go-connections/tlsconfig"
)

// Client ...
// Client is client structure
type Client struct {
client *client.Client
}

// NewClient ...
// NewClient creates a new client instance
func NewClient() *Client {
return newEnvClient()
}

// newClient ...
func newClient() *Client {
httpclient := &http.Client{}

if dockerCertPath := os.Getenv("DOCKER_CERT_PATH"); dockerCertPath != "" {
options := tlsconfig.Options{
CAFile: filepath.Join(dockerCertPath, "ca.pem"),
CertFile: filepath.Join(dockerCertPath, "cert.pem"),
KeyFile: filepath.Join(dockerCertPath, "key.pem"),
InsecureSkipVerify: os.Getenv("DOCKER_TLS_VERIFY") == "",
}
tlsc, err := tlsconfig.Client(options)
if err != nil {
log.Fatalf("[docker] %s", err)
}

httpclient.Transport = &http.Transport{
TLSClientConfig: tlsc,
}
}

host := os.Getenv("DOCKER_HOST")
version := os.Getenv("DOCKER_VERSION")

if host == "" {
log.Fatal("[docker] DOCKER_HOST is required")
}

if version == "" {
version = dockerVersionFromCLI()
if version == "" {
log.Fatal("[docker] DOCKER_VERSION is required")
}
}

cl, err := client.NewClient(host, version, httpclient, nil)
if err != nil {
log.Fatalf("[docker] %s", err)
}

return &Client{
client: cl,
}
}

// newEnvClient ...
// newEnvClient returns a new client instance based on environment variables
func newEnvClient() *Client {
cl, err := client.NewEnvClient()
if err != nil {
Expand All @@ -90,14 +36,14 @@ func newEnvClient() *Client {
}
}

// ImageSummary ....
// ImageSummary is structure for image summary
type ImageSummary struct {
ID string
Tags []string
Size int64
}

// ListImages ...
// ListImages return list of docker images
func (s *Client) ListImages() ([]*ImageSummary, error) {
images, err := s.client.ImageList(context.Background(), types.ImageListOptions{
All: true,
Expand All @@ -118,7 +64,7 @@ func (s *Client) ListImages() ([]*ImageSummary, error) {
return summaries, nil
}

// HasImage ...
// HasImage returns true if image ID is available locally
func (s *Client) HasImage(imageID string) (bool, error) {
args := filters.NewArgs()
args.Add("reference", StripImageTagHost(imageID))
Expand All @@ -137,7 +83,7 @@ func (s *Client) HasImage(imageID string) (bool, error) {
return false, nil
}

// PullImage ...
// PullImage pulls a docker image
func (s *Client) PullImage(imageID string) error {
reader, err := s.client.ImagePull(context.Background(), imageID, types.ImagePullOptions{})
if err != nil {
Expand All @@ -148,7 +94,7 @@ func (s *Client) PullImage(imageID string) error {
return nil
}

// PushImage ...
// PushImage pushes a docker image
func (s *Client) PushImage(imageID string) error {
reader, err := s.client.ImagePush(context.Background(), imageID, types.ImagePushOptions{
// NOTE: if no auth, then any value is required
Expand All @@ -161,12 +107,12 @@ func (s *Client) PushImage(imageID string) error {
return nil
}

// TagImage ...
// TagImage tags an image
func (s *Client) TagImage(imageID, tag string) error {
return s.client.ImageTag(context.Background(), imageID, tag)
}

// RemoveImage ...
// RemoveImage remove an image from the local registry
func (s *Client) RemoveImage(imageID string) error {
_, err := s.client.ImageRemove(context.Background(), imageID, types.ImageRemoveOptions{
Force: true,
Expand All @@ -176,7 +122,7 @@ func (s *Client) RemoveImage(imageID string) error {
return err
}

// RemoveAllImages ...
// RemoveAllImages removes all images from the local registry
func (s *Client) RemoveAllImages() error {
images, err := s.ListImages()
if err != nil {
Expand Down Expand Up @@ -204,171 +150,26 @@ func (s *Client) RemoveAllImages() error {
return nil
}

// CreateContainerConfig ...
type CreateContainerConfig struct {
// container:host
Volumes map[string]string
Ports map[string]string
}

// CreateContainer ...
func (s *Client) CreateContainer(imageID string, cmd []string, config *CreateContainerConfig) (string, error) {
if config == nil {
config = &CreateContainerConfig{}
}

dockerConfig := &container.Config{
Image: imageID,
Cmd: cmd,
Tty: false,
Volumes: map[string]struct{}{},
ExposedPorts: map[nat.Port]struct{}{},
}

hostConfig := &container.HostConfig{
Binds: nil,
PortBindings: map[nat.Port][]nat.PortBinding{},
AutoRemove: true,
IpcMode: "",
Privileged: false,
Mounts: []mount.Mount{},
}

if len(config.Volumes) > 0 {
for k, v := range config.Volumes {
dockerConfig.Volumes[k] = struct{}{}
hostConfig.Mounts = append(hostConfig.Mounts, mount.Mount{
Type: "bind",
Source: v,
Target: k,
ReadOnly: false,
})
}
}

if len(config.Ports) > 0 {
for k, v := range config.Ports {
t, err := nat.NewPort("tcp", k)
if err != nil {
return "", err
}
dockerConfig.ExposedPorts[t] = struct{}{}
hostConfig.PortBindings[t] = []nat.PortBinding{
{
HostIP: "0.0.0.0",
HostPort: v,
},
}
}
}

resp, err := s.client.ContainerCreate(context.Background(), dockerConfig, hostConfig, nil, "")
if err != nil {
return "", err
}

log.Printf("[docker] container %s is ready", resp.ID)

return resp.ID, nil
}

// StartContainer ...
func (s *Client) StartContainer(containerID string) error {
err := s.client.ContainerStart(context.TODO(), containerID, types.ContainerStartOptions{})

if err != nil {
log.Printf("[docker] error starting container %s; %v", containerID, err)
return err
}

reader, err := s.client.ContainerLogs(context.TODO(), containerID, types.ContainerLogsOptions{
ShowStdout: true,
ShowStderr: true,
Follow: true,
})

go func() {
log.Println("[docker] logging to stdout..")
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
line := scanner.Text()
log.Printf("[docker] [container %s] [log] %s\n", ShortContainerID(containerID), line)
}
}()

if err != nil {
log.Printf("[docker] error reading container logs for %s; %v", containerID, err)
return err
}

log.Printf("[docker] running container %s", containerID)
return nil
}

// StopContainer ...
func (s *Client) StopContainer(containerID string) error {
log.Printf("[docker] stopping container %s", containerID)
err := s.client.ContainerStop(context.Background(), containerID, nil)
if err != nil {
return err
}

log.Println("[docker] container stopped")
return nil
}

// InspectContainer ...
func (s *Client) InspectContainer(containerID string) (types.ContainerJSON, error) {
info, err := s.client.ContainerInspect(context.Background(), containerID)
if err != nil {
return types.ContainerJSON{}, err
}

return info, nil
}

// ContainerExec ...
func (s *Client) ContainerExec(containerID string, cmd []string) (io.Reader, error) {
id, err := s.client.ContainerExecCreate(context.Background(), containerID, types.ExecConfig{
AttachStdout: true,
Cmd: cmd,
})

log.Printf("[docker] exec ID %s", id.ID)
if err != nil {
return nil, err
}

resp, err := s.client.ContainerExecAttach(context.Background(), id.ID, types.ExecConfig{})
if err != nil {
return nil, err
}

return resp.Reader, nil
}

// ReadImage ...
// ReadImage reads the contents of an image into an IO reader
func (s *Client) ReadImage(imageID string) (io.Reader, error) {
return s.client.ImageSave(context.Background(), []string{imageID})
}

// LoadImage ...
// LoadImage loads an image from an IO reader
func (s *Client) LoadImage(input io.Reader) error {
output, err := s.client.ImageLoad(context.Background(), input, false)
if err != nil {
return err
}

//io.Copy(os.Stdout, output)
fmt.Println(output)
body, err := ioutil.ReadAll(output.Body)
fmt.Println(string(body))

return err
}

// LoadImageByFilepath ...
func (s *Client) LoadImageByFilepath(filepath string) error {
// LoadImageByFilePath loads an image from a tarball
func (s *Client) LoadImageByFilePath(filepath string) error {
input, err := os.Open(filepath)
if err != nil {
log.Printf("[docker] load image by filepath error; %v", err)
Expand All @@ -377,7 +178,7 @@ func (s *Client) LoadImageByFilepath(filepath string) error {
return s.LoadImage(input)
}

// SaveImageTar ...
// SaveImageTar saves an image into a tarball
func (s *Client) SaveImageTar(imageID string, dest string) error {
reader, err := s.ReadImage(imageID)

Expand All @@ -390,23 +191,3 @@ func (s *Client) SaveImageTar(imageID string, dest string) error {
io.Copy(fo, reader)
return nil
}

func dockerVersionFromCLI() string {
cmd := `docker version --format="{{.Client.APIVersion}}"`
out, err := exec.Command("sh", "-c", cmd).Output()
if err != nil {
return ""
}

return strings.TrimSpace(string(out))
}

// CommitContainer ...
func (s *Client) CommitContainer(containerID string) (string, error) {
resp, err := s.client.ContainerCommit(context.Background(), containerID, types.ContainerCommitOptions{})
if err != nil {
return "", err
}

return resp.ID, nil
}

0 comments on commit 9f96c44

Please sign in to comment.