pallet.parameter.clj Maven / Gradle / Ivy
(ns pallet.parameter
"Provides functions for working with parameters.
Parameters are data maps that allow propogation of information between the
functions of a crate, and between crates. There are two conventions for using
parameters in crates that are directly supported here.
Host specific parameters are specified under
[:parameters :host (keyword target-id)]
These functions are `get-for-target`, `assoc-for-target`, and
`update-for-target`.
Service specific paramters, used across hosts, are specified under
[:parameters :service (keyword service-name)]
These functions are `get-for-service`, `assoc-for-service`, and
`update-for-service`.
The `get-for` functions have slightly different semantics compared with
clojure.core/get, in that they throw an exception if the key is undefined
and no default value is specified.
Delayed evaluation of parameters specified as arguments to action functions
are also implemented here. `lookup` and `lookup-for-target`.
"
(:require
[pallet.action :as action]
[pallet.argument :as argument]
[pallet.compute :as compute]
[clojure.contrib.condition :as condition]))
(defn from-map
"Initialise parameters based on the given keys, which are used to merge maps
from m."
[m keys]
(reduce merge {} (map m keys)))
(defn get-for
"Retrieve the parameter at the path specified by keys.
When no default value is specified, then raise a :parameter-not-found if no
parameter is set.
(get-for {:p {:a {:b 1} {:d 2}}} [:p :a :d])
=> 2"
([session keys]
{:pre [(map? session)]}
(let [result (get-in (:parameters session) keys ::not-set)]
(when (= ::not-set result)
(let [found-keys (take-while
#(not=
(get-in (:parameters session) % ::not-set)
::not-set)
(rest (reductions conj [] keys)))]
(condition/raise
:type :parameter-not-found
:message (format
(str
"Could not find keys %s in session :parameters. "
"Found keys %s with values %s")
(if (sequential? keys) (vec keys) keys)
(vec found-keys)
(if (seq found-keys)
(get-in (:parameters session) (vec found-keys))
(:parameters session)))
:key-not-set keys)))
result))
([session keys default]
(get-in (:parameters session) keys default)))
(defn get-for-target
"Retrieve the host parameter for the current target at the path specified by
keys. When no default value is specified, then raise a :parameter-not-found
if no parameter is set.
(get-for-target
{:parameters {:host {:id1 {:a {:b 1} {:d 2}}}}
:target-id :id1} [:a :b])
=> 1"
([session keys]
(get-for session (concat [:host (-> session :server :node-id)] keys)))
([session keys default]
(get-for
session (concat [:host (-> session :server :node-id)] keys) default)))
(defn get-for-service
"Retrieve the service parameter for the service and path specified by
keys. When no default value is specified, then raise a :parameter-not-found
if no parameter is set.
(get-for-service
{:parameters {:service {:proxy {:a {:b 1} {:d 2}}}}} [:proxy :a :b])
=> 1"
([session keys]
(get-for session (concat [:service] keys)))
([session keys default]
(get-for session (concat [:service] keys) default)))
(defn get-node-settings
"Retrieve the settings for the specified node facility. The instance-id allows
the specification of specific instance of the facility. If passed a nil
`instance-id`, then `:default` is used"
[session node facility instance-id]
(get-for
session
[:host (keyword (compute/id node)) facility (or instance-id :default)]))
(defn get-target-settings
"Retrieve the settings for the specified host facility. The instance-id allows
the specification of specific instance of the facility. If passed a nil
`instance-id`, then `:default` is used"
([session facility instance-id]
(get-for
session
[:host (-> session :server :node-id) facility (or instance-id :default)]))
([session facility instance-id default]
(get-for
session
[:host (-> session :server :node-id) facility (or instance-id :default)]
default)))
(defn- assoc-for-prefix
"Set the values in a map at the paths specified with prefix prepended to each
path.
(assoc-for-prefix {} :prefix [:a :b] 1 [:a :d] 2)
=> {:prefix {:a {:b 1} {:d 2}}}"
[session prefix {:as keys-value-pairs}]
(reduce
#(assoc-in %1 (concat prefix (first %2)) (second %2))
session
keys-value-pairs))
(defn assoc-for
"Set the :parameters values at the paths specified.
(assoc-for {} [:a :b] 1 [:a :d] 2)
=> {:parameters {:a {:b 1} {:d 2}}}"
[session & {:as keys-value-pairs}]
(assoc-for-prefix session [:parameters] keys-value-pairs))
(defn assoc-for-target
"Set the host parameter values at the paths specified.
(assoc-for-target {:target-id :id1} [:a :b] 1 [:a :d] 2)
=> {:parameters {:host {:id1 {:a {:b 1} {:d 2}}}}}"
[session & {:as keys-value-pairs}]
(assoc-for-prefix
session [:parameters :host (-> session :server :node-id)] keys-value-pairs))
(defn assoc-for-service
"Set the service parameter values at the paths specified.
(assoc-for-service {} :proxy [:a :b] 1 [:a :d] 2)
=> {:parameters {:srvice {:proxy {:a {:b 1} {:d 2}}}}}"
[session service & {:as keys-value-pairs}]
(assoc-for-prefix
session [:parameters :service service] keys-value-pairs))
(defn assoc-target-settings
"Set the settings for the specified host facility. The instance-id allows
the specification of specific instance of the facility (the default is
:default)."
[session facility instance-id values]
(assoc-for
session
[:host (-> session :server :node-id) facility (or instance-id :default)]
values))
(defn- update-for-prefix
"Update a map at the path given by the prefix and keys.
The value is set to the value return by calling f with the current
value and the given args.
(update-for-prefix {:p {:a {:b 1}}} [:p] [:a :b] + 2)
=> {:p {:a {:b 3}}}"
([session prefix keys f args]
(apply update-in session (concat prefix keys) f args)))
(defn update-for
"Update parameters at the path given by keys.
The value is set to the value return by calling f with the current
value and the given args.
(update-for {:parameters {:a {:b 1}}} [:a :b] + 2)
=> {:parameters {:a {:b 3}}}"
[session keys f & args]
(update-for-prefix session [:parameters] keys f args))
(defn update-for-target
"Update host parameters for the current target at the path given by keys.
The value is set to the value return by calling f with the current
value and the given args.
(update-for-target
{:parameters {:host {:id1 {:a {:b 1}}}}
:target-id :id1}
[:a :b] + 2)
=> {:parameters {:host {:id1 {:a {:b 3}}}}}"
[session keys f & args]
(update-for-prefix
session [:parameters :host (-> session :server :node-id)] keys f args))
(defn update-for-service
"Update serivce parameters for the pecified service at the path given by keys.
The value is set to the value return by calling f with the current
value and the given args.
(update-for-service
{:parameters {:service {:proxy {:a {:b 1}}}}}
[:proxy :a :b] + 2)
=> {:parameters {:service {:proxy {:a {:b 3}}}}}"
[session keys f & args]
(update-for-prefix session [:parameters :service] keys f args))
(defn update-target-settings
"Update the settings for the specified host facility. The instance-id allows
the specification of specific instance of the facility (the default is
:default)."
[session facility instance-id f & args]
(apply
update-for
session
[:host (-> session :server :node-id) facility (or instance-id :default)]
f args))
;;; Delayed parameter evaluation
(deftype ParameterLookup
[keys]
pallet.argument.DelayedArgument
(evaluate
[_ session]
(get-for session keys)))
(deftype ParameterLookupTarget
[keys]
pallet.argument.DelayedArgument
(evaluate
[_ session]
(get-for session (concat [:host (-> session :server :node-id)] keys))))
(defn lookup
"Lookup a parameter in a delayed manner. Use a call to this function as the
argument of a action.
This function produces an object, which causes parameter lookup when it's
toString method is called.
See also `pallet.argument`."
[& keys]
(ParameterLookup. keys))
(defn lookup-for-target
"Lookup a parameter for the target in a delayed manner. Use a call to this
function as the argument of a action. This function produces an object,
which causes parameter lookup when it's toString method is called.
See also `pallet.argument`."
[& keys]
(ParameterLookupTarget. keys))
;;; Actions
(action/def-clj-action parameters
"An action to set parameters"
[session & {:as keyvector-value-pairs}]
(assoc session
:parameters (reduce
#(apply assoc-in %1 %2)
(:parameters session)
keyvector-value-pairs)))
© 2015 - 2025 Weber Informatics LLC | Privacy Policy