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) (*Manifest, error) { 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 } if manifest.ExtraResources.Environment == "" { manifest.ExtraResources.Environment = manifest.Environment } if manifest.ExtraResources.Workspace == "" { manifest.ExtraResources.Workspace = workspaceMap[manifest.ExtraResources.Environment] } if manifest.Deployment == nil { manifest.Deployment = &Deployment{} } manifest.Deployment.NameSuffix = DeploymentNameSuffix //Fix: Required for templating storage backend var stateStoreBucketName = storageBackendBucketMap[manifest.ExtraResources.Environment] manifest.StateStoreBackend = &StateStoreBackend{ BucketName: stateStoreBucketName, AWSProfile: storageBackendAWSProfileMap[stateStoreBucketName], } return &manifest, nil } func main() { app := &cli.App{ Name: "infra-provisioner", Version: "0.0.1", //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: "plan", Usage: "Run plan for the given resources", Aliases: []string{"p"}, }, }, Commands: []*cli.Command{ { Name: "database", Usage: "Provision database instance", Action: func(c *cli.Context) error { manifest, err := parseManifest(c.String("manifest")) if err != nil { log.Fatalf("\nErr: %v", err) return err } err = provisionResource("rds", "rds-tf", manifest, c.Bool("template-only"), c.Bool("plan")) 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 { manifest, err := parseManifest(c.String("manifest")) if err != nil { log.Fatalf("\nErr: %v", err) return err } err = provisionResource("roles", "aws-roles-tf", manifest, c.Bool("template-only"), c.Bool("plan")) 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 { manifest, err := parseManifest(c.String("manifest")) if err != nil { log.Fatalf("\nErr: %v", err) return err } err = provisionResource("s3", "aws-s3-bucket-tf", manifest, c.Bool("template-only"), c.Bool("plan")) if err != nil { log.Fatalf("\nErr: %v", err) return err } return nil }, }, }, } app.Run(os.Args) }