package devops import ( "strings" "github.com/aws/aws-sdk-go/service/cloudwatchlogs" "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ecr" "github.com/aws/aws-sdk-go/service/ecs" "github.com/aws/aws-sdk-go/service/elasticache" "github.com/aws/aws-sdk-go/service/elbv2" "github.com/aws/aws-sdk-go/service/iam" "github.com/aws/aws-sdk-go/service/rds" "github.com/aws/aws-sdk-go/service/s3" "github.com/aws/aws-sdk-go/service/servicediscovery" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" "github.com/iancoleman/strcase" "github.com/urfave/cli" ) // ServiceDeployFlags defines the flags used for executing a service deployment. type ServiceDeployFlags struct { // Required flags. ServiceName string `validate:"required" example:"web-api"` Env string `validate:"oneof=dev stage prod" example:"dev"` // Optional flags. EnableHTTPS bool `validate:"omitempty" example:"false"` ServiceDomainName string `validate:"omitempty" example:"example-project.com"` ServiceDomainNameAliases cli.StringSlice `validate:"omitempty" example:"subdomain.example-project.com"` S3BucketPrivateName string `validate:"omitempty" example:"saas-example-project-private"` S3BucketPublicName string `validate:"omitempty" example:"saas-example-project-public"` ProjectRoot string `validate:"omitempty" example:"."` ProjectName string ` validate:"omitempty" example:"example-project"` DockerFile string `validate:"omitempty" example:"./cmd/web-api/Dockerfile"` EnableLambdaVPC bool `validate:"omitempty" example:"false"` EnableEcsElb bool `validate:"omitempty" example:"false"` NoBuild bool `validate:"omitempty" example:"false"` NoDeploy bool `validate:"omitempty" example:"false"` NoCache bool `validate:"omitempty" example:"false"` NoPush bool `validate:"omitempty" example:"false"` RecreateService bool `validate:"omitempty" example:"false"` } // serviceDeployRequest defines the details needed to execute a service deployment. type serviceDeployRequest struct { ServiceName string `validate:"required"` ServiceDir string `validate:"required"` Env string `validate:"oneof=dev stage prod"` ProjectRoot string `validate:"required"` ProjectName string `validate:"required"` DockerFile string `validate:"required"` GoModFile string `validate:"required"` GoModName string `validate:"required"` EnableHTTPS bool `validate:"omitempty"` ServiceDomainName string `validate:"omitempty,required_with=EnableHTTPS,fqdn"` ServiceDomainNameAliases []string `validate:"omitempty,dive,fqdn"` AwsCreds awsCredentials `validate:"required,dive,required"` EcrRepositoryName string `validate:"required"` EcrRepository *ecr.CreateRepositoryInput EcrRepositoryMaxImages int `validate:"omitempty"` EcsClusterName string `validate:"required"` EcsCluster *ecs.CreateClusterInput EcsServiceName string `validate:"required"` EcsServiceDesiredCount int64 `validate:"required"` EcsServiceMinimumHealthyPercent *int64 `validate:"omitempty"` EcsServiceMaximumPercent *int64 `validate:"omitempty"` EscServiceHealthCheckGracePeriodSeconds *int64 `validate:"omitempty"` EcsExecutionRoleName string `validate:"required"` EcsExecutionRole *iam.CreateRoleInput EcsExecutionRolePolicyArns []string `validate:"required"` EcsTaskRoleName string `validate:"required"` EcsTaskRole *iam.CreateRoleInput EcsTaskPolicyName string `validate:"required"` EcsTaskPolicy *iam.CreatePolicyInput EcsTaskPolicyDocument IamPolicyDocument Ec2SecurityGroupName string `validate:"required"` Ec2SecurityGroup *ec2.CreateSecurityGroupInput CloudWatchLogGroupName string `validate:"required"` CloudWatchLogGroup *cloudwatchlogs.CreateLogGroupInput S3BucketTempPrefix string `validate:"required_with=S3BucketPrivateName S3BucketPublicName"` S3BucketPrivateName string `validate:"omitempty"` S3BucketPublicName string `validate:"omitempty"` S3Buckets []S3Bucket EnableEcsElb bool `validate:"omitempty"` ElbLoadBalancerName string `validate:"omitempty"` ElbLoadBalancer *elbv2.CreateLoadBalancerInput ElbDeregistrationDelay *int `validate:"omitempty"` ElbSecurityGroupName string `validate:"omitempty"` ElbSecurityGroup *ec2.CreateSecurityGroupInput VpcPublicName string `validate:"omitempty"` VpcPublic *ec2.CreateVpcInput VpcPublicSubnetsDesired int `validate:"omitempty"` EnableLambdaVPC bool `validate:"omitempty"` NoBuild bool `validate:"omitempty"` NoDeploy bool `validate:"omitempty"` NoCache bool `validate:"omitempty"` NoPush bool `validate:"omitempty"` RecreateService bool `validate:"omitempty"` SDNamepsace *servicediscovery.CreatePrivateDnsNamespaceInput SDService *servicediscovery.CreateServiceInput CacheCluster *elasticache.CreateCacheClusterInput CacheClusterParameter []*elasticache.ParameterNameValue DBCluster *rds.CreateDBClusterInput DBInstance *rds.CreateDBInstanceInput ReleaseImage string BuildTags []string flags ServiceDeployFlags _awsSession *session.Session } type S3Bucket struct { Name string `validate:"omitempty"` Input *s3.CreateBucketInput LifecycleRules []*s3.LifecycleRule CORSRules []*s3.CORSRule PublicAccessBlock *s3.PublicAccessBlockConfiguration Policy string } // DB mimics the general info needed for services used to define placeholders. type DB struct { Host string User string Pass string Database string Driver string DisableTLS bool } // projectNameCamel takes a project name and returns the camel cased version. func (r *serviceDeployRequest) ProjectNameCamel() string { s := strings.Replace(r.ProjectName, "_", " ", -1) s = strings.Replace(s, "-", " ", -1) s = strcase.ToCamel(s) return s } // awsSession returns the current AWS session for the serviceDeployRequest. func (r *serviceDeployRequest) awsSession() *session.Session { if r._awsSession == nil { r._awsSession = r.AwsCreds.Session() } return r._awsSession } // AwsCredentials defines AWS credentials used for deployment. Unable to use roles when deploying // using gitlab CI/CD pipeline. type awsCredentials struct { AccessKeyID string `validate:"required"` SecretAccessKey string `validate:"required"` Region string `validate:"required"` } // Session returns a new AWS Session used to access AWS services. func (creds awsCredentials) Session() *session.Session { return session.New( &aws.Config{ Region: aws.String(creds.Region), Credentials: credentials.NewStaticCredentials(creds.AccessKeyID, creds.SecretAccessKey, ""), }) } // IamPolicyDocument defines an AWS IAM policy used for defining access for IAM roles, users, and groups. type IamPolicyDocument struct { Version string `json:"Version"` Statement []IamStatementEntry `json:"Statement"` } // IamStatementEntry defines a single statement for an IAM policy. type IamStatementEntry struct { Sid string `json:"Sid"` Effect string `json:"Effect"` Action []string `json:"Action"` Resource interface{} `json:"Resource"` }