├── .gitignore ├── README.md ├── index.js ├── project.clj ├── run.js └── src └── dns_resolver └── core.cljs /.gitignore: -------------------------------------------------------------------------------- 1 | pom.xml 2 | *jar 3 | /lib/ 4 | /classes/ 5 | /out/ 6 | /target/ 7 | .lein-deps-sum 8 | .lein-repl-history 9 | .lein-plugins/ 10 | node_modules/ 11 | *.zip -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # POC ClojureScript AWS Lambda Function 2 | 3 | ## Usage 4 | 5 | Create a Lambda function in your AWS account: 6 | 7 | ``` 8 | $ zip -r lambda.zip index.js node_modules out 9 | $ lein npm install 10 | $ aws lambda upload-function \ 11 | --region us-west-2 \ 12 | --function-name dns-resolver \ 13 | --function-zip ./lambda.zip \ 14 | --timeout 10 \ 15 | --runtime nodejs \ 16 | --handler handler \ 17 | --mode event \ 18 | --role arn:aws:iam:::role/lambda_exec_role 19 | ``` 20 | 21 | Test the Lambda in the AWS console, with the following input: 22 | 23 | ``` 24 | { 25 | "domain": "example.com", 26 | "type": "A" 27 | } 28 | ``` 29 | 30 | ## DIY 31 | 32 | 1. `lein new mies-node my-lambda` 33 | 2. `cd my-lambda && lein npm install` 34 | 3. Create an `index.js` to export your function 35 | 4. `zip -r lambda.zip index.js node_modules out` 36 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | try { 2 | require("source-map-support").install(); 3 | } catch(err) { 4 | } 5 | require("./out/goog/bootstrap/nodejs.js"); 6 | require("./out/dns_resolver.js"); 7 | goog.require("dns_resolver.core"); 8 | 9 | exports.handler = dns_resolver.core.handler 10 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject dns-resolver "0.1.0-SNAPSHOT" 2 | :description "FIXME: write this!" 3 | :url "http://example.com/FIXME" 4 | 5 | :dependencies [[org.clojure/clojure "1.6.0"] 6 | [org.clojure/clojurescript "0.0-2657"]] 7 | 8 | :node-dependencies [[source-map-support "0.2.8"] 9 | [aws-sdk "2.1.7"] 10 | [node-uuid "1.4.2"]] 11 | 12 | :plugins [[lein-cljsbuild "1.0.4"] 13 | [lein-npm "0.4.0"]] 14 | 15 | :source-paths ["src"] 16 | 17 | :cljsbuild { 18 | :builds [{:id "dns-resolver" 19 | :source-paths ["src"] 20 | :notify-command ["node" "index.js" "example.com" "A"] 21 | :compiler { 22 | :output-to "out/dns_resolver.js" 23 | :output-dir "out" 24 | :target :nodejs 25 | :optimizations :none 26 | :source-map true}}]}) 27 | -------------------------------------------------------------------------------- /run.js: -------------------------------------------------------------------------------- 1 | try { 2 | require("source-map-support").install(); 3 | } catch(err) { 4 | } 5 | require("./out/goog/bootstrap/nodejs.js"); 6 | require("./out/dns_resolver.js"); 7 | goog.require("dns_resolver.core"); 8 | goog.require("cljs.nodejscli"); 9 | -------------------------------------------------------------------------------- /src/dns_resolver/core.cljs: -------------------------------------------------------------------------------- 1 | (ns dns-resolver.core 2 | (:require [cljs.nodejs :as nodejs])) 3 | 4 | (nodejs/enable-util-print!) 5 | 6 | (def dns (nodejs/require "dns")) 7 | (def aws (nodejs/require "aws-sdk")) 8 | (def uuid (nodejs/require "node-uuid")) 9 | 10 | (defn- query->result [job err addresses] 11 | (let [result* (if (nil? err) 12 | ;; then 13 | {:status :success 14 | :result addresses} 15 | ;; else 16 | {:status :failure 17 | :result (.toString err)})] 18 | (merge job result*))) 19 | 20 | (defn- persist-result [result] 21 | ;; (let [db (aws.DynamoDB.)] 22 | ;; (.putItem db {:TableName "dns_resolver" 23 | ;; :Item (js-obj result)})) 24 | result) 25 | 26 | (defn- call-done-fn [result] 27 | (let [status (if (= (:status result) :success) 28 | nil 29 | "error") 30 | prepare-result (comp #(.stringify js/JSON %) 31 | clj->js 32 | #(dissoc % :done-fn))] 33 | ((:done-fn result) status (prepare-result result)))) 34 | 35 | (defn- handle-result [job err addrs] 36 | (-> 37 | (query->result job err addrs) 38 | (persist-result) 39 | (call-done-fn))) 40 | 41 | (defn resolve [job] 42 | (.resolve dns (:domain job) (:type job) #(handle-result job %1 %2))) 43 | 44 | ;; AWS Lambda entry point 45 | (defn ^:export handler [event context] 46 | (resolve {:uuid (or (aget event "uuid") (.v4 uuid)) 47 | :domain (aget event "domain") 48 | :type (aget event "type") 49 | :done-fn (aget context "done")})) 50 | 51 | ;; CLI entry point 52 | (defn -main [domain type uuid] 53 | (resolve {:uuid (or uuid (.v4 uuid)) 54 | :domain domain 55 | :type type 56 | :done-fn println})) 57 | 58 | (set! *main-cli-fn* -main) 59 | --------------------------------------------------------------------------------