From 07ee84b55a3b1766cf8b49880f9152baa9b10db3 Mon Sep 17 00:00:00 2001 From: Ben Zarboni <99673202+bzarboni1@users.noreply.github.com> Date: Wed, 29 May 2024 15:37:45 -0400 Subject: [PATCH] refactor: don't use terragrunt to parse config (#11) * refactor: don't use terragrunt to parse config --- cmd/list/orgs/orgs.go | 4 - cmd/list/repos/repos.go | 10 +- go.mod | 22 ++- go.sum | 28 ++++ internal/pkg/functions/status.go | 91 ++++-------- internal/pkg/types/status/org_repos.go | 23 ++- internal/pkg/types/terragrunt/terragrunt.go | 149 ++++++++++++++++++++ main.go | 9 +- 8 files changed, 247 insertions(+), 89 deletions(-) diff --git a/cmd/list/orgs/orgs.go b/cmd/list/orgs/orgs.go index 7113b4b..930a901 100644 --- a/cmd/list/orgs/orgs.go +++ b/cmd/list/orgs/orgs.go @@ -46,8 +46,4 @@ var OrgsCmd = &cobra.Command{ } func init() { - os.Setenv("GCP_SECRET_MANAGER_PROJECT", "blahblah") - os.Setenv("GCP_TF_STATE_BUCKET_PROJECT", "blahblahblah") - os.Setenv("GCP_TF_STATE_BUCKET_NAME", "blahblahblahblah") - os.Setenv("GCP_TF_STATE_BUCKET_LOCATION", "blahblahblahblahblah") } diff --git a/cmd/list/repos/repos.go b/cmd/list/repos/repos.go index e2aa901..d2774cb 100644 --- a/cmd/list/repos/repos.go +++ b/cmd/list/repos/repos.go @@ -9,7 +9,6 @@ import ( "gh_foundations/internal/pkg/functions" "gh_foundations/internal/pkg/types/status" "log" - "os" "strings" "github.com/spf13/cobra" @@ -31,9 +30,7 @@ var ReposCmd = &cobra.Command{ reposDir := args[0] - ctx := cmd.Context() - - orgSet, err := functions.FindManagedRepos(ctx, reposDir) + orgSet, err := functions.FindManagedRepos(reposDir) if err != nil { log.Fatalf("Error in findManagedRepos: %s", err) } @@ -56,11 +53,6 @@ var ReposCmd = &cobra.Command{ } func init() { - os.Setenv("GCP_SECRET_MANAGER_PROJECT", "blahblah") - os.Setenv("GCP_TF_STATE_BUCKET_PROJECT", "blahblahblah") - os.Setenv("GCP_TF_STATE_BUCKET_NAME", "blahblahblahblah") - os.Setenv("GCP_TF_STATE_BUCKET_LOCATION", "blahblahblahblahblah") - ReposCmd.Flags().BoolVarP(&ghas, "ghas", "g", false, "List repositories with GHAS enabled") } diff --git a/go.mod b/go.mod index bc76975..2eb8d49 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,8 @@ go 1.21.0 require ( github.com/charmbracelet/bubbletea v0.25.0 github.com/charmbracelet/lipgloss v0.10.0 + github.com/gruntwork-io/terragrunt v0.58.9 + github.com/mitchellh/mapstructure v1.5.0 github.com/spf13/afero v1.11.0 github.com/spf13/cobra v1.8.0 ) @@ -62,9 +64,10 @@ require ( github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect github.com/creack/pty v1.1.17 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dlclark/regexp2 v1.4.0 // indirect github.com/fatih/color v1.15.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/getsops/gopgagent v0.0.0-20170926210634-4d7ea76ff71a // indirect github.com/getsops/sops/v3 v3.8.1 // indirect github.com/gitsight/go-vcsurl v1.0.1 // indirect @@ -94,7 +97,6 @@ require ( github.com/gruntwork-io/boilerplate v0.5.11 // indirect github.com/gruntwork-io/go-commons v0.17.1 // indirect github.com/gruntwork-io/gruntwork-cli v0.7.0 // indirect - github.com/gruntwork-io/terragrunt v0.58.9 // indirect github.com/gruntwork-io/terratest v0.41.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -132,6 +134,7 @@ require ( github.com/labstack/gommon v0.4.2 // indirect github.com/lib/pq v1.10.9 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-localereader v0.0.1 // indirect @@ -143,7 +146,6 @@ require ( github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/panicwrap v1.0.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b // indirect @@ -154,22 +156,28 @@ require ( github.com/oklog/run v1.1.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/owenrumney/go-sarif v1.1.1 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/posener/complete v1.2.3 // indirect github.com/pterm/pterm v0.12.41 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f // indirect github.com/shopspring/decimal v1.2.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect github.com/sourcegraph/go-lsp v0.0.0-20200429204803-219e11d77f5d // indirect github.com/sourcegraph/jsonrpc2 v0.2.0 // indirect - github.com/spf13/cast v1.3.1 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/viper v1.18.2 // indirect github.com/stretchr/objx v0.5.2 // indirect + github.com/subosito/gotenv v1.6.0 // indirect github.com/terraform-linters/tflint v0.47.0 // indirect github.com/terraform-linters/tflint-plugin-sdk v0.17.0 // indirect github.com/terraform-linters/tflint-ruleset-terraform v0.4.0 // indirect @@ -201,6 +209,8 @@ require ( go.opentelemetry.io/otel/sdk/metric v1.23.1 // indirect go.opentelemetry.io/otel/trace v1.23.1 // indirect go.opentelemetry.io/proto/otlp v1.1.0 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.9.0 // indirect golang.org/x/crypto v0.21.0 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect golang.org/x/mod v0.13.0 // indirect @@ -212,7 +222,7 @@ require ( golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.14.0 // indirect - google.golang.org/api v0.152.0 // indirect + google.golang.org/api v0.153.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect diff --git a/go.sum b/go.sum index e408697..9d41dbd 100644 --- a/go.sum +++ b/go.sum @@ -392,6 +392,8 @@ github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= @@ -422,6 +424,8 @@ github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/getsops/gopgagent v0.0.0-20170926210634-4d7ea76ff71a h1:qc+7TV35Pq/FlgqECyS5ywq8cSN9j1fwZg6uyZ7G0B0= github.com/getsops/gopgagent v0.0.0-20170926210634-4d7ea76ff71a/go.mod h1:awFzISqLJoZLm+i9QQ4SgMNHDqljH6jWV0B36V5MrUM= github.com/getsops/sops/v3 v3.8.1 h1:3A6KZEHAolxfXtlgRjncCotTGRiNaQFhSDOB2CUCojY= @@ -773,6 +777,8 @@ github.com/likexian/simplejson-go v0.0.0-20190502021454-d8787b4bfa0b/go.mod h1:3 github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lusis/go-artifactory v0.0.0-20160115162124-7e4ce345df82/go.mod h1:y54tfGmO3NKssKveTEFFzH8C/akrSOy/iW9qEAUDV84= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/masterzen/simplexml v0.0.0-20160608183007-4572e39b1ab9/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc= github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc= @@ -883,6 +889,8 @@ github.com/owenrumney/go-sarif v1.1.1 h1:QNObu6YX1igyFKhdzd7vgzmw7XsWN3/6NMGuDzB github.com/owenrumney/go-sarif v1.1.1/go.mod h1:dNDiPlF04ESR/6fHlPyq7gHKmrM0sHUvAGjsoh8ZH0U= github.com/packer-community/winrmcp v0.0.0-20180921211025-c76d91c1e7db/go.mod h1:f6Izs6JvFTdnRbziASagjZ2vmf55NSIkC/weStxCHqk= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pkg/browser v0.0.0-20201207095918-0426ae3fba23/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= @@ -892,6 +900,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.1/go.mod h1:6gapUrK/U1TAN7ciCoNRIdVC5sbdBTUh1DKN0g6uH7E= github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= @@ -928,6 +938,10 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f h1:MvTmaQdww/z0Q4wrYjDSCcZ78NoftLQyHBSLW/Cx79Y= github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= @@ -945,6 +959,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/sourcegraph/go-lsp v0.0.0-20200429204803-219e11d77f5d h1:afLbh+ltiygTOB37ymZVwKlJwWZn+86syPTbrrOAydY= github.com/sourcegraph/go-lsp v0.0.0-20200429204803-219e11d77f5d/go.mod h1:SULmZY7YNBsvNiQbrb/BEDdEJ84TGnfyUQxaHt8t8rY= github.com/sourcegraph/jsonrpc2 v0.2.0 h1:KjN/dC4fP6aN9030MZCJs9WQbTOjWHhrtKVpzzSrr/U= @@ -955,6 +971,8 @@ github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -963,6 +981,8 @@ github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -983,6 +1003,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tencentcloud/tencentcloud-sdk-go v3.0.82+incompatible/go.mod h1:0PfYow01SHPMhKY31xa+EFz2RStxIqj6JFAJS+IkCi4= github.com/tencentyun/cos-go-sdk-v5 v0.0.0-20190808065407-f07404cefc8c/go.mod h1:wk2XFUg6egk4tSDNZtXeKfe2G6690UVyt163PuUxBZk= github.com/terraform-linters/tflint v0.47.0 h1:RTN4b4E+O//rUgWDgQtEJ+DN6893aUSjrsL8c7wgPag= @@ -1087,7 +1109,11 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1517,6 +1543,8 @@ google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= google.golang.org/api v0.152.0 h1:t0r1vPnfMc260S2Ci+en7kfCZaLOPs5KI0sVV/6jZrY= google.golang.org/api v0.152.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= +google.golang.org/api v0.153.0 h1:N1AwGhielyKFaUqH07/ZSIQR3uNPcV7NVw0vj+j4iR4= +google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= diff --git a/internal/pkg/functions/status.go b/internal/pkg/functions/status.go index da18061..05d3007 100644 --- a/internal/pkg/functions/status.go +++ b/internal/pkg/functions/status.go @@ -1,19 +1,13 @@ package functions import ( - "context" githubfoundations "gh_foundations/internal/pkg/types/github_foundations" "gh_foundations/internal/pkg/types/status" + "gh_foundations/internal/pkg/types/terragrunt" "log" "os" - "path" "path/filepath" "strings" - - "github.com/gruntwork-io/terragrunt/config" - "github.com/gruntwork-io/terragrunt/config/hclparse" - "github.com/gruntwork-io/terragrunt/options" - "github.com/mitchellh/mapstructure" ) // Given a set of HCL file, find the org name @@ -29,36 +23,6 @@ func findOrgsFromFilenames(hclFiles []string) map[string][]string { return names } -// Given a repository struct returned by the HCL parser, return a githubfoundations.RepositoryInput -func GetRepositoryInput(repo status.Repository) githubfoundations.RepositoryInput { - return githubfoundations.RepositoryInput{ - Name: repo.Name, - AdvanceSecurity: repo.AdvanceSecurity, - AllowAutoMerge: repo.AllowAutoMerge, - DefaultBranch: repo.DefaultBranch, - DeleteHeadBranchOnMerge: repo.DeleteHeadBranchOnMerge, - DependabotSecurityUpdates: repo.DependabotSecurityUpdates, - Description: repo.Description, - HasVulnerabilityAlerts: repo.HasVulnerabilityAlerts, - Homepage: repo.Homepage, - ProtectedBranches: repo.ProtectedBranches, - RequiresWebCommitSignOff: repo.RequiresWebCommitSignOff, - Topics: repo.Topics, - } -} - -// Setup the terragrunt options with defaults -func getOptions() *options.TerragruntOptions { - tgOptions := options.NewTerragruntOptions() - tgOptions.Env = map[string]string{ - "GCP_SECRET_MANAGER_PROJECT": os.Getenv("GCP_SECRET_MANAGER_PROJECT"), - "GCP_TF_STATE_BUCKET_PROJECT": os.Getenv("GCP_SECRET_MANAGER_PROJECT"), - "GCP_TF_STATE_BUCKET_NAME": os.Getenv("GCP_TF_STATE_BUCKET_NAME"), - "GCP_TF_STATE_BUCKET_LOCATION": os.Getenv("GCP_TF_STATE_BUCKET_LOCATION"), - } - return tgOptions -} - // List all of the organizations managed by the tool func FindManagedOrgs(orgsDir string) ([]string, error) { // Get the list of the dir names in the directory @@ -76,11 +40,25 @@ func FindManagedOrgs(orgsDir string) ([]string, error) { return orgs, nil } + // List all of the organizations + repository configs managed by the tool -func findOrgFiles(rootDir string, options *options.TerragruntOptions) (map[string][]string, error) { +func findOrgFiles(rootDir string) (map[string][]string, error) { // Get the list of HCL files in the root directory - hclFiles, err := config.FindConfigFilesInPath(rootDir, options) + // hclFiles, err := config.FindConfigFilesInPath(rootDir, options) + var hclFiles []string + err := filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + // if the file ends with "repositories/terragrunt.hcl", then it is a repository fil + if strings.HasSuffix(path, "repositories/terragrunt.hcl") { + hclFiles = append(hclFiles, path) + } + + return nil + }) if err != nil { return nil, err } @@ -89,11 +67,10 @@ func findOrgFiles(rootDir string, options *options.TerragruntOptions) (map[strin return orgFiles, nil } -// List all of the repositories managed by the tool -func FindManagedRepos(ctx context.Context, reposDir string) (status.OrgSet, error) { - options := getOptions() - orgFiles, err := findOrgFiles(reposDir, options) +// List all of the repositories managed by the tool +func FindManagedRepos(reposDir string) (status.OrgSet, error) { + orgFiles, err := findOrgFiles(reposDir) if err != nil { log.Fatalf("Error in findOrgFiles: %s", err) return status.OrgSet{}, err @@ -132,32 +109,16 @@ func FindManagedRepos(ctx context.Context, reposDir string) (status.OrgSet, erro parts := strings.Split(file, "/") project := parts[len(parts)-4] - // Parse the HCL file - options.TerragruntConfigPath = file - options.WorkingDir = path.Dir(file) - parseCtx := config.NewParsingContext(ctx, options) - parser := hclparse.NewParser() - parsedHCL, err := parser.ParseFromFile(file) - - if err != nil { - log.Fatalf(`Error in hclparse.NewParser().ParseFromFile: %s`, err) - return orgSet, err + hclFile := terragrunt.HCLFile { + Path: file, } - tfConfig, err := config.ParseConfig(parseCtx, parsedHCL, nil) + inputs, err := hclFile.GetInputsFromFile() if err != nil { - log.Fatalf(`Error in config.ParseConfig: %s`, err) + log.Fatalf(`Error in getInputsFromFile: %s`, err) return orgSet, err } - var inputs status.Inputs - err = mapstructure.Decode(tfConfig.Inputs, &inputs) - if err != nil { - log.Fatalf(`Error in mapstructure.Decode: %s`, err) - return orgSet, err - } - - log.Printf("Repository Set has %d private repositories and %d public repositories", len(inputs.PrivateRepositories), len(inputs.PublicRepositories)) var repoSet githubfoundations.RepositorySetInput for key, value := range inputs.DefaultRepositoryTeamPermissions { @@ -167,13 +128,13 @@ func FindManagedRepos(ctx context.Context, reposDir string) (status.OrgSet, erro for name, repo := range inputs.PrivateRepositories { // Coerce the repo into a githubfoundations.RepositoryInput - repoInput := GetRepositoryInput(repo) + repoInput := repo.GetRepositoryInput() repoInput.Name = name repoSet.PrivateRepositories = append(repoSet.PrivateRepositories, &repoInput) } for name, repo := range inputs.PublicRepositories { // Coerce the repo into a githubfoundations.RepositoryInput - repoInput := GetRepositoryInput(repo) + repoInput := repo.GetRepositoryInput() repoInput.Name = name repoSet.PublicRepositories = append(repoSet.PublicRepositories, &repoInput) } diff --git a/internal/pkg/types/status/org_repos.go b/internal/pkg/types/status/org_repos.go index 711b7b4..f5b3ba8 100644 --- a/internal/pkg/types/status/org_repos.go +++ b/internal/pkg/types/status/org_repos.go @@ -36,7 +36,7 @@ type OrgSet struct { OrgProjectSets map[string]OrgProjectSet } -// Return only the names of the repositories managed by the tool +// Return only the names of the repositories managed by the tool // that have GHAS enabled func (org OrgSet) WithGHASEnabled() OrgSet { reposWithGHAS := OrgSet{} @@ -62,4 +62,23 @@ func (org OrgSet) WithGHASEnabled() OrgSet { } } return reposWithGHAS -} \ No newline at end of file +} + + +// Given a repository struct returned by the HCL parser, return a githubfoundations.RepositoryInput +func (repo *Repository) GetRepositoryInput() githubfoundations.RepositoryInput { + return githubfoundations.RepositoryInput{ + Name: repo.Name, + AdvanceSecurity: repo.AdvanceSecurity, + AllowAutoMerge: repo.AllowAutoMerge, + DefaultBranch: repo.DefaultBranch, + DeleteHeadBranchOnMerge: repo.DeleteHeadBranchOnMerge, + DependabotSecurityUpdates: repo.DependabotSecurityUpdates, + Description: repo.Description, + HasVulnerabilityAlerts: repo.HasVulnerabilityAlerts, + Homepage: repo.Homepage, + ProtectedBranches: repo.ProtectedBranches, + RequiresWebCommitSignOff: repo.RequiresWebCommitSignOff, + Topics: repo.Topics, + } +} diff --git a/internal/pkg/types/terragrunt/terragrunt.go b/internal/pkg/types/terragrunt/terragrunt.go index 2fdf276..67a630e 100644 --- a/internal/pkg/types/terragrunt/terragrunt.go +++ b/internal/pkg/types/terragrunt/terragrunt.go @@ -4,13 +4,19 @@ import ( "bytes" "fmt" "gh_foundations/internal/pkg/types" + "gh_foundations/internal/pkg/types/status" "gh_foundations/internal/pkg/types/terraform_state" v1_2 "gh_foundations/internal/pkg/types/terraform_state/v1.2" "io" + "log" "os/exec" "path" + "regexp" + "strings" + "github.com/mitchellh/mapstructure" "github.com/spf13/afero" + "github.com/spf13/viper" "github.com/tidwall/gjson" ) @@ -37,6 +43,149 @@ type PlanFile struct { OutputFilePath string } +type HCLFile struct { + Path string +} + +func getRepository(repo map[string]interface{}) (status.Repository, error) { + var repository status.Repository + + err := mapstructure.Decode(repo, &repository) + if err != nil { + log.Fatalf("Error in getInputsFromFile mapstructure.Decode: %s", err) + return repository, err + } + + return repository, nil + +} + + +// Given a repository map, returned by Viper, return a map of status.Repository +func getRepositoryMap(repoList []map[string]interface{}) (map[string]status.Repository, error) { + repos := make(map[string]status.Repository) + + for name, r := range repoList[0] { + details := r.([]map[string]interface{}) + d := details[0] + repo, err := getRepository(d) + if err != nil { + log.Fatalf("Error in getRepositoryMap: %s", err) + return repos, err + } + repos[name] = repo + } + return repos, nil +} + +func replaceLocals(contents string) string { + // The locals are in the form of locals = { key = value } + // Then, they are referred to as local.key in the configuration + // This function replaces the locals with their values + + // Use regex to find the locals block + lre := regexp.MustCompile(`locals\s*{\n*((.*[^}])\n)+}`) + locals := lre.FindString(contents) + + if locals == "" { + log.Printf("locals not found") + return contents + } + + // Use regex to find the key-value pairs in the locals block + kvre := regexp.MustCompile(`(.*[^=])=(.*(?:(:?\n.*[^\]])*])*)`) + matches := kvre.FindAllStringSubmatch(locals, -1) + + // Replace the locals with their values + for _, match := range matches { + key := strings.Trim(match[1], " ") + value := strings.Trim(match[2], " ") + + contents = strings.ReplaceAll(contents, key, value) + + } + + return contents +} + +// Given an HCL file, return the inputs +func (h *HCLFile) GetInputsFromFile() (status.Inputs, error) { + + var inputs status.Inputs + + viper.SetConfigType("hcl") + viper.SetConfigFile(h.Path) + if err := viper.ReadInConfig(); err != nil { + if _, ok := err.(viper.ConfigFileNotFoundError); ok { + // Config file not found; + log.Fatalf(`GetInputsFromFile: config file not found: %s`, h.Path) + return inputs, err + } else if _, ok := err.(viper.ConfigParseError); ok { + // the viper library can't parse the "locals". Here's a workaround + // read in the file contents and replace the locals with their values + // then write the file to a temporary location and read it in + // again + + // read in the file contents + contents, err := afero.ReadFile(fs, h.Path) + if err != nil { + log.Fatalf(`GetInputsFromFile: unable to read config file: %s`, h.Path) + return inputs, err + } + // replace the locals with their values + contents = []byte(replaceLocals(string(contents))) + // write the file to a temporary location and read it in again + tempPath := "/tmp/" + path.Base(h.Path) + err = afero.WriteFile(fs, tempPath, contents, 0644) + if err != nil { + log.Fatalf(`GetInputsFromFile: unable to write config file: %s`, h.Path) + return inputs, err + } + viper.SetConfigFile(tempPath) + viper.ReadInConfig() + } else { + // Config file was found but another error was produced + log.Fatalf(`GetInputsFromFile: config file found but another error was produced: %s`, h.Path) + return inputs, err + } + } + + raw := viper.Get("inputs").([]map[string]interface{}) + for key, input := range raw[0] { + switch key { + case "private_repositories": + repoList := input.([]map[string]interface{}) + repos, err := getRepositoryMap(repoList) + if err != nil { + log.Fatalf("Error in getRepositoryMap: %s", err) + return inputs, err + } + inputs.PrivateRepositories = repos + case "public_repositories": + repoList := input.([]map[string]interface{}) + repos, err := getRepositoryMap(repoList) + if err != nil { + log.Fatalf("Error in getRepositoryMap: %s", err) + return inputs, err + } + inputs.PublicRepositories = repos + case "default_repository_team_permissions": + permissions := make(map[string]string) + inputArr := input.([]map[string]interface{}) + drtpsArr := inputArr[0] + for permission, value := range drtpsArr { + permissions[permission] = value.(string) + } + inputs.DefaultRepositoryTeamPermissions = permissions + default: + log.Fatalf("Unknown input: %s", key) + return inputs, nil + } + } + + return inputs, nil +} + func NewTerragruntPlanFile(name string, modulePath string, moduleDir string, outputFilePath string) (*PlanFile, error) { // If there is a file conflict with the output file, create a new file with a "copy_" prefix if _, err := fs.Stat(outputFilePath); err == nil { diff --git a/main.go b/main.go index ec64068..b3bccf4 100644 --- a/main.go +++ b/main.go @@ -6,15 +6,18 @@ package main import ( "gh_foundations/cmd" "log" + "os" ui "github.com/gizak/termui/v3" ) func main() { - if err := ui.Init(); err != nil { - log.Fatalf("failed to initialize termui: %v", err) + if os.Getenv("GITHUB_ACTIONS") != "true" { + if err := ui.Init(); err != nil { + log.Fatalf("failed to initialize termui: %v", err) + } + defer ui.Close() } - defer ui.Close() cmd.Execute() }