forked from daidokoro/qaz
-
Notifications
You must be signed in to change notification settings - Fork 0
/
helpers.go
254 lines (205 loc) · 5.79 KB
/
helpers.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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
package commands
// -- Contains helper functions
import (
"bufio"
"bytes"
"errors"
"fmt"
"io/ioutil"
"net/http"
"os"
"runtime"
"strconv"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/cloudformation"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/ttacon/chalk"
)
// configTemplate - Returns template byte string for init() function
func configTemplate(project string, region string) []byte {
return []byte(fmt.Sprintf(`
# Specify the AWS region code
# qaz will attempt to get it from AWS configuration
# or from the environment. This setting overrides
# every other.
region: %s
# Required: specify the name of the Project
# (qaz will prepend this value to the stack
# names defined below.
project: %s
# Optional: global values accisible accross
# all stacks can be define under global
global:
# Stack-specific variables and
# arbitrary keys cab be defined here,
# Under the [stacks] key word,
stacks:
# Note that the stack name must match the file name of the template file. The extension does not need to be specified.
your_stack_name_here:
cf:
your_key/value_pairs_here:
`, region, project))
}
// colorMap - Used to map a particular color to a cf status phrase - returns lowercase strings in color.
func colorMap(s string) string {
// If Windows, disable colorS
if runtime.GOOS == "windows" {
return s
}
v := strings.Split(s, "_")[len(strings.Split(s, "_"))-1]
var result string
switch v {
case "COMPLETE":
result = chalk.Green.Color(s)
case "PROGRESS":
result = chalk.Yellow.Color(s)
case "FAILED":
result = chalk.Red.Color(s)
case "SKIPPED":
result = chalk.Blue.Color(s)
default:
// Unidentified, just returns the same string
return strings.ToLower(s)
}
return strings.ToLower(result)
}
// colorString - Returns colored string
func colorString(s string, color string) string {
// If Windows, disable colorS
if runtime.GOOS == "windows" {
return s
}
var result string
switch strings.ToLower(color) {
case "green":
result = chalk.Green.Color(s)
case "yellow":
result = chalk.Yellow.Color(s)
case "red":
result = chalk.Red.Color(s)
case "magenta":
result = chalk.Magenta.Color(s)
default:
// Unidentified, just returns the same string
return s
}
return result
}
// verbose - Takes a stackname and tracks the progress of creating the stack. s - stackname, c - command Type
func verbose(s string, c string, session *session.Session) {
svc := cloudformation.New(session)
params := &cloudformation.DescribeStackEventsInput{
StackName: aws.String(s),
}
// used to track what lines have already been printed, to prevent dubplicate output
printed := make(map[string]interface{})
for {
Log(fmt.Sprintf("Calling [DescribeStackEvents] with parameters: %s", params), level.debug)
stackevents, err := svc.DescribeStackEvents(params)
if err != nil {
Log(fmt.Sprintln("Error when tailing events: ", err.Error()), level.debug)
}
Log(fmt.Sprintln("Response:", stackevents), level.debug)
for _, event := range stackevents.StackEvents {
statusReason := ""
if strings.Contains(*event.ResourceStatus, "FAILED") {
statusReason = *event.ResourceStatusReason
}
line := strings.Join([]string{
colorMap(*event.ResourceStatus),
*event.StackName,
*event.ResourceType,
*event.LogicalResourceId,
statusReason,
}, " - ")
if _, ok := printed[line]; !ok {
if strings.Split(*event.ResourceStatus, "_")[0] == c || c == "" {
Log(strings.Trim(line, "- "), level.info)
}
printed[line] = nil
}
}
// Sleep 2 seconds before next check
time.Sleep(time.Duration(2 * time.Second))
}
}
// all - returns true if all items in array the same as the given string
func all(a []string, s string) bool {
for _, str := range a {
if s != str {
return false
}
}
return true
}
// stringIn - returns true if string in array
func stringIn(s string, a []interface{}) bool {
Log(fmt.Sprintf("Checking If [%s] is in: %s", s, a), level.debug)
for _, str := range a {
if str.(string) == s {
return true
}
}
return false
}
// getInput - reads input from stdin - request & default (if no input)
func getInput(request string, def string) string {
r := bufio.NewReader(os.Stdin)
fmt.Printf("%s [%s]:", request, def)
t, _ := r.ReadString('\n')
// using len as t will always have atleast 1 char, "\n"
if len(t) > 1 {
return strings.Trim(t, "\n")
}
return def
}
// Get - HTTP Get request of given url and returns string
func Get(url string) (string, error) {
timeout := time.Duration(10 * time.Second)
client := http.Client{
Timeout: timeout,
}
resp, err := client.Get(url)
if resp == nil {
return "", errors.New(fmt.Sprintln("Error, GET request timeout @:", url))
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return "", fmt.Errorf("GET request failed, url: %s - Status:[%s]", url, strconv.Itoa(resp.StatusCode))
}
if err != nil {
return "", err
}
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
return string(b), nil
}
// S3Read - Reads the content of a given s3 url endpoint and returns the content string.
func S3Read(url string) (string, error) {
sess, err := awsSession()
if err != nil {
return "", err
}
svc := s3.New(sess)
// Parse s3 url
bucket := strings.Split(strings.Replace(strings.ToLower(url), `s3://`, "", -1), `/`)[0]
key := strings.Replace(strings.ToLower(url), fmt.Sprintf("s3://%s/", bucket), "", -1)
params := &s3.GetObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
}
Log(fmt.Sprintln("Calling S3 [GetObject] with parameters:", params), level.debug)
resp, err := svc.GetObject(params)
if err != nil {
return "", err
}
buf := new(bytes.Buffer)
Log("Reading from S3 Response Body", level.debug)
buf.ReadFrom(resp.Body)
return buf.String(), nil
}