[ch11782] | Anoop | Add validations for components (#20)

* [ch11782] | Anoop | Add validations for components

* [ch11782] | Anoop | Allow database & servicerole structure to be null

* [ch11782] | Anoop | Add required validation for s3 fields
This commit is contained in:
Anoop Narang
2020-05-27 13:51:41 +05:30
committed by GitHub Enterprise
parent 865dfc8233
commit fdca9cc060
8 changed files with 50 additions and 41 deletions

View File

@@ -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

View File

@@ -7,7 +7,7 @@
// templates/rds-tf/deploy.sh
// templates/rds-tf/main.tf
package main
package bindata
import (

3
go.mod
View File

@@ -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

4
go.sum
View File

@@ -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=

25
main.go
View File

@@ -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
}

View File

@@ -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

View File

@@ -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"]
}
]

View File

@@ -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 {