diff --git a/README.md b/README.md index eb5ebf4..e29f9b4 100644 --- a/README.md +++ b/README.md @@ -10,10 +10,6 @@ Simply explained, its a thin wrapper over terraform to hide the complexities lik ##### Check templates generated `infra-provisioner --manifest sample_infra_manifest.json --template-only database` -or - -`infra-provisioner -m sample_infra_manifest.json -t database` - ##### Run plan for resources `infra-provisioner --manifest sample_infra_manifest.json --plan database` @@ -27,12 +23,12 @@ or - Add templates to your resource in templates folder - Make changes to cli to support new resource - Package templates with `go-bindata` -- Dry run with `go run *.go --manifest manifest.json --template-only resourceName` +- Dry run with `go run *.go --manifest sample_infra_manifest.json --template-only resourceName` ##### Package templates ``` go get github.com/shuLhan/go-bindata/cmd/go-bindata -go-bindata templates/... +go-bindata -o bindata/ templates/... ``` ## Caveats diff --git a/bindata.go b/bindata/bindata.go similarity index 99% rename from bindata.go rename to bindata/bindata.go index 516493c..2971df1 100644 --- a/bindata.go +++ b/bindata/bindata.go @@ -7,7 +7,7 @@ // templates/rds-tf/deploy.sh // templates/rds-tf/main.tf -package main +package bindata import ( diff --git a/go.mod b/go.mod index 03e7bf2..daabd79 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,8 @@ go 1.13 require ( github.com/Masterminds/sprig/v3 v3.0.2 github.com/a8m/envsubst v1.1.0 - github.com/caarlos0/env/v6 v6.2.1 // indirect + github.com/asaskevich/govalidator v0.0.0-20200108192510-8ed6f3c986a9 // Do not upgrade this further as this library is broken on latest commit + github.com/caarlos0/env/v6 v6.2.1 github.com/huandu/xstrings v1.2.1 // indirect github.com/imdario/mergo v0.3.8 // indirect github.com/urfave/cli/v2 v2.1.1 diff --git a/go.sum b/go.sum index 5664840..b9ffdfa 100644 --- a/go.sum +++ b/go.sum @@ -7,7 +7,8 @@ github.com/Masterminds/sprig/v3 v3.0.2 h1:wz22D0CiSctrliXiI9ZO3HoNApweeRGftyDN+B github.com/Masterminds/sprig/v3 v3.0.2/go.mod h1:oesJ8kPONMONaZgtiHNzUShJbksypC5kWczhZAf6+aU= github.com/a8m/envsubst v1.1.0 h1:d+14SVq1lbI+JuxhEqYduWofZ0/qQHatwm3TBzvdzaE= github.com/a8m/envsubst v1.1.0/go.mod h1:91m2Q6AZE0w4WD/laQam2MtWq6FxJVm7UqcB30DeYxw= -github.com/caarlos0/env v3.5.0+incompatible h1:Yy0UN8o9Wtr/jGHZDpCBLpNrzcFLLM2yixi/rBrKyJs= +github.com/asaskevich/govalidator v0.0.0-20200108192510-8ed6f3c986a9 h1:CuxdFKTqyemGnEVfzbbJC+PWwO/Rrp5vo6c5ZNtJHgo= +github.com/asaskevich/govalidator v0.0.0-20200108192510-8ed6f3c986a9/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= github.com/caarlos0/env/v6 v6.2.1 h1:/bFpX1dg4TNioJjg7mrQaSrBoQvRfLUHNfXivdFbbEo= github.com/caarlos0/env/v6 v6.2.1/go.mod h1:3LpmfcAYCG6gCiSgDLaFR5Km1FRpPwFvBbRcjHar6Sw= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= @@ -40,6 +41,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k= github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= diff --git a/main.go b/main.go index 1172ae2..270ce36 100644 --- a/main.go +++ b/main.go @@ -2,13 +2,13 @@ package main import ( "encoding/json" + "github.com/a8m/envsubst" + "github.com/asaskevich/govalidator" + "github.com/caarlos0/env/v6" + "github.com/urfave/cli/v2" "io/ioutil" "log" "os" - - "github.com/a8m/envsubst" - "github.com/caarlos0/env/v6" - "github.com/urfave/cli/v2" ) func init() { @@ -36,19 +36,28 @@ func parseManifest(manifestPath string) (*Manifest, error) { return nil, err } - err = env.Parse(&manifest.ExtraResources.Database) + err = env.Parse(&manifest) if err != nil { log.Fatalf("\nErr: %v", err) return nil, err } + _, err = govalidator.ValidateStruct(manifest) + if err != nil { + log.Fatalf("\nErr: %v", err.Error()) + return nil, err + } + + manifest.ExtraResources.Workspace = workspaceMap[manifest.ExtraResources.Environment] - manifest.Deployment.NameSuffix = DEPLOYMENT_NAME_SUFFIX + manifest.Deployment.NameSuffix = DeploymentNameSuffix //Fix: Required for templating storage backend var stateStoreBucketName = storageBackendBucketMap[manifest.ExtraResources.Environment] - manifest.StateStoreBackend.BucketName = stateStoreBucketName - manifest.StateStoreBackend.AWSProfile = storageBackendAWSProfileMap[stateStoreBucketName] + manifest.StateStoreBackend = &StateStoreBackend{ + BucketName: stateStoreBucketName, + AWSProfile: storageBackendAWSProfileMap[stateStoreBucketName], + } return &manifest, nil } diff --git a/resource.go b/resource.go index 7c58def..6d65776 100644 --- a/resource.go +++ b/resource.go @@ -1,6 +1,7 @@ package main import ( + "github.cmd.navi-tech.in/navi-infra/infra-provisioner/bindata" "log" "os" "os/exec" @@ -10,8 +11,8 @@ import ( "github.com/Masterminds/sprig/v3" ) -const TEMPLATES_DIR = "templates" -const INIT_SCRIPT = "./deploy.sh" +const TemplatesDir = "templates" +const InitScript = "./deploy.sh" func provisionResource(resourceName, resourceDir string, manifest *Manifest, templateOnly, plan bool) error { err := templateResourceTf(resourceName, resourceDir, manifest) @@ -34,13 +35,13 @@ func provisionResource(resourceName, resourceDir string, manifest *Manifest, tem func templateResourceTf(templateName, resourceDir string, manifest *Manifest) error { log.Printf("Creating templates for %s in %s", templateName, resourceDir) - tfFiles, err := AssetDir(strings.Join([]string{TEMPLATES_DIR, resourceDir}, "/")) + tfFiles, err := bindata.AssetDir(strings.Join([]string{TemplatesDir, resourceDir}, "/")) if err != nil { return err } for _, tfFile := range tfFiles { - tfBytes := MustAsset(strings.Join([]string{TEMPLATES_DIR, resourceDir, tfFile}, "/")) + tfBytes := bindata.MustAsset(strings.Join([]string{TemplatesDir, resourceDir, tfFile}, "/")) t := template.Must(template.New(templateName).Funcs(sprig.TxtFuncMap()).Parse(string(tfBytes))) tfOut, err := createFile(resourceDir, tfFile) @@ -63,10 +64,10 @@ func templateResourceTf(templateName, resourceDir string, manifest *Manifest) er func executeResourceTf(resourceDir string, plan bool) error { var cmd *exec.Cmd if plan { - cmd = exec.Command(INIT_SCRIPT, "plan") + cmd = exec.Command(InitScript, "plan") } else { log.Printf("Running terraform for %s", resourceDir) - cmd = exec.Command(INIT_SCRIPT) + cmd = exec.Command(InitScript) } cmd.Dir = resourceDir cmd.Stdout = os.Stdout diff --git a/sample_infra_manifest.json b/sample_infra_manifest.json index de0ab97..4e06df2 100644 --- a/sample_infra_manifest.json +++ b/sample_infra_manifest.json @@ -20,10 +20,10 @@ }, { "actions": ["s3:GetObject","s3:PutObject"], - "resource": "arn:aws:s3:::arn:aws:s3:::test-bucket-to-be-deleted/*" + "resource": "*" }, { - "resource": "*", + "resource": "arn:aws:s3:::arn:aws:s3:::test-bucket-to-be-deleted/*", "actions":["sns:Publish", "sns:SetSMSAttributes"] } ] diff --git a/types.go b/types.go index 5069de3..3b1ddb1 100644 --- a/types.go +++ b/types.go @@ -1,24 +1,24 @@ package main -const DEPLOYMENT_NAME_SUFFIX = "navi-service" +const DeploymentNameSuffix = "navi-service" type Deployment struct { - Name string `json:"name"` + Name string `json:"name" valid:"required"` NameSuffix string } type Manifest struct { - ExtraResources ExtraResources `json:"extraResources"` - Team Team `json:"team"` - Deployment Deployment `json:"deployment"` - StateStoreBackend StateStoreBackend + ExtraResources *ExtraResources `json:"extraResources"` + Team *Team `json:"team"` + Deployment *Deployment `json:"deployment" valid:"required"` + StateStoreBackend *StateStoreBackend } type ExtraResources struct { Environment string `json:"environment"` Workspace string - Database Database `json:"database"` - ServiceRole ServiceRole `json:"aws_access"` + Database *Database `json:"database"` + ServiceRole *ServiceRole `json:"aws_access"` S3Buckets []S3Bucket `json:"s3_buckets"` } @@ -27,11 +27,11 @@ type Database struct { AwsInstanceClass string `json:"awsInstanceClass"` PsqlFamily string `json:"psqlFamily"` PsqlEngineVersion string `json:"psqlEngineVersion"` - User string `json:"user"` - Password string `json:"password"` + User string `json:"user" valid:"required"` + Password string `json:"password" valid:"required"` SizeInGb int `json:"sizeInGb"` DbNames []string `json:"dbNames"` - InstanceName string `json:"instanceName"` + InstanceName string `json:"instanceName" valid:"required"` BackupDisabled bool `json:"backupDisabled"` MultiAZDisabled bool `json:"multiAZDisabled"` DbExtensions []string `json:"dbExtensions"` @@ -48,7 +48,7 @@ type Team struct { type Policies struct { Actions []string `json:"actions"` - Resource string `json:"resource"` + Resource string `json:"resource" valid:"required,matches((^arn.*)|(^\\*$))~Policy resource must be an aws arn or *"` } type ServiceRole struct { @@ -61,13 +61,13 @@ type StateStoreBackend struct { } type S3Bucket struct { - BucketName string `json:"anonymizedBucketName"` - BucketTag string `json:"bucketTag"` - LifecycleRules []LifecycleRule `json:"lifecycleRules"` + BucketName string `json:"anonymizedBucketName" valid:"required"` + BucketTag string `json:"bucketTag" valid:"required"` + LifecycleRules []LifecycleRule `json:"lifecycleRules" valid:"required"` } type LifecycleRule struct { - ObjectExpiration ObjectExpiration `json:"expiration"` + ObjectExpiration *ObjectExpiration `json:"expiration"` } type ObjectExpiration struct {