-
Notifications
You must be signed in to change notification settings - Fork 0
/
execution.go
130 lines (112 loc) · 3.08 KB
/
execution.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 cronify
import (
"context"
"fmt"
"io"
"log"
"time"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/docker/docker/pkg/stdcopy"
)
// JobExecution represent a job to execute
type JobExecution interface {
execute(ctx context.Context, outputWriter io.Writer) (bool, error)
}
// JobDockerKill implements JobExecution for sending process signals
type JobDockerKill struct {
Client *client.Client
Config *JobTypeConfig
}
func (j *JobDockerKill) execute(ctx context.Context, outputWriter io.Writer) (bool, error) {
err := j.Client.ContainerKill(ctx, j.Config.Container, j.Config.Signal)
if err != nil {
return false, err
}
return true, nil
}
// JobDockerRestart restarts container
type JobDockerRestart struct {
Client *client.Client
Config *JobTypeConfig
}
func (j *JobDockerRestart) execute(ctx context.Context, outputWriter io.Writer) (bool, error) {
err := j.Client.ContainerRestart(ctx, j.Config.Container, &j.Config.Timeout)
if err != nil {
return false, err
}
return true, nil
}
// JobDockerStop stops container
type JobDockerStop struct {
Client *client.Client
Config *JobTypeConfig
}
func (j *JobDockerStop) execute(ctx context.Context, outputWriter io.Writer) (bool, error) {
err := j.Client.ContainerStop(ctx, j.Config.Container, &j.Config.Timeout)
if err != nil {
return false, err
}
return true, nil
}
// JobDockerStart starts container
type JobDockerStart struct {
Client *client.Client
Config *JobTypeConfig
}
func (j *JobDockerStart) execute(ctx context.Context, outputWriter io.Writer) (bool, error) {
err := j.Client.ContainerStart(ctx, j.Config.Container, types.ContainerStartOptions{})
if err != nil {
return false, err
}
//todo: wait with log output attach -> j.Config.Wait
return true, nil
}
// JobDockerExec implements JobExecution for attached container executions
type JobDockerExec struct {
Client *client.Client
Config *JobTypeConfig
LogWriter io.Writer
}
func (j *JobDockerExec) execute(ctx context.Context, outputWriter io.Writer) (bool, error) {
execID, err := j.Client.ContainerExecCreate(ctx, j.Config.Container, types.ExecConfig{
AttachStderr: true,
AttachStdout: true,
Cmd: j.Config.Command,
})
if err != nil {
return false, err
}
hj, err := j.Client.ContainerExecAttach(ctx, execID.ID, types.ExecStartCheck{
Detach: false,
})
if err != nil {
return false, err
}
defer hj.Close()
// start writer shipped by docker (StdCopy will demultiplex `src`, assuming that it contains two streams)
go stdcopy.StdCopy(outputWriter, outputWriter, hj.Reader)
err = j.Client.ContainerExecStart(ctx, execID.ID, types.ExecStartCheck{})
if err != nil {
return false, err
}
// wait for end of execution
ticker := time.NewTicker(2 * time.Second)
defer ticker.Stop()
for {
<-ticker.C
inspect, err := j.Client.ContainerExecInspect(ctx, execID.ID)
if err != nil {
return false, err
}
if inspect.Running {
continue
}
log.Print(inspect)
if inspect.ExitCode != 0 {
return false, fmt.Errorf("execution failed with exit code: %d", inspect.ExitCode)
}
break
}
return true, nil
}