Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add task to update function configuration and run during deploy #1

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 56 additions & 2 deletions src/provisdom/boot_lambda.clj
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
(:require
[clojure.string :as str]
[clojure.java.io :as io]
[clojure.java.shell :as java-shell]
[boot.core :as core]
[boot.util :as util]))

Expand Down Expand Up @@ -34,6 +35,30 @@
[input-files opts command & args]
(-> opts (task-opts->cmd-opts input-files) (cmd-opts->string (format "aws lambda %s" command)) (str " " (str/join " " args))))

(defn- last-lambda-update-status
[function-name]
(let [cmd-string (format "aws lambda get-function-configuration --function-name %s --query \"LastUpdateStatus\" --output text" function-name)]
(util/info (str cmd-string "\n"))
(-> (apply java-shell/sh (str/split cmd-string #" "))
(:out)
(str/trim))))

(defn- await-configuration-update-success
[function-name]
(let [retry-after-seconds 10
timeout-seconds 90] ; AWS docs say it should complete within a minute; give it a little longer (https://docs.aws.amazon.com/cli/latest/reference/lambda/update-function-configuration.html)
(loop [elapsed-seconds 0]
(when (>= elapsed-seconds timeout-seconds)
(throw (Exception. "Function configuration update did not complete in time\n")))
(let [status (last-lambda-update-status function-name)]
(case status
"InProgress" (do (util/info "Waiting until lambda function configuration has completed successfully...\n")
(Thread/sleep (* retry-after-seconds 1000))
(recur (+ elapsed-seconds retry-after-seconds)))
"Failed" (throw (Exception. "Function configuration update failed\n"))
"Successful" (util/info "Function configuration update was successful\n")
(throw (Exception. (str "Unexpected function configuration update status: " status))))))))

(core/deftask create-function
[f function-name VAL str "The name you want to assign to the function you are uploading"
r runtime VAL str "The runtime environment for the Lambda function you are uploading"
Expand All @@ -59,6 +84,34 @@
(shell cmd-string))
fileset))

(core/deftask update-function-configuration
[f function-name VAL str "The name you want to assign to the function you are uploading"
r runtime VAL str "The runtime environment for the Lambda function you are uploading"
i role VAL str "The ARN of the IAM role that Lambda assumes when it executes your function"
e handler VAL sym "The function within your code that Lambda calls to begin execution"
d description VAL str "A short, user-defined function description"
t timeout VAL int "The function execution time at which Lambda should terminate the function"
m memory-size VAL int "The amount of memory, in MB, your Lambda function is given"
v vpc-config VAL str "Identifies the list of security group IDs and subnet IDs"
j cli-input-json VAL str "Performs service operation based on the JSON string provided"
g generate-cli-skeleton bool "Prints a sample input JSON to standard output"
_ environment VAL str "The parent object that contains your environment's configuration settings"
_ dead-letter-config VAL str "The parent object that contains the target ARN (Amazon Resource Name) of an Amazon SQS queue or Amazon SNS topic"
_ kms-key-arn VAL str "The Amazon Resource Name (ARN) of the KMS key used to encrypt your function's environment variables"
_ tracing-config VAL str "The parent object that contains your function's tracing settings"
_ revision-id VAL str "Used to ensure you are updating the latest update of the function version or alias"
_ layers VAL str "A string containing zero or more function layers specified by their ARNs and separated by a space"]
(when-not function-name
(throw (Exception. "Required function-name to update function configuration")))
(core/with-pre-wrap fileset
(let [input-files (core/input-files fileset)
cmd-string (lambda-cmd-string input-files *opts* "update-function-configuration")]
(util/info "Updating lambda function configuration...\n")
(util/info (str cmd-string "\n"))
(shell cmd-string)
(await-configuration-update-success function-name))
fileset))

(core/deftask update-function
[f function-name VAL str "The name you want to assign to the function you are uploading"
l local-file VAL str "The path to the local file of the code you are uploading"
Expand Down Expand Up @@ -112,7 +165,8 @@
(try
;; throws if function does not exist
(shell (format "aws lambda get-function --function-name %s" function-name))
(apply update-function (mapcat identity (select-task-keys #'update-function opts)))
(comp (apply update-function-configuration (mapcat identity (select-task-keys #'update-function-configuration opts)))
(apply update-function (mapcat identity (select-task-keys #'update-function opts))))
(catch Exception ex
(util/info (format "Function %s not found. Creating function..." function-name))
(apply create-function (mapcat identity (select-task-keys #'create-function opts)))))))
Expand All @@ -135,4 +189,4 @@
out-dir (core/tmp-dir!)
out-file (io/file out-dir out-file-name)]
(spit out-file file-content)
(core/commit! (core/add-resource fileset out-dir)))))
(core/commit! (core/add-resource fileset out-dir)))))