@@ -21,10 +21,18 @@ func main() {
2121 // DO NOTHING
2222}
2323
24+ // Policy holds information for the deployer to implement
2425type Policy struct {
25- MaximumVersions int
26+ // MaximumUnAliasedVersions is the maximum unaliased versions of a lambda function
27+ // we want to keep. Versions with an alias are never deleted.
28+ MaximumUnAliasedVersions int
29+
30+ // ReduceUnAliasedVersions is true if MaxUnAliasedVersions has been specified
31+ ReduceUnAliasedVersions bool
2632}
2733
34+ // S3Event struct captures the JSON structure of the event passed when a new
35+ // object is created in S3
2836type S3Event struct {
2937 Records []struct {
3038 EventVersion string `json:"eventVersion"`
@@ -62,6 +70,9 @@ type S3Event struct {
6270 } `json:"Records"`
6371}
6472
73+ // Handle is called when ever an object is written to S3 via the uploader.
74+ // We assume this is always a lambda function zip file and that AWS Lambda will error
75+ // if the file is not of a correct format.
6576func Handle (evt json.RawMessage , ctx * runtime.Context ) (string , error ) {
6677
6778 log .Println ("deployer : " , deployer .VersionString ())
@@ -73,9 +84,15 @@ func Handle(evt json.RawMessage, ctx *runtime.Context) (string, error) {
7384 return "error" , errors .New ("DEPLOYER_FUNCTION_ROLE_ARN not set" )
7485 }
7586
87+ policy , err := loadPolicy ()
88+
89+ if err != nil {
90+ return "error" , errors .Wrap (err , "error loading policy" )
91+ }
92+
7693 s3Event := S3Event {}
7794
78- err : = json .Unmarshal (evt , & s3Event )
95+ err = json .Unmarshal (evt , & s3Event )
7996
8097 if err != nil {
8198 return "error" , errors .Wrap (err , "error un-marshaling event json" )
@@ -87,36 +104,48 @@ func Handle(evt json.RawMessage, ctx *runtime.Context) (string, error) {
87104 return "error" , err
88105 }
89106
90- svc := lambda .New (session , aws .NewConfig ())
107+ lambdaSvc := lambda .New (session , aws .NewConfig ())
108+ s3Svc := s3 .New (session , aws .NewConfig ())
91109
92110 bucket := s3Event .Records [0 ].S3 .Bucket .Name
93111 key := s3Event .Records [0 ].S3 .Object .Key
94112
95- s3Svc := s3 .New (session , aws .NewConfig ())
96113 meta , err := getMetadata (s3Svc , bucket , key )
97114
98115 if err != nil {
99116 return "error" , errors .Wrap (err , "error reading metadata from s3 object" )
100117 }
101118
102119 // create or update the lambda function
103- conf , err := aws_helper .CreateOrUpdateFunction (svc , bucket , key , role , meta )
120+ conf , err := aws_helper .CreateOrUpdateFunction (lambdaSvc , bucket , key , role , meta )
104121
105122 if err != nil {
106123 return "error" , errors .Wrap (err , "error creating or updating lambda function" )
107124 }
108125
109126 // update, create the alias
110- err = aws_helper .CreateOrUpdateAlias (svc , conf , meta )
127+ err = aws_helper .CreateOrUpdateAlias (lambdaSvc , conf , meta )
111128
112129 if err != nil {
113130 return "error" , errors .Wrap (err , "error creating or updating alias" )
114131 }
115132
133+ // delete unused versions if required
134+ if policy .ReduceUnAliasedVersions {
135+
136+ err = aws_helper .ReduceUnAliasedVersions (lambdaSvc , policy .MaximumUnAliasedVersions , meta )
137+
138+ if err != nil {
139+ return "error" , errors .Wrap (err , "error deleting UnAliased versions" )
140+ }
141+
142+ }
143+
116144 return "ok" , nil
117145
118146}
119147
148+ // getMetadata parses the S3 object metadata
120149func getMetadata (svc * s3.S3 , s3Bucket , s3Key string ) (deployer.FunctionMetadata , error ) {
121150
122151 req := & s3.HeadObjectInput {
@@ -130,26 +159,26 @@ func getMetadata(svc *s3.S3, s3Bucket, s3Key string) (deployer.FunctionMetadata,
130159 return deployer.FunctionMetadata {}, err
131160 }
132161
133- memorySize , err := strconv .ParseInt (* (resp .Metadata ["Function-Memory-Size" ]), 10 , 64 )
162+ memorySize , err := strconv .ParseInt (* (resp .Metadata [deployer . FunctionMemorySizeTag ]), 10 , 64 )
134163
135164 if err != nil {
136165 return deployer.FunctionMetadata {}, errors .Wrap (err , "cannot parse function-memory-size" )
137166 }
138167
139- timeout , err := strconv .ParseInt (* (resp .Metadata ["Function-Timeout" ]), 10 , 64 )
168+ timeout , err := strconv .ParseInt (* (resp .Metadata [deployer . FunctionTimeoutTag ]), 10 , 64 )
140169
141170 if err != nil {
142171 return deployer.FunctionMetadata {}, errors .Wrap (err , "cannot parse function-timeout" )
143172 }
144173
145174 meta := deployer.FunctionMetadata {
146- Description : * (resp .Metadata ["Function-Description" ]),
147- FunctionName : * (resp .Metadata ["Function-Name" ]),
148- Handler : * (resp .Metadata ["Function-Handler" ]),
149- Runtime : * (resp .Metadata ["Function-Runtime" ]),
175+ Description : * (resp .Metadata [deployer . FunctionDescriptionTag ]),
176+ FunctionName : * (resp .Metadata [deployer . FunctionNameTag ]),
177+ Handler : * (resp .Metadata [deployer . FunctionHandlerTag ]),
178+ Runtime : * (resp .Metadata [deployer . FunctionRuntimeTag ]),
150179 MemorySize : int64 (memorySize ),
151180 Timeout : int64 (timeout ),
152- Alias : * (resp .Metadata ["Function-Alias" ]),
181+ Alias : * (resp .Metadata [deployer . FunctionAliasTag ]),
153182 EnvVars : map [string ]interface {}{},
154183 }
155184
@@ -159,9 +188,33 @@ func getMetadata(svc *s3.S3, s3Bucket, s3Key string) (deployer.FunctionMetadata,
159188 err = json .Unmarshal ([]byte (envVars ), & meta .EnvVars )
160189
161190 if err != nil {
162- return deployer.FunctionMetadata {}, errors .Wrap (err , "error un-marshaling envionmental vars" )
191+ return deployer.FunctionMetadata {}, errors .Wrap (err , "error un-marshaling environmental vars" )
163192 }
164193
165194 return meta , nil
166195
167196}
197+
198+ func loadPolicy () (Policy , error ) {
199+
200+ maxUnAliasedVersionsStr := os .Getenv ("DEPLOYER_POLICY_MAX_UNALIASED_VERSIONS" )
201+
202+ maxUnAliasedVersions := int64 (0 )
203+ var reduceUnAliasedVersions bool
204+ var err error
205+
206+ if maxUnAliasedVersionsStr != "" {
207+
208+ maxUnAliasedVersions , err = strconv .ParseInt (maxUnAliasedVersionsStr , 10 , 64 )
209+
210+ if err != nil {
211+ return Policy {}, err
212+ }
213+ reduceUnAliasedVersions = true
214+ }
215+ return Policy {
216+ MaximumUnAliasedVersions : int (maxUnAliasedVersions ),
217+ ReduceUnAliasedVersions : reduceUnAliasedVersions ,
218+ }, nil
219+
220+ }
0 commit comments