* INFRA-3755 | Saurabh | Adding new vertical and cluster details for NIAPL * INFRA-3755 | Saurabh | go fmt in file
310 lines
8.2 KiB
Go
310 lines
8.2 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
|
|
"github.com/a8m/envsubst"
|
|
"github.com/asaskevich/govalidator"
|
|
"github.com/caarlos0/env/v6"
|
|
"github.com/urfave/cli/v2"
|
|
)
|
|
|
|
func init() {
|
|
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
|
}
|
|
|
|
func parseManifest(manifestPath string, tfActions *Actions) (*Manifest, error) {
|
|
log.Printf("Parsing Manifest")
|
|
rawManifest, err := ioutil.ReadFile(manifestPath)
|
|
if err != nil {
|
|
log.Fatalf("\nErr: %v", err)
|
|
return nil, err
|
|
}
|
|
|
|
//Do Environment substitution
|
|
manifestWithEnvironment, err := envsubst.Bytes(rawManifest)
|
|
if err != nil {
|
|
log.Fatalf("\nErr: %v", err)
|
|
return nil, err
|
|
}
|
|
|
|
var manifest Manifest
|
|
err = json.Unmarshal(manifestWithEnvironment, &manifest)
|
|
if err != nil {
|
|
log.Fatalf("\nErr: %v", err)
|
|
return nil, err
|
|
}
|
|
|
|
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.Actions = tfActions
|
|
if manifest.ExtraResources.Environment == "" {
|
|
manifest.ExtraResources.Environment = manifest.Environment
|
|
}
|
|
|
|
if manifest.InfraVertical == "" {
|
|
manifest.InfraVertical = DefaultInfraVertical
|
|
}
|
|
|
|
if manifest.Team.Owner == "" {
|
|
manifest.Team.Owner = ownerMap[manifest.InfraVertical]
|
|
}
|
|
|
|
if manifest.Team.Product == "" {
|
|
manifest.Team.Product = productMap[manifest.InfraVertical]
|
|
}
|
|
|
|
if manifest.ExtraResources.Workspace == "" {
|
|
var workspace string
|
|
if manifest.Cluster != "" {
|
|
workspace = manifest.Cluster
|
|
log.Printf("Got workspace from manifest.cluster: %v", workspace)
|
|
} else if manifest.Deployment.Cluster != "" {
|
|
workspace = manifest.Deployment.Cluster
|
|
log.Printf("Got workspace from manifest.deployment.cluster: %v", workspace)
|
|
} else {
|
|
workspace = defaultWorkspaceMap[manifest.InfraVertical][manifest.ExtraResources.Environment]
|
|
log.Printf("Got workspace from workspace map: %v", workspace)
|
|
}
|
|
manifest.ExtraResources.Workspace = workspace
|
|
}
|
|
|
|
if globalTagsMapVar, ok := globalTagsMap[manifest.ExtraResources.Environment]; ok {
|
|
manifest.ExtraResources.GlobalTags = &GlobalTags{}
|
|
marshal, err := json.Marshal(globalTagsMapVar)
|
|
if err != nil {
|
|
log.Fatalf("\nErr: %v", err)
|
|
return nil, err
|
|
}
|
|
err = json.Unmarshal(marshal, &manifest.ExtraResources.GlobalTags)
|
|
if err != nil {
|
|
log.Fatalf("\nErr: %v", err)
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
manifest.NameSuffix = DeploymentNameSuffix
|
|
|
|
stateStoreBucketName := DefaultStateStorageBucket
|
|
if _, ok := storageBackendBucketMap[manifest.InfraVertical]; ok {
|
|
if _, ok = storageBackendBucketMap[manifest.InfraVertical][manifest.ExtraResources.Environment]; ok {
|
|
stateStoreBucketName = storageBackendBucketMap[manifest.InfraVertical][manifest.ExtraResources.Environment]
|
|
}
|
|
}
|
|
manifest.StateStoreBackend = &StateStoreBackend{
|
|
BucketName: stateStoreBucketName,
|
|
AWSProfile: storageBackendAWSProfileMap[stateStoreBucketName],
|
|
}
|
|
|
|
return &manifest, nil
|
|
}
|
|
|
|
func setActions(templateOnly bool, plan bool, destroy bool, runAdditionalScripts bool) (*Actions, error) {
|
|
log.Printf("Setting actions. \nTemplateOnly: %v, \nPlan: %v, \nDestroy: %v, \n"+
|
|
"RunAdditionalScripts: %v\n", templateOnly, plan, destroy, runAdditionalScripts)
|
|
var actions Actions
|
|
actions.TemplateOnly = templateOnly
|
|
actions.Plan = plan
|
|
actions.Destroy = destroy
|
|
actions.RunAdditionalScripts = runAdditionalScripts
|
|
if !plan {
|
|
actions.Apply = true
|
|
}
|
|
return &actions, nil
|
|
}
|
|
|
|
func executeCommand(c *cli.Context, resourceName string, resourceDir string) error {
|
|
tfActions, err := setActions(c.Bool("template-only"), c.Bool("plan"), c.Bool("destroy"), false)
|
|
if err != nil {
|
|
log.Fatalf("\nErr: %v", err)
|
|
return err
|
|
}
|
|
manifest, err := parseManifest(c.String("manifest"), tfActions)
|
|
if err != nil {
|
|
log.Fatalf("\nErr: %v", err)
|
|
return err
|
|
}
|
|
err = provisionResource(resourceName, resourceDir, manifest)
|
|
|
|
if err != nil {
|
|
log.Fatalf("\nErr: %v", err)
|
|
return err
|
|
}
|
|
if manifest.Actions.Apply && !manifest.Actions.TemplateOnly {
|
|
sendResourceDeploymentStatus(manifest)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func main() {
|
|
app := &cli.App{
|
|
Name: "infra-provisioner",
|
|
Version: "2.0.0",
|
|
|
|
//Common flags for all subcommands
|
|
Flags: []cli.Flag{
|
|
&cli.StringFlag{
|
|
Name: "manifest",
|
|
Usage: "Path of the manifest file",
|
|
Aliases: []string{"m"},
|
|
Required: true,
|
|
},
|
|
&cli.BoolFlag{
|
|
Name: "template-only",
|
|
Usage: "Provisions just the template for given resource",
|
|
Aliases: []string{"t"},
|
|
},
|
|
&cli.BoolFlag{
|
|
Name: "run-additional-scripts",
|
|
Usage: "Runs configured scripts before and after terraform apply",
|
|
Aliases: []string{"s"},
|
|
},
|
|
&cli.BoolFlag{
|
|
Name: "plan",
|
|
Usage: "Run plan for the given resources",
|
|
Aliases: []string{"p"},
|
|
},
|
|
&cli.BoolFlag{
|
|
Name: "destroy",
|
|
Usage: "Run destroy for the given terraform resources",
|
|
Aliases: []string{"d"},
|
|
},
|
|
},
|
|
|
|
Commands: []*cli.Command{
|
|
{
|
|
Name: "database",
|
|
Usage: "Provision rds database instance",
|
|
Action: func(c *cli.Context) error {
|
|
log.Printf("Provisioning the rds database resource specified in the manifest.")
|
|
err := executeCommand(c, RESOURCE_RDS, DIR_RDS_TF)
|
|
if err != nil {
|
|
log.Fatalf("\nErr: %v", err)
|
|
return err
|
|
}
|
|
return nil
|
|
},
|
|
},
|
|
{
|
|
Name: "redis",
|
|
Usage: "Provision elastic cache instance",
|
|
Action: func(c *cli.Context) error {
|
|
log.Printf("Provisioning the redis resource specified in the manifest.")
|
|
err := executeCommand(c, RESOURCE_ELASTIC_CACHE, DIR_ELASTIC_CACHE_TF)
|
|
if err != nil {
|
|
log.Fatalf("\nErr: %v", err)
|
|
return err
|
|
}
|
|
return nil
|
|
},
|
|
},
|
|
{
|
|
Name: "docdb",
|
|
Usage: "Provision document db instance",
|
|
Action: func(c *cli.Context) error {
|
|
log.Printf("Provisioning the document db resource specified in the manifest.")
|
|
err := executeCommand(c, RESOURCE_DOCDB, DIR_DOCDB_TF)
|
|
if err != nil {
|
|
log.Fatalf("\nErr: %v", err)
|
|
return err
|
|
}
|
|
return nil
|
|
},
|
|
},
|
|
{
|
|
Name: "iam-roles",
|
|
Usage: "Provision iam service roles",
|
|
Action: func(c *cli.Context) error {
|
|
log.Printf("Provisioning the iam roles specified in the manifest.")
|
|
err := executeCommand(c, RESOURCE_AWS_ROLES, DIR_AWS_ROLES_TF)
|
|
if err != nil {
|
|
log.Fatalf("\nErr: %v", err)
|
|
return err
|
|
}
|
|
return nil
|
|
},
|
|
},
|
|
{
|
|
Name: "s3-buckets",
|
|
Usage: "Provision s3 buckets",
|
|
Action: func(c *cli.Context) error {
|
|
log.Printf("Provisioning the s3 buckets specified in the manifest.")
|
|
err := executeCommand(c, RESOURCE_S3_BUCKETS, DIR_S3_BUCKETS_TF)
|
|
if err != nil {
|
|
log.Fatalf("\nErr: %v", err)
|
|
return err
|
|
}
|
|
return nil
|
|
},
|
|
},
|
|
{
|
|
Name: "dynamo-db",
|
|
Usage: "Provision dynamo db tables",
|
|
Action: func(c *cli.Context) error {
|
|
log.Printf("Provisioning the dynamo db tables specified in the manifest.")
|
|
err := executeCommand(c, RESOURCE_DYNAMODB, DIR_DYNAMODB_TF)
|
|
if err != nil {
|
|
log.Fatalf("\nErr: %v", err)
|
|
return err
|
|
}
|
|
return nil
|
|
},
|
|
},
|
|
{
|
|
Name: "aurora-db",
|
|
Usage: "Provision aurora database instance/cluster",
|
|
Action: func(c *cli.Context) error {
|
|
log.Printf("Provisioning the aurora database resource specified in the manifest.")
|
|
err := executeCommand(c, RESOURCE_AURORADB, DIR_AURORADB_TF)
|
|
if err != nil {
|
|
log.Fatalf("\nErr: %v", err)
|
|
return err
|
|
}
|
|
return nil
|
|
},
|
|
},
|
|
{
|
|
Name: "all",
|
|
Usage: "Provision all resources",
|
|
Action: func(c *cli.Context) error {
|
|
log.Printf("Provisioning all resources specified in the manifest.")
|
|
tfActions, err := setActions(c.Bool("template-only"), c.Bool("plan"), c.Bool("destroy"), false)
|
|
if err != nil {
|
|
log.Fatalf("\nErr: %v", err)
|
|
return err
|
|
}
|
|
manifest, err := parseManifest(c.String("manifest"), tfActions)
|
|
if err != nil {
|
|
log.Fatalf("\nErr: %v", err)
|
|
return err
|
|
}
|
|
err = provisionAllResource(manifest)
|
|
if err != nil {
|
|
log.Fatalf("\nErr: %v", err)
|
|
return err
|
|
}
|
|
return nil
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
err := app.Run(os.Args)
|
|
if err != nil {
|
|
log.Fatalf("\nErr: %v", err)
|
|
}
|
|
}
|