/
deploy_lambda.go
146 lines (123 loc) · 4.02 KB
/
deploy_lambda.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package devdeploy
import (
"github.com/aws/aws-sdk-go/aws"
"log"
"github.com/aws/aws-sdk-go/service/lambda"
"github.com/pkg/errors"
)
// DeployLambdaToTargetEnv deploys a function to AWS Lambda The following steps will be executed for deployment:
// 1. Find the AWS IAM role if defined.
// 2. Find the AWS function if it exists.
// 3. Create or update the code/configuration.
// 4. Hookup any AWS Cloudwatch Event Rules.
func DeployLambdaToTargetEnv(log *log.Logger, cfg *Config, target *ProjectFunction) error {
log.Printf("Deploy function %s to environment %s\n", target.Name, cfg.Env)
infra, err := NewInfrastructure(cfg)
if err != nil {
return err
}
// Step 1: Find or create the AWS IAM role.
if target.AwsIamRole != nil {
role, err := infra.GetAwsIamRole(target.AwsIamRole.RoleName)
if err != nil {
return err
}
target.AwsLambdaFunction.Role = role.Arn
log.Printf("\t%s\tConfigured Lambda role.\n", Success)
}
lambdaSvc := lambda.New(infra.AwsSession())
funcName := target.AwsLambdaFunction.FunctionName
// Step 2: Search for an existing lambda function
var lambdaFunc *lambda.FunctionConfiguration
{
log.Println("\tLambda - Check for existing function")
err := lambdaSvc.ListFunctionsPages(&lambda.ListFunctionsInput{},
func(res *lambda.ListFunctionsOutput, lastPage bool) bool {
for _, n := range res.Functions {
if *n.FunctionName == funcName {
lambdaFunc = n
return false
}
}
return !lastPage
})
if err != nil {
return errors.Wrap(err, "Failed to list functions")
}
}
var (
vpc *AwsEc2VpcResult
securityGroup *AwsEc2SecurityGroupResult
)
if target.EnableVPC {
if cfg.AwsEc2Vpc.IsDefault {
vpc, err = infra.GetAwsEc2DefaultVpc()
} else if cfg.AwsEc2Vpc.VpcId != "" {
vpc, err = infra.GetAwsEc2Vpc(cfg.AwsEc2Vpc.VpcId)
} else {
vpc, err = infra.GetAwsEc2Vpc(cfg.AwsEc2Vpc.CidrBlock)
}
if err != nil {
return err
}
securityGroup, err = infra.GetAwsEc2SecurityGroup(cfg.AwsEc2SecurityGroup.GroupName)
if err != nil {
return err
}
}
// Step 3: Create or update the code/configuration.
if lambdaFunc != nil {
log.Printf("\t\tFound: %s", *lambdaFunc.FunctionArn)
cfgRes, err := lambdaSvc.GetFunctionConfiguration(&lambda.GetFunctionConfigurationInput{
FunctionName: aws.String(funcName),
})
if err != nil {
return errors.Wrapf(err, "Failed to get configuration for '%s'", funcName)
}
codeInput, err := target.AwsLambdaFunction.UpdateCodeInput(target.CodeS3Bucket, target.CodeS3Key)
if err != nil {
return err
}
codeRes, err := lambdaSvc.UpdateFunctionCode(codeInput)
if err != nil {
return errors.Wrapf(err, "Failed to update code for '%s'", funcName)
}
lambdaFunc = codeRes
log.Printf("\t\tUpdated Code: %s", *lambdaFunc.FunctionArn)
configInput, err := target.AwsLambdaFunction.UpdateConfigurationInput(vpc, securityGroup, cfgRes)
if err != nil {
return err
}
configRes, err := lambdaSvc.UpdateFunctionConfiguration(configInput)
if err != nil {
return errors.Wrapf(err, "Failed to update configuration for '%s'", funcName)
}
lambdaFunc = configRes
log.Printf("\t\tUpdated Configuration: %s", *lambdaFunc.FunctionArn)
} else {
input, err := target.AwsLambdaFunction.CreateInput(target.CodeS3Bucket, target.CodeS3Key, vpc, securityGroup)
if err != nil {
return err
}
// If no repository was found, create one.
createRes, err := lambdaSvc.CreateFunction(input)
if err != nil {
return errors.Wrapf(err, "Failed to create repository '%s'", funcName)
}
lambdaFunc = createRes
log.Printf("\t\tCreated: %s", *lambdaFunc.FunctionArn)
}
// Hookup any defined Cloudwatch Event rules defined for the lambda function.
for _, eventRule := range target.AwsCloudwatchEventRules {
eventRule.Targets = append(eventRule.Targets, &AwsCloudwatchEventTarget{
Arn: *lambdaFunc.FunctionArn,
Id: *lambdaFunc.FunctionName,
RoleArn: lambdaFunc.Role,
})
_, err = infra.setupAwsCloudwatchEventRule(log, eventRule)
if err != nil {
return err
}
}
return nil
}