Skip to content

Commit

Permalink
feat: fogg create tfe folder (#730)
Browse files Browse the repository at this point in the history
* feat: tfe generated by fogg

* feat: fogg tfe is code generated

* adding test templates

* update to a public repo for tests

* added locals.tf
  • Loading branch information
jakeyheath authored Sep 19, 2022
1 parent 18a1722 commit b259e9b
Show file tree
Hide file tree
Showing 52 changed files with 1,406 additions and 44 deletions.
76 changes: 51 additions & 25 deletions apply/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import (
const rootPath = "terraform"

// Apply will run a plan and apply all the changes to the current repo.
func Apply(fs afero.Fs, conf *v2.Config, tmp *templates.T, upgrade bool) error {
func Apply(fs afero.Fs, conf *v2.Config, tmpl *templates.T, upgrade bool) error {
if !upgrade {
toolVersion, err := util.VersionString()
if err != nil {
Expand All @@ -45,55 +45,54 @@ func Apply(fs afero.Fs, conf *v2.Config, tmp *templates.T, upgrade bool) error {
if err != nil {
return errs.WrapUser(err, "unable to evaluate plan")
}
err = applyRepo(fs, plan, tmp.Repo, tmp.Common)
err = applyRepo(fs, plan, tmpl.Repo, tmpl.Common)
if err != nil {
return errs.WrapUser(err, "unable to apply repo")
}

if plan.TravisCI.Enabled {
err = applyTree(fs, tmp.TravisCI, tmp.Common, "", plan.TravisCI)
err = applyTree(fs, tmpl.TravisCI, tmpl.Common, "", plan.TravisCI)
if err != nil {
return errs.WrapUser(err, "unable to apply travis ci")
}
}

if plan.CircleCI.Enabled {
err = applyTree(fs, tmp.CircleCI, tmp.Common, "", plan.CircleCI)
err = applyTree(fs, tmpl.CircleCI, tmpl.Common, "", plan.CircleCI)
if err != nil {
return errs.WrapUser(err, "unable to apply CircleCI")
}
}

if plan.GitHubActionsCI.Enabled {
err = applyTree(fs, tmp.GitHubActionsCI, tmp.Common, ".github", plan.GitHubActionsCI)
err = applyTree(fs, tmpl.GitHubActionsCI, tmpl.Common, ".github", plan.GitHubActionsCI)
if err != nil {
return errs.WrapUser(err, "unable to apply GitHub Actions CI")
}
}

tfBox := tmp.Components[v2.ComponentKindTerraform]
err = applyAccounts(fs, plan, tfBox, tmp.Common)
tfBox := tmpl.Components[v2.ComponentKindTerraform]
err = applyAccounts(fs, plan, tfBox, tmpl.Common)
if err != nil {
return errs.WrapUser(err, "unable to apply accounts")
}

err = applyEnvs(fs, plan, tmp.Env, tmp.Components, tmp.Common)
err = applyEnvs(fs, plan, tmpl.Env, tmpl.Components, tmpl.Common)
if err != nil {
return errs.WrapUser(err, "unable to apply envs")
}

tfBox = tmp.Components[v2.ComponentKindTerraform]
err = applyGlobal(fs, plan.Global, tfBox, tmp.Common)
tfBox = tmpl.Components[v2.ComponentKindTerraform]
err = applyGlobal(fs, plan.Global, tfBox, tmpl.Common)
if err != nil {
return errs.WrapUser(err, "unable to apply global")
}

err = applyModules(fs, plan.Modules, tmp.Module, tmp.Common)
err = applyModules(fs, plan.Modules, tmpl.Module, tmpl.Common)
if err != nil {
return errs.WrapUser(err, "unable to apply modules")
}

return errs.WrapUser(applyTFE(fs, plan), "unable to apply TFE locals.tf.json")
return errs.WrapUser(applyTFE(fs, plan, tmpl), "unable to apply TFE locals.tf.json")
}

type LocalsTFE struct {
Expand Down Expand Up @@ -189,15 +188,7 @@ func updateLocalsFromPlan(locals *LocalsTFE, plan *plan.Plan) {
}
}

func applyTFE(fs afero.Fs, plan *plan.Plan) error {
tfePath := filepath.Join("terraform", "tfe", "locals.tf.json")
_, err := fs.Stat(tfePath)
// if the repo doesn't have a locals.tf.json, don't worry about it
if errors.Is(err, os.ErrNotExist) {
return nil
} else if err != nil {
return err
}
func updateLocalsTFEFile(fs afero.Fs, tfePath string, plan *plan.Plan) error {
read, err := fs.Open(tfePath)
if err != nil {
return errors.Wrapf(err, "unable to open locals.tf.json file %s for unmarshalling", tfePath)
Expand All @@ -217,12 +208,47 @@ func applyTFE(fs afero.Fs, plan *plan.Plan) error {
defer write.Close()
encoder := json.NewEncoder(write)
encoder.SetIndent("", " ")
err = encoder.Encode(locals)
return errors.Wrap(encoder.Encode(locals), "unable to marhsal locals.tf.json")
}

func applyTFE(fs afero.Fs, plan *plan.Plan, tmpl *templates.T) error {
// the TFE configuration is optional
if plan.TFE == nil {
return nil
}

logrus.Debug("applying tfe")
path := fmt.Sprintf("%s/tfe", rootPath)
err := fs.MkdirAll(path, 0755)
if err != nil {
return errors.Wrapf(err, "unable to make directory %s", path)
}
err = applyTree(fs, tmpl.Components[v2.ComponentKindTerraform], tmpl.Common, path, plan.TFE)
if err != nil {
return err
}
err = applyTree(fs, tmpl.TFE, tmpl.Common, path, plan.TFE)
if err != nil {
return errors.Wrap(err, "unable to marhsal locals.tf.json")
return err
}
if plan.TFE.ModuleSource != nil {
downloader, err := util.MakeDownloader(*plan.TFE.ModuleSource)
if err != nil {
return errs.WrapUser(err, "unable to make a downloader")
}
err = applyModuleInvocation(fs, path, *plan.TFE.ModuleSource, plan.TFE.ModuleName, templates.Templates.ModuleInvocation, tmpl.Common, downloader)
if err != nil {
return errs.WrapUser(err, "unable to apply module invocation")
}
}

return nil
tfePath := filepath.Join("terraform", "tfe", "locals.tf.json")
_, err = fs.Stat(tfePath)
if err != nil {
return errors.Wrapf(err, "unable to stat on %s", tfePath)
}

return updateLocalsTFEFile(fs, tfePath, plan)
}

func checkToolVersions(fs afero.Fs, current string) (bool, string, error) {
Expand Down
1 change: 1 addition & 0 deletions apply/golden_file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func TestIntegration(t *testing.T) {
{"circleci"},
{"tfe_provider_yaml"},
{"remote_backend_yaml"},
{"tfe_config"},
}

for _, test := range testCases {
Expand Down
19 changes: 16 additions & 3 deletions config/v2/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
yaml "gopkg.in/yaml.v3"
)

//ReadConfig take a byte array as input and outputs a json or yaml config struct
// ReadConfig take a byte array as input and outputs a json or yaml config struct
func ReadConfig(fs afero.Fs, b []byte, configFile string) (*Config, error) {
var e error
c := &Config{}
Expand Down Expand Up @@ -60,6 +60,19 @@ type Config struct {
Modules map[string]Module `yaml:"modules,omitempty"`
Plugins Plugins `yaml:"plugins,omitempty"`
Version int `validate:"required,eq=2"`
TFE *TFE `yaml:"tfe,omitempty"`
}

type TFE struct {
Component `yaml:",inline"`
ReadTeams *[]string `yaml:"read_teams,omitempty"`
Branch *string `yaml:"branch,omitempty"`
GithubOrg *string `yaml:"gh_org,omitempty"`
GithubRepo *string `yaml:"gh_repo,omitempty"`
TFEOrg string `yaml:"tfe_org,omitempty"`
SSHKeyName *string `yaml:"ssh_key_name,omitempty"`
ExcludedGithubRequiredChecks *[]string `yaml:"excluded_gh_required_checks,omitempty"`
AdditionalGithubRequiredChecks *[]string `yaml:"additional_gh_required_checks,omitempty"`
}

type Common struct {
Expand Down Expand Up @@ -145,7 +158,7 @@ type CommonProvider struct {
Version *string `yaml:"version,omitempty"`
}

//Auth0Provider is the terraform provider for the Auth0 service.
// Auth0Provider is the terraform provider for the Auth0 service.
type Auth0Provider struct {
Version *string `yaml:"version,omitempty"`
Domain *string `yaml:"domain,omitempty"`
Expand Down Expand Up @@ -238,7 +251,7 @@ type KubernetesProvider struct {
CommonProvider `yaml:",inline"`
}

//Backend is used to configure a terraform backend
// Backend is used to configure a terraform backend
type Backend struct {
Kind *string `yaml:"kind,omitempty" validate:"omitempty,oneof=s3 remote"`

Expand Down
12 changes: 12 additions & 0 deletions config/v2/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/chanzuckerberg/fogg/errs"
multierror "github.com/hashicorp/go-multierror"
goVersion "github.com/hashicorp/go-version"
"github.com/pkg/errors"
validator "gopkg.in/go-playground/validator.v9"
)

Expand Down Expand Up @@ -52,6 +53,7 @@ func (c *Config) Validate() ([]string, error) {
errs = multierror.Append(errs, c.validateModules())
errs = multierror.Append(errs, c.ValidateTravis())
errs = multierror.Append(errs, c.ValidateGithubActionsCI())
errs = multierror.Append(errs, c.validateTFE())

// refactor to make it easier to manage these
w, e := c.ValidateToolsTfLint()
Expand Down Expand Up @@ -274,6 +276,16 @@ func (c *Config) ValidateTravis() error {
return errs
}

func (c *Config) validateTFE() error {
var errs *multierror.Error

if c.TFE != nil && c.TFE.TFEOrg == "" {
errs = multierror.Append(errs, errors.Errorf("tfe org is required"))
}

return errs
}

func (c *Config) ValidateGithubActionsCI() error {
var errs *multierror.Error
c.WalkComponents(func(component string, comms ...Common) {
Expand Down
14 changes: 13 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/davecgh/go-spew v1.1.1
github.com/fatih/color v1.10.0
github.com/go-errors/errors v1.1.1
github.com/go-git/go-git/v5 v5.4.2
github.com/google/go-github/v27 v27.0.6
github.com/hashicorp/go-getter v1.6.2
github.com/hashicorp/go-multierror v1.1.1
Expand Down Expand Up @@ -43,13 +44,19 @@ require (
cloud.google.com/go/storage v1.10.0 // indirect
github.com/Masterminds/goutils v1.1.0 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
github.com/Microsoft/go-winio v0.4.16 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect
github.com/acomagu/bufpipe v1.0.3 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/apparentlymart/go-cidr v1.1.0 // indirect
github.com/apparentlymart/go-textseg v1.0.0 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/apparentlymart/go-versions v1.0.1 // indirect
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
github.com/bmatcuk/doublestar v1.2.4 // indirect
github.com/emirpasic/gods v1.12.0 // indirect
github.com/go-git/gcfg v1.5.0 // indirect
github.com/go-git/go-billy/v5 v5.3.1 // indirect
github.com/go-playground/locales v0.13.0 // indirect
github.com/go-playground/universal-translator v0.17.0 // indirect
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
Expand All @@ -68,10 +75,12 @@ require (
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 // indirect
github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c // indirect
github.com/huandu/xstrings v1.3.1 // indirect
github.com/imdario/mergo v0.3.9 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jstemmer/go-junit-report v0.9.1 // indirect
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
github.com/klauspost/compress v1.11.2 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/leodido/go-urn v1.2.0 // indirect
Expand All @@ -82,9 +91,11 @@ require (
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mitchellh/reflectwalk v1.0.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/sergi/go-diff v1.1.0 // indirect
github.com/ulikunitz/xz v0.5.8 // indirect
github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect
github.com/vmihailenco/tagparser v0.1.1 // indirect
github.com/xanzy/ssh-agent v0.3.0 // indirect
github.com/zclconf/go-cty v1.8.0 // indirect
github.com/zclconf/go-cty-yaml v1.0.2 // indirect
go.opencensus.io v0.22.4 // indirect
Expand All @@ -103,4 +114,5 @@ require (
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d // indirect
google.golang.org/grpc v1.31.1 // indirect
google.golang.org/protobuf v1.25.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
)
Loading

0 comments on commit b259e9b

Please sign in to comment.