#!/usr/bin/env boot ;; or `BOOT_FILE=ec2query.boot boot repl' for interactive use (set-env! :dependencies '[[amazonica "0.3.23"] [com.datomic/datomic-free "0.9.5344"]]) (require '[amazonica.aws.ec2 :as ec2] '[amazonica.core :refer [defcredential]] '[boot.cli :refer [defclifn]] '[boot.util :refer [info]] '[datomic.api :refer [db q] :as d]) (defcredential {:access-key (System/getenv "AWS_ACCESS_KEY") :secret-key (System/getenv "AWS_SECRET_KEY") :endpoint "us-east-1"}) (defn paths "Enumerate set of paths, with values at each path, for a nested map/vector." ([root] (when (or (map? root) (vector? root)) (paths [] root))) ([parent x] (cond (map? x) (mapcat (fn [[k v]] (paths (conj parent k) v)) x) (vector? x) (mapcat #(paths (conj parent %1) %2) (range) x) :else [parent]))) (defn map->tuples "Returns every path and value in the map as a set of tuples, each prefixed with the supplied id." [id m] (mapv #(conj % (get-in {id m} %)) (paths {id m}))) (def instances (reify clojure.lang.IDeref (deref [_] (->> (ec2/describe-instances) :reservations (mapcat :instances))))) (defn make-db [maps] (mapcat #(map->tuples %1 %2) (range) maps)) (def +instance-states+ #{"pending" "running" "stopping" "stopped" "shutting-down" "terminated" "rebooting"}) (defn tags->tuples [id tag-map] (when (seq tag-map) (reduce-kv #(let [e (gensym "?e")] (into %1 [[id :tags e :key %2] [id :tags e :value %3]])) [] tag-map))) (defn get-instances [db state tag-map] {:pre [(contains? +instance-states+ state)]} (q (concat '[:find ?instance-id ?public-dns :in $ ?state :where [?id :state :name ?state] [?id :instance-id ?instance-id] [?id :public-dns-name ?public-dns]] (tags->tuples '?id tag-map)) db state)) (defclifn -main "Print out instance ids and public DNS names (if available) of instances in a particular state." [s state STATE str "State of the instances to search for." t tags KEY=VALUE {str str} "Tags to filter by (optional). For example: ./ec2query.boot -s running -t System=Reporting"] (let [state (or state (do (info "No state supplied, defaulting to 'running'") "running"))] (doseq [[id dns] (get-instances (make-db @instances) state tags)] (println id dns))))