|
1 | 1 | (ns docker-clojure.variant |
2 | 2 | (:refer-clojure :exclude [compare sort]) |
3 | 3 | (:require [clojure.math.combinatorics :as combo] |
| 4 | + [clojure.spec.alpha :as s] |
| 5 | + [clojure.spec.gen.alpha :as gen] |
4 | 6 | [clojure.string :as str] |
5 | 7 | [docker-clojure.config :as cfg] |
| 8 | + [docker-clojure.core :as-alias core] |
6 | 9 | [docker-clojure.docker :as docker] |
7 | 10 | [docker-clojure.util :refer [get-or-default]])) |
8 | 11 |
|
| 12 | +(s/def ::variant-base |
| 13 | + (s/keys :req-un [::cfg/jdk-version ::cfg/base-image ::cfg/base-image-tag |
| 14 | + ::cfg/distro ::cfg/build-tool ::cfg/build-tool-version |
| 15 | + ::cfg/maintainer ::cfg/docker-tag ::cfg/architecture] |
| 16 | + :opt-un [::cfg/build-tool-versions])) |
| 17 | + |
| 18 | +(s/def ::variant |
| 19 | + (s/with-gen |
| 20 | + ::variant-base |
| 21 | + #(gen/fmap (fn [[v btv]] |
| 22 | + (if (= ::core/all (:build-tool v)) |
| 23 | + (-> v ; ::core/all implies docker tag "latest" |
| 24 | + (assoc :build-tool-version nil |
| 25 | + :build-tool-versions btv) |
| 26 | + (dissoc :distro :docker-tag :base-image-tag :base-image)) |
| 27 | + v)) |
| 28 | + (gen/tuple (s/gen ::variant-base) |
| 29 | + (gen/map (s/gen ::cfg/specific-build-tool) |
| 30 | + (s/gen ::cfg/specific-build-tool-version)))))) |
| 31 | + |
| 32 | +(s/def ::variants (s/coll-of ::variant)) |
| 33 | + |
| 34 | +(s/def ::manifest-variant |
| 35 | + (s/keys :req-un [::cfg/jdk-version ::cfg/base-image ::cfg/base-image-tag |
| 36 | + ::cfg/distro ::cfg/build-tool ::cfg/build-tool-version |
| 37 | + ::cfg/maintainer ::cfg/docker-tag] |
| 38 | + :opt-un [::cfg/build-tool-versions ::cfg/architectures])) |
| 39 | + |
9 | 40 | (defn assoc-if |
10 | 41 | [m pred k v] |
11 | 42 | (if (pred) |
|
28 | 59 | (assoc-if #(nil? (:build-tool-version base)) :build-tool-versions |
29 | 60 | cfg/build-tools)))) |
30 | 61 |
|
| 62 | +(s/def ::variant-tuple |
| 63 | + (s/tuple ::cfg/base-image ::cfg/jdk-version ::cfg/distro |
| 64 | + (s/tuple ::cfg/specific-build-tool ::cfg/specific-build-tool-version) |
| 65 | + ::cfg/architecture)) |
| 66 | + |
| 67 | +(s/fdef ->map |
| 68 | + :args (s/cat :variant-tuple ::variant-tuple) |
| 69 | + :ret ::variant |
| 70 | + :fn #(let [[base-image jdk-version distro |
| 71 | + [specific-build-tool specific-build-tool-version] |
| 72 | + architecture] (-> % :args :variant-tuple)] |
| 73 | + (println "arg:" (-> % :args :variant-tuple pr-str)) |
| 74 | + (println "ret:" (-> % :ret pr-str)) |
| 75 | + (and (= (-> % :ret :base-image) base-image) |
| 76 | + (= (-> % :ret :jdk-version) jdk-version) |
| 77 | + (= (-> % :ret :distro) distro) |
| 78 | + (= (-> % :ret :base-image-tag) |
| 79 | + (docker/base-image-tag base-image jdk-version distro)) |
| 80 | + (= (-> % :ret :build-tool last) specific-build-tool) |
| 81 | + (= (-> % :ret :build-tool-version) specific-build-tool-version) |
| 82 | + (= (-> % :ret :architecture) architecture)))) |
| 83 | + |
31 | 84 | (defn exclude? |
32 | 85 | "Returns true if the map `variant` contains every key-value pair in the map |
33 | 86 | `exclusion`. `variant` may contain additional keys that are not in |
|
68 | 121 | (= 0 (compare v1 v2))) |
69 | 122 |
|
70 | 123 | (defn equal-except-architecture? |
71 | | - [v1 v2] |
72 | | - (= 0 (compare (dissoc v1 :architecture) (dissoc v2 :architecture)))) |
| 124 | + [{arch1 :architecture :as v1} {arch2 :architecture :as v2}] |
| 125 | + (and (not= arch1 arch2) |
| 126 | + (equal? (dissoc v1 :architecture) (dissoc v2 :architecture)))) |
73 | 127 |
|
74 | 128 | (defn combinations |
75 | 129 | [base-images jdk-versions distros build-tools architectures] |
|
91 | 145 | #{} jdk-versions)) |
92 | 146 |
|
93 | 147 | (defn merge-architectures |
94 | | - [variants default-architectures] |
| 148 | + [default-architectures variants] |
95 | 149 | (->> variants |
96 | 150 | (map #(assoc % :architectures #{(:architecture %)})) |
97 | 151 | (reduce |
|
104 | 158 | (-> mav |
105 | 159 | (->> (remove #(= % matching))) |
106 | 160 | (conj (update matching :architectures conj |
107 | | - (:architecture v)))) |
| 161 | + (:architecture v)))) |
108 | 162 | (conj mav v))) |
109 | 163 | []) |
110 | 164 | (map #(if (= (:architectures %) default-architectures) |
111 | 165 | (dissoc % :architectures :architecture) |
112 | 166 | (dissoc % :architecture))) |
113 | 167 | sort)) |
| 168 | + |
| 169 | +(s/fdef merge-architectures |
| 170 | + :args (s/cat :default-architectures ::cfg/architectures |
| 171 | + :variants |
| 172 | + (s/with-gen |
| 173 | + ::variants |
| 174 | + #(gen/fmap |
| 175 | + (fn [variants] |
| 176 | + ;; duplicate variants for each architecture |
| 177 | + (mapcat (fn [variant] |
| 178 | + (map (fn [arch] |
| 179 | + (assoc variant :architecture arch)) |
| 180 | + cfg/architectures)) |
| 181 | + variants)) |
| 182 | + (s/gen (s/coll-of ::variant))))) |
| 183 | + :ret (s/coll-of ::manifest-variant) |
| 184 | + :fn #(let [ret-count (-> % :ret count) |
| 185 | + arg-variants (-> % :args :variants) |
| 186 | + should-merge? (fn [v] |
| 187 | + (some (partial equal-except-architecture? v) |
| 188 | + arg-variants)) |
| 189 | + one-per-arch (fn [c] (if (> c 0) |
| 190 | + (/ c (count cfg/architectures)) |
| 191 | + c)) |
| 192 | + num-should-merge (->> arg-variants |
| 193 | + (filter should-merge?) |
| 194 | + count |
| 195 | + one-per-arch) |
| 196 | + arg-count (- (count arg-variants) num-should-merge)] |
| 197 | + (= ret-count arg-count))) |
0 commit comments