-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
Copy pathrepo_cfg.go
211 lines (188 loc) · 5.92 KB
/
repo_cfg.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
// Package valid contains the structs representing the atlantis.yaml config
// after it's been parsed and validated.
package valid
import (
"fmt"
"log"
"regexp"
"strings"
version "github.com/hashicorp/go-version"
)
// RepoCfg is the atlantis.yaml config after it's been parsed and validated.
type RepoCfg struct {
// Version is the version of the atlantis YAML file.
Version int
Projects []Project
Workflows map[string]Workflow
PolicySets PolicySets
Automerge *bool
AutoDiscover *AutoDiscover
ParallelApply *bool
ParallelPlan *bool
ParallelPolicyCheck *bool
DeleteSourceBranchOnMerge *bool
RepoLocking *bool
CustomPolicyCheck *bool
EmojiReaction string
AllowedRegexpPrefixes []string
AbortOnExcecutionOrderFail bool
}
func (r RepoCfg) FindProjectsByDirWorkspace(repoRelDir string, workspace string) []Project {
var ps []Project
for _, p := range r.Projects {
if p.Dir == repoRelDir && p.Workspace == workspace {
ps = append(ps, p)
}
}
return ps
}
// FindProjectsByDir returns all projects that are in dir.
func (r RepoCfg) FindProjectsByDir(dir string) []Project {
var ps []Project
for _, p := range r.Projects {
if p.Dir == dir {
ps = append(ps, p)
}
}
return ps
}
func (r RepoCfg) FindProjectByName(name string) *Project {
for _, p := range r.Projects {
if p.Name != nil && *p.Name == name {
return &p
}
}
return nil
}
// FindProjectsByName returns all projects that match with name.
func (r RepoCfg) FindProjectsByName(name string) []Project {
var ps []Project
sanitizedName := "^" + name + "$"
for _, p := range r.Projects {
if p.Name != nil {
if match, _ := regexp.MatchString(sanitizedName, *p.Name); match {
ps = append(ps, p)
}
}
}
// If we found more than one project then we need to make sure that the regex is allowed.
if len(ps) > 1 && !isRegexAllowed(name, r.AllowedRegexpPrefixes) {
log.Printf("Found more than one project for regex %q. This regex is not on the allow list.", name)
return nil
}
return ps
}
func isRegexAllowed(name string, allowedRegexpPrefixes []string) bool {
if len(allowedRegexpPrefixes) == 0 {
return true
}
for _, allowedRegexPrefix := range allowedRegexpPrefixes {
if strings.HasPrefix(name, allowedRegexPrefix) {
return true
}
}
return false
}
// This function returns a final true/false decision for whether AutoDiscover is enabled
// for a repo. It takes into account the defaultAutoDiscoverMode when there is no explicit
// repo config. The defaultAutoDiscoverMode param should be understood as the default
// AutoDiscover mode as may be set via CLI params or server side repo config.
func (r RepoCfg) AutoDiscoverEnabled(defaultAutoDiscoverMode AutoDiscoverMode) bool {
autoDiscoverMode := defaultAutoDiscoverMode
if r.AutoDiscover != nil {
autoDiscoverMode = r.AutoDiscover.Mode
}
if autoDiscoverMode == AutoDiscoverAutoMode {
// AutoDiscover is enabled by default when no projects are defined
return len(r.Projects) == 0
}
return autoDiscoverMode == AutoDiscoverEnabledMode
}
// validateWorkspaceAllowed returns an error if repoCfg defines projects in
// repoRelDir but none of them use workspace. We want this to be an error
// because if users have gone to the trouble of defining projects in repoRelDir
// then it's likely that if we're running a command for a workspace that isn't
// defined then they probably just typed the workspace name wrong.
func (r RepoCfg) ValidateWorkspaceAllowed(repoRelDir string, workspace string) error {
projects := r.FindProjectsByDir(repoRelDir)
// If that directory doesn't have any projects configured then we don't
// enforce workspace names.
if len(projects) == 0 {
return nil
}
var configuredSpaces []string
for _, p := range projects {
if p.Workspace == workspace {
return nil
}
configuredSpaces = append(configuredSpaces, p.Workspace)
}
return fmt.Errorf(
"running commands in workspace %q is not allowed because this"+
" directory is only configured for the following workspaces: %s",
workspace,
strings.Join(configuredSpaces, ", "),
)
}
type Project struct {
Dir string
BranchRegex *regexp.Regexp
Workspace string
Name *string
WorkflowName *string
TerraformVersion *version.Version
Autoplan Autoplan
PlanRequirements []string
ApplyRequirements []string
ImportRequirements []string
DependsOn []string
DeleteSourceBranchOnMerge *bool
RepoLocking *bool
ExecutionOrderGroup int
PolicyCheck *bool
CustomPolicyCheck *bool
}
// GetName returns the name of the project or an empty string if there is no
// project name.
func (p Project) GetName() string {
if p.Name != nil {
return *p.Name
}
return ""
}
type Autoplan struct {
WhenModified []string
Enabled bool
}
// PostProcessRunOutputOption is an enum of options for post-processing RunCommand output
type PostProcessRunOutputOption string
const (
PostProcessRunOutputShow = "show"
PostProcessRunOutputHide = "hide"
PostProcessRunOutputStripRefreshing = "strip_refreshing"
)
type Stage struct {
Steps []Step
}
type Step struct {
StepName string
ExtraArgs []string
// RunCommand is either a custom run step or the command to run
// during an env step to populate the environment variable dynamically.
RunCommand string
// Output is option for post-processing a RunCommand output
Output PostProcessRunOutputOption
// EnvVarName is the name of the
// environment variable that should be set by this step.
EnvVarName string
// EnvVarValue is the value to set EnvVarName to.
EnvVarValue string
}
type Workflow struct {
Name string
Apply Stage
Plan Stage
PolicyCheck Stage
Import Stage
StateRm Stage
}