Skip to content

Instantly share code, notes, and snippets.

@d11wtq
Last active August 29, 2015 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save d11wtq/702f272ff0234c83f88a to your computer and use it in GitHub Desktop.
Save d11wtq/702f272ff0234c83f88a to your computer and use it in GitHub Desktop.
(ns example.factory.aws.cloudformation
(:require [clojure.data.json :as json]))
(defn apply-stack-fn
[create-fn update-fn]
(fn apply-stack
[payload]
(try
(create-fn payload)
(catch AlreadyExistsException e
(update-fn payload)))))
(defn expand-params
[params-hash]
(map
(fn [[key value]]
(zipmap [:parameter-key :parameter-value]
[key value]))
params))
(defn deploy-stack-fn
[apply-fn]
(fn deploy-stack
[stack-name template-hash params-hash]
(apply-fn :stack-name stack-name
:template-body (json/write-str template-hash)
:parameters (expand-params params-hash))))
(ns example.aws.cloudformation
(:require [example.factory.aws.cloudformation :as factory]
[amazonica.aws.cloudformation :as cloudformation])) ; side-effecty AWS SDK
(def apply-stack
(factory/apply-stack-fn cloudformation/create-stack
cloudformation/update-stack))
(def deploy-stack
(factory/deploy-stack-fn apply-stack))
(ns example.factory.aws.cloudformation-test
(:require [clojure.test :refer :all]
[example.factory.aws.cloudformation :as factory]))
(deftest apply-stack-fn-test
(testing "applies create-fn with payload"
(let [payload {:stack-name "example"}
create-fn (spy)
update-fn (spy)]
((factory/apply-stack-fn create-fn update-fn) payload)
(is (called? (create-fn payload)))))
(testing "when stack already exists"
(testing "applies update-fn with payload"
(let [payload {:stack-name "example"}
create-fn (fn [& args] (throw (AlreadyExistsException.)))
update-fn (spy)]
((factory/apply-stack-fn create-fn update-fn) payload)
(is (called? (update-fn payload)))))))
(deftest deploy-stack-fn
(testing "applies apply-fn with constructed payload"
(let [apply-fn (spy)]
((factory/deploy-stack-fn apply-fn) "example"
{:Description "Example"}
{:port "8080"})
(is (called? (apply-fn {:stack-name "example"
:template-body "{\"Description\":\"Example\"}"
:parameters [{:parameter-key :port
:parameter-value "8080"}]}))))))
// example/factory/aws/cloudformation.js
module.exports.applyStackFunc = function(createFunc, updateFunc){
return function(payload) {
try {
return createFunc(payload);
} catch (e if e instanceof AlreadyExistsException) {
return updateFunc(payload);
}
};
};
module.exports.deployStackFunc = function(applyFunc) {
return function(stackName, template, params) {
return applyFunc({
stackName: stackName,
templateBody: JSON.stringify(template),
parameters: expandParams(params)
});
}
};
// example/aws/cloudformation.js
var factory = require('example/factory/aws/cloudformation')
, AWS = require('aws-sdk')
;
var cloudformation = new AWS.CloudFormation();
module.exports.applyStack = factory.applyStackFunc(
cloudformation.createStack,
cloudformation.updateStack
);
module.exports.deployStack = factory.deployStackFunc(
module.exports.applyStack
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment