-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdeploy.go
130 lines (107 loc) · 3.01 KB
/
deploy.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
package dargo
import (
"bufio"
"context"
"encoding/json"
"fmt"
"io"
"log"
"os"
"github.com/docker/engine-api/client"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/container"
"github.com/docker/engine-api/types/network"
)
// DeployOptions control attributes about the resulting Docker Image
type DeployOptions struct {
Tags []string
Foreground bool
}
type buildOutput struct {
Stream string `json:"stream"`
}
func buildImage(o DeployOptions, cli *client.Client) error {
buildOptions := types.ImageBuildOptions{
Tags: o.Tags,
}
self, err := makeTar()
if err != nil {
return fmt.Errorf("Error building tar for image build: %v", err)
}
buildResponse, err := cli.ImageBuild(context.Background(), self, buildOptions)
if err != nil {
return fmt.Errorf("Error starting image build: %v", err)
}
defer buildResponse.Body.Close()
scanner := bufio.NewScanner(buildResponse.Body)
for scanner.Scan() {
var output buildOutput
err = json.Unmarshal([]byte(scanner.Text()), &output)
fmt.Print(output.Stream)
}
return nil
}
func runImage(runOptions DeployOptions, cli *client.Client) error {
containerConfig := container.Config{
Image: runOptions.Tags[0],
}
if runOptions.Foreground {
containerConfig.AttachStdin = true
containerConfig.AttachStdout = true
containerConfig.AttachStderr = true
containerConfig.Tty = true
containerConfig.OpenStdin = true
containerConfig.StdinOnce = true
}
networkConfig := network.NetworkingConfig{}
hostConfig := container.HostConfig{}
createResponse, err := cli.ContainerCreate(context.Background(), &containerConfig, &hostConfig, &networkConfig, "")
if err != nil {
return fmt.Errorf("Error creating container: %v", err)
}
attachResp, err := cli.ContainerAttach(context.Background(), createResponse.ID, types.ContainerAttachOptions{
Stdin: true,
Stdout: true,
Stderr: true,
Stream: true,
})
go func() { io.Copy(attachResp.Conn, os.Stdin) }()
go func() { io.Copy(os.Stdout, attachResp.Reader) }()
err = cli.ContainerStart(context.Background(), createResponse.ID, types.ContainerStartOptions{})
if err != nil {
return fmt.Errorf("Error starting container: %v", err)
}
_, err = cli.ContainerWait(context.Background(), createResponse.ID)
if err != nil {
return fmt.Errorf("Error waiting for container to exit: %v", err)
}
return nil
}
// Deploy deploys to the Docker engine reachable via environment variables and
// defaults.
func Deploy(o DeployOptions) error {
cli, err := client.NewEnvClient()
if err != nil {
return fmt.Errorf("Error creating docker client: %v", err)
}
err = buildImage(o, cli)
if err != nil {
return fmt.Errorf("Error building image: %v", err)
}
err = runImage(o, cli)
if err != nil {
return fmt.Errorf("Error starting image: %v", err)
}
return nil
}
// DeployAndExit checks to see if we're Enabled, then calls Deploy, logging
// Fatal errors, then exiting
func DeployAndExit(o DeployOptions) {
if !Enable {
return
}
if err := Deploy(o); err != nil {
log.Fatal(err)
}
os.Exit(0)
}