-
Notifications
You must be signed in to change notification settings - Fork 1
/
resource_io.go
158 lines (147 loc) · 4.22 KB
/
resource_io.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
package concourse_tfe_resource
import (
"encoding/json"
"errors"
"fmt"
"github.com/drone/envsubst"
tfe "github.com/hashicorp/go-tfe"
"io"
"log"
"net/url"
"os"
)
type (
version struct {
Ref string `json:"ref"`
}
sourceJSON struct {
Workspace string `json:"workspace"`
Organization string `json:"organization"`
Token string `json:"token"`
Address string `json:"address"`
}
inputJSON struct {
Params paramsJSON `json:"params"`
Source sourceJSON `json:"source"`
Version version `json:"version"`
}
versionMetadata struct {
Name string `json:"name"`
Value string `json:"value"`
}
checkOutputJSON []version
inOutputJSON struct {
Version version `json:"version"`
Metadata []versionMetadata `json:"metadata"`
}
outOutputJSON inOutputJSON
paramsJSON struct {
Vars map[string]variableJSON `json:"vars"`
Message string `json:"message"`
Confirm bool `json:"confirm"`
PollingPeriod int `json:"polling_period"`
Sensitive bool `json:"sensitive"`
ApplyMessage string `json:"apply_message"`
}
variableJSON struct {
File string `json:"file"`
Value string `json:"value"`
Description string `json:"description"`
Category tfe.CategoryType `json:"category"`
Sensitive bool `json:"sensitive"`
Hcl bool `json:"hcl"`
}
)
func (v variableJSON) UnmarshalJSON(b []byte) error {
type VJ variableJSON
var vj = (*VJ)(&v)
vj.Category = tfe.CategoryTerraform
if err := json.Unmarshal(b, vj); err != nil {
return err
}
// for some reason this structure includes "policy-set" which you can't set as a variable
if v.Category == tfe.CategoryTerraform || v.Category == tfe.CategoryEnv {
return nil
}
return errors.New("invalid variable type")
}
func getInputs(in io.Reader) (inputJSON, error) {
input := inputJSON{}
input.Source = sourceJSON{
Address: "https://app.terraform.io",
}
input.Params = paramsJSON{
Message: "Queued by ${pipeline}/${job} (${number})",
PollingPeriod: 5,
Sensitive: false,
}
decoder := json.NewDecoder(in)
decoder.DisallowUnknownFields()
if err := decoder.Decode(&input); err != nil {
return input, formatError(err, "parsing input")
}
// a few sanity checks
if !validateInput(&input) {
return input, fmt.Errorf("invalid configuration provided")
}
return input, nil
}
func validateInput(input *inputJSON) (validConfig bool) {
validConfig = true
message, err := parseMessage(input.Params.ApplyMessage)
input.Params.ApplyMessage = message
if err != nil {
log.Printf("error in source configuration: invalid apply message (%s)", err)
validConfig = false
}
message, err = parseMessage(input.Params.Message)
input.Params.Message = message
if err != nil {
log.Printf("error in source configuration: invalid run message (%s)", err)
validConfig = false
}
if _, err := url.ParseRequestURI(input.Source.Address); err != nil {
log.Printf("error in source configuration: \"%v\" is not a valid URL", input.Source.Address)
validConfig = false
}
if input.Source.Workspace == "" {
log.Print("error in source configuration: workspace is not set")
validConfig = false
}
if input.Source.Organization == "" {
log.Print("error in source configuration: organization is not set")
validConfig = false
}
if input.Source.Token == "" {
log.Print("error in source configuration: token is not set")
validConfig = false
}
if input.Params.PollingPeriod < 1 {
log.Print("error in parameter value: polling_period must be at least 1 second")
validConfig = false
}
return validConfig
}
func parseMessage(message string) (string, error) {
return envsubst.Eval(message, func(varName string) string {
envVar := "NONEXISTENT_VALUE"
switch varName {
case "id":
envVar = "BUILD_ID"
case "number":
envVar = "BUILD_NAME"
case "job":
envVar = "BUILD_JOB_NAME"
case "pipeline":
envVar = "BUILD_PIPELINE_NAME"
case "team":
envVar = "BUILD_TEAM_NAME"
case "url":
envVar = "ATC_EXTERNAL_URL"
}
return os.Getenv(envVar)
})
}
func formatError(err error, context string) error {
return fmt.Errorf("error %s: %w", context, err)
}