1
0
mirror of https://github.com/raseels-repos/golang-saas-starter-kit.git synced 2025-06-25 00:46:51 +02:00
Files
golang-saas-starter-kit/build/cicd/internal/config/function.go

299 lines
9.0 KiB
Go
Raw Normal View History

2019-08-21 14:31:28 -08:00
package config
import (
"log"
"path/filepath"
"encoding/json"
"github.com/aws/aws-sdk-go/aws"
"github.com/pkg/errors"
"gitlab.com/geeks-accelerator/oss/devops/pkg/devdeploy"
)
// Function define the name of a function.
type Function = string
var (
Function_Ddlogscollector = "ddlogscollector"
2019-08-21 14:31:28 -08:00
)
// List of function names used by main.go for help.
var FunctionNames = []Function{
// Python Datadog Logs Collector
Function_Ddlogscollector,
}
2019-08-26 04:48:43 -08:00
// NewFunction returns the *devdeploy.ProjectFunction.
func NewFunction(funcName string, cfg *devdeploy.Config) (*devdeploy.ProjectFunction, error) {
2019-08-21 14:31:28 -08:00
2019-08-26 04:48:43 -08:00
ctx := &devdeploy.ProjectFunction{
Name: funcName,
CodeDir: filepath.Join(cfg.ProjectRoot, "cmd", funcName),
DockerBuildDir: cfg.ProjectRoot,
2019-08-21 14:31:28 -08:00
DockerBuildContext: ".",
2019-08-26 04:48:43 -08:00
// Set the release tag for the image to use include env + function name + commit hash/tag.
2019-08-21 14:31:28 -08:00
ReleaseTag: devdeploy.GitLabCiReleaseTag(cfg.Env, funcName),
}
switch funcName {
case Function_Ddlogscollector:
// Python Datadog Logs Collector is
2019-08-26 04:48:43 -08:00
ctx.CodeDir = filepath.Join(cfg.ProjectRoot, "deployments", funcName)
2019-08-21 14:31:28 -08:00
// Change the build directory to the function directory instead of project root.
2019-08-26 04:48:43 -08:00
ctx.DockerBuildDir = ctx.CodeDir
2019-08-21 14:31:28 -08:00
// AwsLambdaFunction defines the details needed to create an lambda function.
ctx.AwsLambdaFunction = &devdeploy.AwsLambdaFunction{
FunctionName: ctx.Name,
Description: "Ship logs from cloudwatch to datadog",
Handler: "lambda_function.lambda_handler",
Runtime: "python2.7",
MemorySize: 512,
Timeout: aws.Int64(300),
Environment: map[string]string{
"DD_API_KEY": "",
"LAMBDA_FUNC": ctx.Name,
},
Tags: []devdeploy.Tag{
{Key: devdeploy.AwsTagNameProject, Value: cfg.ProjectName},
{Key: devdeploy.AwsTagNameEnv, Value: cfg.Env},
},
}
ctx.AwsIamRole = &devdeploy.AwsIamRole{
RoleName: "DatadogAWSIntegrationLambdaRole",
Description: "Allows Datadog to run Lambda functions to call AWS services on your behalf.",
AssumeRolePolicyDocument: "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":[\"lambda.amazonaws.com\"]},\"Action\":[\"sts:AssumeRole\"]}]}",
Tags: []devdeploy.Tag{
{Key: devdeploy.AwsTagNameProject, Value: cfg.ProjectName},
{Key: devdeploy.AwsTagNameEnv, Value: cfg.Env},
},
}
ctx.AwsIamPolicy = &devdeploy.AwsIamPolicy{
PolicyName: "DatadogAWSIntegrationPolicy",
Description: "Provides Datadog Lambda function the ability to ship AWS service related logs back to Datadog.",
PolicyDocument: devdeploy.AwsIamPolicyDocument{
Version: "2012-10-17",
Statement: []devdeploy.AwsIamStatementEntry{
{
Action: []string{
"apigateway:GET",
"autoscaling:Describe*",
"budgets:ViewBudget",
"cloudfront:GetDistributionConfig",
"cloudfront:ListDistributions",
"cloudtrail:DescribeTrails",
"cloudtrail:GetTrailStatus",
"cloudwatch:Describe*",
"cloudwatch:Get*",
"cloudwatch:List*",
"codedeploy:List*",
"codedeploy:BatchGet*",
"directconnect:Describe*",
"dynamodb:List*",
"dynamodb:Describe*",
"ec2:Describe*",
"ecs:Describe*",
"ecs:List*",
"elasticache:Describe*",
"elasticache:List*",
"elasticfilesystem:DescribeFileSystems",
"elasticfilesystem:DescribeTags",
"elasticloadbalancing:Describe*",
"elasticmapreduce:List*",
"elasticmapreduce:Describe*",
"es:ListTags",
"es:ListDomainNames",
"es:DescribeElasticsearchDomains",
"health:DescribeEvents",
"health:DescribeEventDetails",
"health:DescribeAffectedEntities",
"kinesis:List*",
"kinesis:Describe*",
"lambda:AddPermission",
"lambda:GetPolicy",
"lambda:List*",
"lambda:RemovePermission",
"logs:Get*",
"logs:Describe*",
"logs:FilterLogEvents",
"logs:TestMetricFilter",
"logs:PutSubscriptionFilter",
"logs:DeleteSubscriptionFilter",
"logs:DescribeSubscriptionFilters",
"rds:Describe*",
"rds:List*",
"redshift:DescribeClusters",
"redshift:DescribeLoggingStatus",
"route53:List*",
"s3:GetBucketLogging",
"s3:GetBucketLocation",
"s3:GetBucketNotification",
"s3:GetBucketTagging",
"s3:ListAllMyBuckets",
"s3:PutBucketNotification",
"ses:Get*",
"sns:List*",
"sns:Publish",
"sqs:ListQueues",
"support:*",
"tag:GetResources",
"tag:GetTagKeys",
"tag:GetTagValues",
"xray:BatchGetTraces",
"xray:GetTraceSummaries",
"lambda:List*",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"logs:FilterLogEvents",
"tag:GetResources",
"cloudfront:GetDistributionConfig",
"cloudfront:ListDistributions",
"elasticloadbalancing:DescribeLoadBalancers",
"elasticloadbalancing:DescribeLoadBalancerAttributes",
"lambda:AddPermission",
"lambda:GetPolicy",
"lambda:RemovePermission",
"redshift:DescribeClusters",
"redshift:DescribeLoggingStatus",
"s3:GetBucketLogging",
"s3:GetBucketLocation",
"s3:GetBucketNotification",
"s3:ListAllMyBuckets",
"s3:PutBucketNotification",
"logs:PutSubscriptionFilter",
"logs:DeleteSubscriptionFilter",
"logs:DescribeSubscriptionFilters",
},
Effect: "Allow",
Resource: "*",
},
},
},
}
default:
return nil, errors.Wrapf(devdeploy.ErrInvalidFunction,
"No function context defined for function '%s'",
funcName)
}
// Append the datadog api key before execution.
ctx.AwsLambdaFunction.UpdateEnvironment = func(vars map[string]string) error {
datadogApiKey, err := getDatadogApiKey(cfg)
if err != nil {
return err
}
vars["DD_API_KEY"] = datadogApiKey
return nil
}
2019-08-26 04:48:43 -08:00
ctx.CodeS3Bucket = cfg.AwsS3BucketPrivate.BucketName
ctx.CodeS3Key = filepath.Join("src", "aws", "lambda", cfg.Env, ctx.Name, ctx.ReleaseTag+".zip")
2019-08-21 14:31:28 -08:00
// Set the docker file if no custom one has been defined for the service.
if ctx.Dockerfile == "" {
2019-08-26 04:48:43 -08:00
ctx.Dockerfile = filepath.Join(ctx.CodeDir, "Dockerfile")
2019-08-21 14:31:28 -08:00
}
return ctx, nil
}
// BuildFunctionForTargetEnv executes the build commands for a target function.
func BuildFunctionForTargetEnv(log *log.Logger, awsCredentials devdeploy.AwsCredentials, targetEnv Env, functionName, releaseTag string, dryRun, noCache, noPush bool) error {
2019-08-26 04:48:43 -08:00
cfg, err := NewConfig(log, targetEnv, awsCredentials)
2019-08-21 14:31:28 -08:00
if err != nil {
return err
}
2019-08-26 04:48:43 -08:00
targetFunc, err := NewFunction(functionName, cfg)
2019-08-21 14:31:28 -08:00
if err != nil {
return err
}
// Override the release tag if set.
if releaseTag != "" {
2019-08-26 04:48:43 -08:00
targetFunc.ReleaseTag = releaseTag
2019-08-21 14:31:28 -08:00
}
2019-08-26 04:48:43 -08:00
// Append build args to be used for all functions.
if targetFunc.DockerBuildArgs == nil {
targetFunc.DockerBuildArgs = make(map[string]string)
2019-08-21 14:31:28 -08:00
}
// funcPath is used to copy the service specific code in the Dockerfile.
2019-08-26 04:48:43 -08:00
codePath, err := filepath.Rel(cfg.ProjectRoot, targetFunc.CodeDir)
2019-08-21 14:31:28 -08:00
if err != nil {
return err
}
2019-08-26 04:48:43 -08:00
targetFunc.DockerBuildArgs["code_path"] = codePath
2019-08-21 14:31:28 -08:00
// commitRef is used by main.go:build constant.
commitRef := getCommitRef()
if commitRef == "" {
2019-08-26 04:48:43 -08:00
commitRef = targetFunc.ReleaseTag
2019-08-21 14:31:28 -08:00
}
2019-08-26 04:48:43 -08:00
targetFunc.DockerBuildArgs["commit_ref"] = commitRef
2019-08-21 14:31:28 -08:00
if dryRun {
cfgJSON, err := json.MarshalIndent(cfg, "", " ")
if err != nil {
log.Fatalf("BuildFunctionForTargetEnv : Marshalling config to JSON : %+v", err)
}
log.Printf("BuildFunctionForTargetEnv : config : %v\n", string(cfgJSON))
2019-08-26 04:48:43 -08:00
detailsJSON, err := json.MarshalIndent(targetFunc, "", " ")
2019-08-21 14:31:28 -08:00
if err != nil {
log.Fatalf("BuildFunctionForTargetEnv : Marshalling details to JSON : %+v", err)
}
log.Printf("BuildFunctionForTargetEnv : details : %v\n", string(detailsJSON))
return nil
}
2019-08-26 04:48:43 -08:00
return devdeploy.BuildLambdaForTargetEnv(log, cfg, targetFunc, noCache, noPush)
2019-08-21 14:31:28 -08:00
}
// DeployFunctionForTargetEnv executes the deploy commands for a target function.
func DeployFunctionForTargetEnv(log *log.Logger, awsCredentials devdeploy.AwsCredentials, targetEnv Env, functionName, releaseTag string, dryRun bool) error {
2019-08-26 04:48:43 -08:00
cfg, err := NewConfig(log, targetEnv, awsCredentials)
2019-08-21 14:31:28 -08:00
if err != nil {
return err
}
2019-08-26 04:48:43 -08:00
targetFunc, err := NewFunction(functionName, cfg)
2019-08-21 14:31:28 -08:00
if err != nil {
return err
}
// Override the release tag if set.
if releaseTag != "" {
2019-08-26 04:48:43 -08:00
targetFunc.ReleaseTag = releaseTag
2019-08-21 14:31:28 -08:00
}
if dryRun {
cfgJSON, err := json.MarshalIndent(cfg, "", " ")
if err != nil {
log.Fatalf("DeployFunctionForTargetEnv : Marshalling config to JSON : %+v", err)
}
log.Printf("DeployFunctionForTargetEnv : config : %v\n", string(cfgJSON))
2019-08-26 04:48:43 -08:00
detailsJSON, err := json.MarshalIndent(targetFunc, "", " ")
2019-08-21 14:31:28 -08:00
if err != nil {
log.Fatalf("DeployFunctionForTargetEnv : Marshalling details to JSON : %+v", err)
}
log.Printf("DeployFunctionForTargetEnv : details : %v\n", string(detailsJSON))
return nil
}
2019-08-26 04:48:43 -08:00
return devdeploy.DeployLambdaToTargetEnv(log, cfg, targetFunc)
2019-08-21 14:31:28 -08:00
}