forked from runatlantis/atlantis
-
Notifications
You must be signed in to change notification settings - Fork 0
/
project_config.go
133 lines (119 loc) · 4.95 KB
/
project_config.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
package events
import (
"io/ioutil"
"os"
"path/filepath"
"github.com/hashicorp/go-version"
"github.com/pkg/errors"
"gopkg.in/yaml.v2"
)
// ProjectConfigFile is the filename of Atlantis project config.
const ProjectConfigFile = "atlantis.yaml"
//go:generate pegomock generate -m --use-experimental-model-gen --package mocks -o mocks/mock_project_config_reader.go ProjectConfigReader
// ProjectConfigReader implements reading project config.
type ProjectConfigReader interface {
// Exists returns true if a project config file exists at projectPath.
Exists(projectPath string) bool
// Read attempts to read the project config file for the project at projectPath.
// NOTE: projectPath is not the path to the actual config file, just to the
// project root.
// Returns the parsed ProjectConfig or error if unable to read.
Read(projectPath string) (ProjectConfig, error)
}
// Hook represents the commands that can be run at a certain stage.
type Hook struct {
Commands []string `yaml:"commands"`
}
// projectConfigYAML is used to parse the YAML.
type projectConfigYAML struct {
PreInit Hook `yaml:"pre_init"`
PreGet Hook `yaml:"pre_get"`
PrePlan Hook `yaml:"pre_plan"`
PostPlan Hook `yaml:"post_plan"`
PreApply Hook `yaml:"pre_apply"`
PostApply Hook `yaml:"post_apply"`
TerraformVersion string `yaml:"terraform_version"`
ExtraArguments []commandExtraArguments `yaml:"extra_arguments"`
}
// ProjectConfig is a more usable version of projectConfigYAML that we can
// return to our callers. It holds the config for a project.
type ProjectConfig struct {
// PreInit is a slice of command strings to run prior to terraform init.
PreInit []string
// PreGet is a slice of command strings to run prior to terraform get.
PreGet []string
// PrePlan is a slice of command strings to run prior to terraform plan.
PrePlan []string
// PostPlan is a slice of command strings to run after terraform plan.
PostPlan []string
// PreApply is a slice of command strings to run prior to terraform apply.
PreApply []string
// PostApply is a slice of command strings to run after terraform apply.
PostApply []string
// TerraformVersion is the version specified in the config file or nil
// if version wasn't specified.
TerraformVersion *version.Version
// extraArguments is the extra args that we should tack on to certain
// terraform commands. It shouldn't be used directly and instead callers
// should use the GetExtraArguments method on ProjectConfig.
extraArguments []commandExtraArguments
}
// commandExtraArguments is used to parse the config file. These are the args
// that should be tacked on to certain terraform commands.
type commandExtraArguments struct {
// Name is the name of the command we should add the args to.
Name string `yaml:"command_name"`
// Arguments is the list of args we should append.
Arguments []string `yaml:"arguments"`
}
// ProjectConfigManager deals with project config files that users can
// use to specify additional behaviour around how Atlantis executes for a project.
type ProjectConfigManager struct{}
// Exists returns true if an atlantis config file exists for the project at
// projectPath. projectPath is an absolute path to the project.
func (c *ProjectConfigManager) Exists(projectPath string) bool {
_, err := os.Stat(filepath.Join(projectPath, ProjectConfigFile))
return err == nil
}
// Read attempts to read the project config file for the project at projectPath.
// NOTE: projectPath is not the path to the actual config file.
// Returns the parsed ProjectConfig or error if unable to read.
func (c *ProjectConfigManager) Read(execPath string) (ProjectConfig, error) {
var pc ProjectConfig
filename := filepath.Join(execPath, ProjectConfigFile)
raw, err := ioutil.ReadFile(filename)
if err != nil {
return pc, errors.Wrapf(err, "reading %s", ProjectConfigFile)
}
var pcYaml projectConfigYAML
if err = yaml.Unmarshal(raw, &pcYaml); err != nil {
return pc, errors.Wrapf(err, "parsing %s", ProjectConfigFile)
}
var v *version.Version
if pcYaml.TerraformVersion != "" {
v, err = version.NewVersion(pcYaml.TerraformVersion)
if err != nil {
return pc, errors.Wrap(err, "parsing terraform_version")
}
}
return ProjectConfig{
TerraformVersion: v,
extraArguments: pcYaml.ExtraArguments,
PreInit: pcYaml.PreInit.Commands,
PreGet: pcYaml.PreGet.Commands,
PostApply: pcYaml.PostApply.Commands,
PreApply: pcYaml.PreApply.Commands,
PrePlan: pcYaml.PrePlan.Commands,
PostPlan: pcYaml.PostPlan.Commands,
}, nil
}
// GetExtraArguments returns the arguments that were specified to be appended
// to command in the project config file.
func (c *ProjectConfig) GetExtraArguments(command string) []string {
for _, value := range c.extraArguments {
if value.Name == command {
return value.Arguments
}
}
return nil
}