This repository has been archived by the owner on Jun 3, 2021. It is now read-only.
/
index.go
163 lines (150 loc) · 4.7 KB
/
index.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
package tools
import (
"bufio"
"context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"strings"
yaml "gopkg.in/yaml.v2"
"github.com/Originate/exosphere/src/types"
"github.com/Originate/exosphere/src/util"
dockerTypes "github.com/docker/docker/api/types"
"github.com/moby/moby/client"
"github.com/pkg/errors"
)
// CatFileInDockerImage reads the file fileName inside the given image
func CatFileInDockerImage(c *client.Client, imageName, fileName string) ([]byte, error) {
if err := PullImage(c, imageName); err != nil {
return []byte(""), err
}
command := fmt.Sprintf("cat %s", fileName)
output, err := RunInDockerImage(imageName, command)
return []byte(output), err
}
// GetDockerCompose reads docker-compose.yml at the given path and
// returns the dockerCompose object
func GetDockerCompose(dockerComposePath string) (result types.DockerCompose, err error) {
yamlFile, err := ioutil.ReadFile(dockerComposePath)
if err != nil {
return result, err
}
err = yaml.Unmarshal(yamlFile, &result)
if err != nil {
return result, errors.Wrap(err, "Failed to unmarshal docker-compose.yml")
}
return result, nil
}
// GetExitCode returns the exit code for the given container
func GetExitCode(containerName string) (int, error) {
c, err := client.NewEnvClient()
if err != nil {
return 1, err
}
containerJSON, err := c.ContainerInspect(context.Background(), containerName)
if err != nil {
return 1, err
}
if containerJSON.State.Status != "exited" {
return 1, fmt.Errorf("%s has not exited", containerName)
}
return containerJSON.State.ExitCode, nil
}
// ListRunningContainers returns the names of running containers
// and an error (if any)
func ListRunningContainers(c *client.Client) ([]string, error) {
containerNames := []string{}
ctx := context.Background()
containers, err := c.ContainerList(ctx, dockerTypes.ContainerListOptions{})
if err != nil {
return containerNames, err
}
for _, container := range containers {
containerNames = append(containerNames, strings.Replace(container.Names[0], "/", "", -1))
}
return containerNames, nil
}
// ListImages returns the names of all images and an error (if any)
func ListImages(c *client.Client) ([]string, error) {
imageNames := []string{}
ctx := context.Background()
imageSummaries, err := c.ImageList(ctx, dockerTypes.ImageListOptions{
All: true,
})
if err != nil {
return imageNames, err
}
for _, imageSummary := range imageSummaries {
if len(imageSummary.RepoTags) > 0 {
repoTag := imageSummary.RepoTags[0]
imageNames = append(imageNames, repoTag)
}
}
return imageNames, nil
}
// PullImage pulls the given image from DockerHub, returns an error if any
func PullImage(c *client.Client, image string) error {
ctx := context.Background()
stream, err := c.ImagePull(ctx, image, dockerTypes.ImagePullOptions{})
if err != nil {
return err
}
_, err = ioutil.ReadAll(stream)
return err
}
// RunInDockerImage runs the given command in a new writeable container layer
// over the given image, removes the container when the command exits, and returns
// the output string and an error if any
func RunInDockerImage(imageName, command string) (string, error) {
return util.Run("", fmt.Sprintf("docker run --rm %s %s", imageName, command))
}
// TagImage tags a docker image srcImage as targetImage
func TagImage(srcImage, targetImage string) error {
dockerClient, err := client.NewEnvClient()
if err != nil {
return err
}
ctx := context.Background()
return dockerClient.ImageTag(ctx, srcImage, targetImage)
}
// PushImage pushes image with imageName to the registry given an encoded auth object
func PushImage(c *client.Client, writer io.Writer, imageName, encodedAuth string) error {
util.PrintSectionHeaderf(writer, "docker push %s", imageName)
ctx := context.Background()
stream, err := c.ImagePush(ctx, imageName, dockerTypes.ImagePushOptions{
RegistryAuth: encodedAuth,
})
if err != nil {
return err
}
scanner := bufio.NewScanner(stream)
for scanner.Scan() {
err = printPushProgress(writer, scanner.Text())
if err != nil {
return fmt.Errorf("Cannot push image '%s': %s", imageName, err)
}
}
if err := scanner.Err(); err != nil {
return errors.Wrap(err, "error reading ImagePush output")
}
fmt.Println()
return stream.Close()
}
func printPushProgress(writer io.Writer, output string) error {
outputObject := struct {
Status string `json:"status"`
ID string `json:"id"`
ErrorDetail interface{} `json:"errorDetail"`
Error string `json:"error"`
}{}
err := json.Unmarshal([]byte(output), &outputObject)
if err != nil {
return err
}
if outputObject.Error != "" {
return errors.New(outputObject.Error)
}
_, err = fmt.Fprintf(writer, "%s: %s\n", outputObject.Status, outputObject.ID)
return err
}