Change clojure template builder to take a map. Issue 272.

This commit is contained in:
Hugo Duncan 2010-09-12 21:23:48 -04:00
parent 00361f859b
commit 9a3b8e151f
2 changed files with 59 additions and 43 deletions

View File

@ -56,6 +56,8 @@ webserver:
See http://code.google.com/p/jclouds for details." See http://code.google.com/p/jclouds for details."
(:use org.jclouds.core (:use org.jclouds.core
(clojure.contrib logging core)) (clojure.contrib logging core))
(:require
[clojure.contrib.condition :as condition])
(:import java.io.File (:import java.io.File
java.util.Properties java.util.Properties
[org.jclouds.domain Location] [org.jclouds.domain Location]
@ -189,7 +191,9 @@ See http://code.google.com/p/jclouds for details."
(with-compute-service [compute] (with-compute-service [compute]
(run-nodes \"webserver\" 2 (run-nodes \"webserver\" 2
(build-template (build-template
service :centos :smallest :image-name-matches \".*w/ None.*\")))" service
{:os-family :centos :smallest true
:image-name-matches \".*w/ None.*\"})))"
([tag count] ([tag count]
(run-nodes tag count (default-template *compute*) *compute*)) (run-nodes tag count (default-template *compute*) *compute*))
([tag count compute-or-template] ([tag count compute-or-template]
@ -373,53 +377,45 @@ See http://code.google.com/p/jclouds for details."
(def enum-map {:os-family (os-families)}) (def enum-map {:os-family (os-families)})
(defn add-option-with-value-if [builder kword] (defn translate-enum-value [kword value]
(loop [enums (sequence enum-map)] (or (-> (filter #(= (name value) (str %)) (kword enum-map)) first)
(if (not (empty? enums)) value))
(let [enum (first enums)
value (filter #(= (name kword) (str %)) (second enum))]
(if (not (empty? value))
(((first enum) option-1arg-map) builder (first value))
(recur (rest enums)))))))
(defn add-option-if [builder kword] (defn add-nullary-option [builder option value]
(let [f (option-0arg-map kword)] (if-let [f (option-0arg-map option)]
(if f (f builder)))) (if value
(f builder)
(defn add-keyword-option [builder option] builder)))
(if (not (or (add-option-with-value-if builder option)
(add-option-if builder option)))
(println "Unknown option " option)))
(defn add-value-option [builder option value] (defn add-value-option [builder option value]
(let [f (option-1arg-map option)] (if-let [f (option-1arg-map option)]
(if f (f builder (translate-enum-value option value))))
(f builder value)
(println "Unknown option" option))))
;; TODO look at clojure-datalog ;; TODO look at clojure-datalog
(defn build-template (defn build-template
"Creates a template that can be used to run nodes. "Creates a template that can be used to run nodes.
There are many options to use for the default template" The :os-family key expects a keyword version of OsFamily,
[#^ComputeService compute option & options] eg. :os-family :ubuntu.
The :smallest, :fastest, :biggest, :any, and :destroy-on-error keys expect a
boolean value.
Options correspond to TemplateBuilder methods."
[#^ComputeService compute
{:keys [os-family location-id architecture image-id hardware-id
os-name-matches os-version-matches os-description-matches
os-64-bit image-version-matches image-name-matches
image-description-matches min-cores min-ram
run-script install-private-key authorize-public-key
inbound-ports smallest fastest biggest any destroy-on-error]
:as options}]
(let [builder (.. compute (templateBuilder))] (let [builder (.. compute (templateBuilder))]
(loop [option option (doseq [[option value] options]
remaining options] (or
(if (empty? remaining) (add-value-option builder option value)
(add-keyword-option builder option) (add-nullary-option builder option value)
(let [next-is-keyword (keyword? (first remaining)) (condition/raise
arg (if (not next-is-keyword) :type :invalid-template-builder-option
(first remaining)) :message (format "Invalid template builder option : %s" option))))
next (if next-is-keyword
(first remaining)
(fnext remaining))
remaining (if (keyword? (first remaining))
(rest remaining)
(drop 2 remaining))]
(if arg
(add-value-option builder option arg)
(add-keyword-option builder option))
(if next
(recur next remaining)))))
(.build builder))) (.build builder)))

View File

@ -19,7 +19,10 @@
(ns org.jclouds.compute-test (ns org.jclouds.compute-test
(:use [org.jclouds.compute] :reload-all) (:use [org.jclouds.compute] :reload-all)
(:use clojure.test)) (:use clojure.test)
(:import
org.jclouds.compute.domain.OsFamily
clojure.contrib.condition.Condition))
(defmacro with-private-vars [[ns fns] & tests] (defmacro with-private-vars [[ns fns] & tests]
"Refers private fns from ns and runs tests in context. From users mailing "Refers private fns from ns and runs tests in context. From users mailing
@ -49,3 +52,20 @@ list, Alan Dipert and MeikelBrandmeyer."
(is (compute-service? (compute-service "stub" "user" "password"))) (is (compute-service? (compute-service "stub" "user" "password")))
(is (compute-service? (as-compute-service *compute*))) (is (compute-service? (as-compute-service *compute*)))
(is (compute-service? (as-compute-service (compute-context *compute*))))) (is (compute-service? (as-compute-service (compute-context *compute*)))))
(deftest build-template-test
(let [service (compute-service "stub" "user" "password")]
(testing "nullary"
(is (>= (-> (build-template service {:fastest true})
bean :hardware bean :processors first bean :cores)
8.0)))
(testing "one arg"
(is (> (-> (build-template service {:min-ram 512})
bean :hardware bean :ram)
512)))
(testing "enumerated"
(is (= OsFamily/CENTOS
(-> (build-template service {:os-family :centos})
bean :image bean :operatingSystem bean :family))))
(testing "invalid"
(is (thrown? Condition (build-template service {:xx :yy}))))))