forked from chanzuckerberg/fogg
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[feature] atlantis integration (chanzuckerberg#303)
[feature] atlantis integrationThis PR adds Atlantis (<runatlantis.io>) integration to fogg. The goal is to be able to use fogg to generate an atlantis.yaml configuration file and all related tools, scripts etc. Happy to take feedback on both the approach and the implementation. ### Approach The basic approach is, in no particular order– * To the degree possible it would be great to be able to make changes to how Atlantis works without touching the Atlantis instances, so as much as possible is put into the per-repo config file. * We allow configuring Atlantis on a per-component basis. I think this is important as I would expect teams to adopt it incrementally. * We do a 2-phase plan - first . plan for each component (so that we can set a var in each) and then walk those plans and generate a plan for the atlantis.yaml and aws config * We generate an aws config for atlantis. Because we rely on aws profiles for authentication, we need to find a way to get the Atlantis instance configured with all the right profiles. In the future we may want to think about doing this for other modes. * If atlantis is enabled for a component, `make apply` will by default fail. You have to add `FORCE=1` to override. This should nudge people in the right direction while allowing a fall-back to running locally (important for adoption phase). * we add a `make setup` that will install fogg and run `fogg setup` (you can run this from components, not just top-level) * we no longer run `terraform get` since that is redundant with `terrraform init` and we **don't run -update=true anymore** which means that modules will not get updated. People should be using stable versions anyway and this makes it much faster * tfenv is now installed inside the repo, rather than homedir. This makes it so that we can use tfenv in atlantis (rather than atlantis' own process for getting terraform versions) --- Note there are also a handful of stylistic changes in this diff. Tried to keep those to a minimum, but also wanted to make some improvements, especially to our makefiles. ## Test Plan * unit tests * ran on shared-infra repo for 1 component ## References * <https://www.runatlantis.io/docs/> * Fixes chanzuckerberg#290 * Fixes chanzuckerberg#289 * Fixes chanzuckerberg#278
- Loading branch information
Showing
67 changed files
with
1,342 additions
and
276 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
package plan | ||
|
||
import ( | ||
"fmt" | ||
"sort" | ||
) | ||
|
||
type Atlantis struct { | ||
Enabled bool | ||
Projects []AtlantisProject | ||
|
||
// AWSProfiles is a map of profile name -> role info | ||
// TODO de-dupe this with AWSProfile in the travis-ci plan | ||
AWSProfiles map[string]AWSRole | ||
} | ||
|
||
type AtlantisProject struct { | ||
Name string `yaml:"name"` | ||
Dir string `yaml:"dir"` | ||
TerraformVersion string `yaml:"terraform_version"` | ||
PathToRepoRoot string `yaml:"path_to_repo_root"` | ||
} | ||
|
||
type AWSRole struct { | ||
AccountID string `yaml:"account_id"` | ||
RolePath string `yaml:"role_path"` | ||
RoleName string `yaml:"role_name"` | ||
} | ||
|
||
// buildAtlantis will walk all the components and build an atlantis plan | ||
func (p *Plan) buildAtlantis() Atlantis { | ||
// TODO This func has a lot of duplication. | ||
enabled := false | ||
projects := []AtlantisProject{} | ||
profiles := map[string]AWSRole{} | ||
|
||
if p.Global.Atlantis.Enabled { | ||
enabled = true | ||
proj := AtlantisProject{ | ||
Name: "global", | ||
Dir: "terraform/global", | ||
PathToRepoRoot: p.Global.PathToRepoRoot, | ||
TerraformVersion: p.Global.TerraformVersion, | ||
} | ||
|
||
projects = append(projects, proj) | ||
|
||
profiles[p.Global.Backend.Profile] = AWSRole{ | ||
AccountID: *p.Global.Backend.AccountID, | ||
RoleName: p.Global.Atlantis.RoleName, | ||
RolePath: p.Global.Atlantis.RolePath, | ||
} | ||
|
||
if p.Global.Providers.AWS != nil { | ||
a := *p.Global.Providers.AWS | ||
profiles[a.Profile] = AWSRole{ | ||
AccountID: *p.Global.Backend.AccountID, | ||
RoleName: p.Global.Atlantis.RoleName, | ||
RolePath: p.Global.Atlantis.RolePath, | ||
} | ||
} | ||
} | ||
|
||
for name, acct := range p.Accounts { | ||
if acct.Atlantis.Enabled { | ||
enabled = true | ||
proj := AtlantisProject{ | ||
Name: fmt.Sprintf("accounts/%s", name), | ||
Dir: fmt.Sprintf("terraform/accounts/%s", name), | ||
PathToRepoRoot: acct.PathToRepoRoot, | ||
TerraformVersion: acct.TerraformVersion, | ||
} | ||
projects = append(projects, proj) | ||
|
||
profiles[acct.Backend.Profile] = AWSRole{ | ||
AccountID: *acct.Backend.AccountID, | ||
RoleName: acct.Atlantis.RoleName, | ||
RolePath: acct.Atlantis.RolePath, | ||
} | ||
|
||
if acct.Providers.AWS != nil { | ||
a := *acct.Providers.AWS | ||
profiles[a.Profile] = AWSRole{ | ||
AccountID: a.AccountID.String(), | ||
RoleName: acct.Atlantis.RoleName, | ||
RolePath: acct.Atlantis.RolePath, | ||
} | ||
} | ||
} | ||
} | ||
|
||
for envName, env := range p.Envs { | ||
for cName, c := range env.Components { | ||
if c.Atlantis.Enabled { | ||
enabled = true | ||
p := AtlantisProject{ | ||
Name: fmt.Sprintf("%s/%s", envName, cName), | ||
Dir: fmt.Sprintf("terraform/envs/%s/%s", envName, cName), | ||
PathToRepoRoot: c.PathToRepoRoot, | ||
TerraformVersion: c.TerraformVersion, | ||
} | ||
projects = append(projects, p) | ||
|
||
profiles[c.Backend.Profile] = AWSRole{ | ||
AccountID: *c.Backend.AccountID, | ||
RoleName: c.Atlantis.RoleName, | ||
RolePath: c.Atlantis.RolePath, | ||
} | ||
|
||
if c.Providers.AWS != nil { | ||
a := *c.Providers.AWS | ||
profiles[a.Profile] = AWSRole{ | ||
AccountID: a.AccountID.String(), | ||
RoleName: c.Atlantis.RoleName, | ||
RolePath: c.Atlantis.RolePath, | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
// sort so that we get stable output | ||
sort.SliceStable(projects, func(i, j int) bool { | ||
return projects[i].Name < projects[j].Name | ||
}) | ||
|
||
return Atlantis{ | ||
Enabled: enabled, | ||
Projects: projects, | ||
AWSProfiles: profiles, | ||
} | ||
} |
Oops, something went wrong.