-
-
Notifications
You must be signed in to change notification settings - Fork 11
/
enqueue.go
145 lines (130 loc) · 3.41 KB
/
enqueue.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
package main
import (
"bytes"
"encoding/json"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"strconv"
"github.com/rafecolton/docker-builder/server"
"github.com/rafecolton/go-gitutils"
"github.com/codegangsta/cli"
"github.com/onsi/gocleanup"
)
// EnqueueOptions is a struct for sending options to an Enqueuer
type EnqueueOptions struct {
Bobfile string
Host string
Top string
}
// Enqueuer is a struct that handles parsing the repo data and making the
// actual enqueue request for the `docker-builder enqueue` feature
type Enqueuer struct {
account string
bobfile string
host string
ref string
repo string
}
func enqueue(c *cli.Context) {
var top = os.Getenv("PWD")
var bobfile = c.Args().First()
if bobfile == "" {
bobfile = "Bobfile"
}
if !git.IsClean(top) {
Logger.Error("cannot enqueue, working directory is dirty")
gocleanup.Exit(1)
}
upToDate := git.UpToDate(top)
if upToDate != git.StatusUpToDate {
switch upToDate {
case git.StatusNeedToPull:
Logger.Warn("CAUTION: need to pull")
case git.StatusNeedToPush:
Logger.Warn("CAUTION: need to push")
case git.StatusDiverged:
Logger.Error("cannot enqueue, status has diverged from remote")
gocleanup.Exit(1)
}
}
var host = c.String("host")
opts := EnqueueOptions{
Host: host,
Bobfile: bobfile,
Top: top,
}
enqueuer := NewEnqueuer(opts)
result, err := enqueuer.Enqueue()
if err != nil {
Logger.Errorf("error enqueueing build: %q", err.Error())
gocleanup.Exit(1)
}
Logger.Debugln(result)
gocleanup.Exit(0)
}
// NewEnqueuer returns an Enqueuer with data populated from the repo
// information
func NewEnqueuer(options EnqueueOptions) *Enqueuer {
return &Enqueuer{
account: git.RemoteAccount(options.Top),
bobfile: options.Bobfile,
host: options.Host,
ref: git.Branch(options.Top),
repo: filepath.Base(options.Top),
}
}
// BodyBytes returns the byte slice that enc would send in an enqueue request
func (enc *Enqueuer) BodyBytes() ([]byte, error) {
var body = map[string]string{
"account": enc.account,
"repo": enc.repo,
"ref": enc.ref,
"bobfile": enc.bobfile,
}
bodyBytes, err := json.Marshal(body)
if err != nil {
return nil, err
}
return bodyBytes, nil
}
// RequestPath returns the path to which enqueue requests are sent. This
// includes both the host and the route
func (enc *Enqueuer) RequestPath() string {
return enc.host + server.BuildRoute
}
// Request returns the http request that will be sent for enqueueing
func (enc *Enqueuer) Request() (*http.Request, error) {
bodyBytes, err := enc.BodyBytes()
if err != nil {
return nil, err
}
req, err := http.NewRequest(
"POST",
enc.RequestPath(),
bytes.NewReader(bodyBytes),
)
req.Header.Add("Content-Length", strconv.Itoa(len(bodyBytes)))
req.Header.Add("Content-Type", "application/json")
return req, nil
}
// Enqueue performs an actual http request using the result of Request().
// Enqueue() should not be called during tests
func (enc *Enqueuer) Enqueue() (string, error) {
req, err := enc.Request()
if err != nil {
return "", err
}
reqBody, _ := ioutil.ReadAll(req.Body)
req.Body = ioutil.NopCloser(bytes.NewReader(reqBody)) // reset body after reading
Logger.Debugf("enqueueing request %s", reqBody)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
contentBytes, _ := ioutil.ReadAll(resp.Body)
return string(contentBytes), nil
}