Skip to content

Commit 1613cb0

Browse files
authored
Merge pull request #78 from OpenVoxProject/classpath_jars
Add :classpath-jars and :project-files features
2 parents c79ce48 + 1b44a38 commit 1613cb0

File tree

2 files changed

+153
-4
lines changed

2 files changed

+153
-4
lines changed

src/puppetlabs/ezbake/core.clj

Lines changed: 152 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
(def terminus-prefix "puppet/")
4545
(def additional-uberjar-checkouts-dir "target/uberjars")
4646
(def cli-defaults-filename (str shared-cli-defaults-prefix "cli-defaults.sh.erb"))
47+
(def classpath-jars-prefix "ext/classpath-jars/")
48+
(def project-files-prefix "ext/project-files/")
4749

4850
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4951
;;; Schemas
@@ -68,6 +70,23 @@
6870
(schema/optional-key :image-name) schema/Str
6971
(schema/optional-key :ports) [schema/Int]})
7072

73+
(def ClasspathJarInstallSpec
74+
{(schema/optional-key :path) schema/Str
75+
(schema/optional-key :mode) schema/Str
76+
(schema/optional-key :owner) schema/Str
77+
(schema/optional-key :group) schema/Str})
78+
79+
(def ClasspathJarSpec
80+
{:artifact schema/Symbol
81+
(schema/optional-key :install) ClasspathJarInstallSpec})
82+
83+
(def ProjectFileSpec
84+
{:file schema/Str
85+
:install {:path schema/Str
86+
(schema/optional-key :mode) schema/Str
87+
(schema/optional-key :owner) schema/Str
88+
(schema/optional-key :group) schema/Str}})
89+
7190
(def LocalProjectVars
7291
{(schema/optional-key :user) schema/Str
7392
(schema/optional-key :numeric-uid-gid) schema/Int
@@ -385,6 +404,122 @@ Additional uberjar dependencies:
385404
(for [config-file config-files]
386405
(cp-to-staging-dir config-dir config-file system-config-dir))))
387406

407+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
408+
;;; Classpath Jar Extraction
409+
410+
(schema/defn find-jar-on-classpath :- (schema/maybe File)
411+
"Given a lein project and an artifact symbol (e.g., 'org.bouncycastle/bcpkix-jdk18on),
412+
find the corresponding jar file on the resolved classpath. For artifacts where
413+
the group-id equals the artifact-id (e.g., commons-io), an unqualified symbol
414+
like 'commons-io may be used.
415+
Returns the File for the jar, or nil if not found."
416+
[lein-project artifact-symbol :- schema/Symbol]
417+
(let [group-id (or (namespace artifact-symbol) (name artifact-symbol))
418+
artifact-id (name artifact-symbol)
419+
jar-pattern (re-pattern (format "%s-.+\\.jar$"
420+
(java.util.regex.Pattern/quote artifact-id)))
421+
group-path (str/replace group-id "." "/")
422+
classifier-pattern #"-(sources|javadoc|tests)\.jar$"
423+
classpath-jars (lein-classpath/resolve-managed-dependencies
424+
:dependencies :managed-dependencies lein-project)]
425+
(->> classpath-jars
426+
(filter #(and (re-find jar-pattern (.getPath %))
427+
(str/includes? (.getPath %) group-path)
428+
(not (re-find classifier-pattern (.getPath %)))))
429+
first)))
430+
431+
(schema/defn cp-classpath-jar-to-staging
432+
"Copy a single jar from the classpath to the staging directory.
433+
Returns a map with :jar-name, :staged-path, and :install-spec (if provided).
434+
Aborts the build if the jar is not found on the classpath."
435+
[lein-project {:keys [artifact install] :as jar-spec} :- ClasspathJarSpec]
436+
(let [jar-file (find-jar-on-classpath lein-project artifact)
437+
dest-dir (fs/file staging-dir classpath-jars-prefix)]
438+
(if jar-file
439+
(do
440+
(fs/mkdirs dest-dir)
441+
(let [dest-file (fs/file dest-dir (fs/base-name jar-file))]
442+
(lein-main/info (format "Copying classpath jar %s (%s) to %s"
443+
artifact (.getName jar-file) classpath-jars-prefix))
444+
(fs/copy jar-file dest-file)
445+
{:artifact artifact
446+
:jar-name (fs/base-name jar-file)
447+
:staged-path (str classpath-jars-prefix (fs/base-name jar-file))
448+
:install-spec install}))
449+
(lein-main/abort (format "Could not find jar for artifact %s on classpath" artifact)))))
450+
451+
(schema/defn cp-classpath-jars
452+
"Copy all configured classpath jars to the staging directory.
453+
Returns a sequence of maps describing what was copied."
454+
[lein-project]
455+
(let [jar-specs (get-in lein-project [:lein-ezbake :classpath-jars] [])]
456+
(mapv (partial cp-classpath-jar-to-staging lein-project) jar-specs)))
457+
458+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
459+
;;; Staged file installation for classpath jars and project files
460+
461+
(defn- get-unique-install-dirs
462+
"Extract unique installation directories from staged file results."
463+
[staged-results]
464+
(->> staged-results
465+
(map #(get-in % [:install-spec :path]))
466+
(remove nil?)
467+
distinct))
468+
469+
(defn- generate-mkdir-cmd
470+
"Generate a mkdir install command for a directory."
471+
[dir]
472+
(format "install -d -m 0755 \"${DESTDIR}%s\"" dir))
473+
474+
(defn- generate-file-install-cmd
475+
"Generate an install command for a single staged file."
476+
[{:keys [staged-path install-spec]}]
477+
(let [{:keys [path mode owner group]} install-spec
478+
mode (or mode "0644")
479+
ownership-args (str (when owner (str " -o " owner))
480+
(when group (str " -g " group)))]
481+
(format "install -m %s%s \"%s\" \"${DESTDIR}%s/\""
482+
mode ownership-args staged-path path)))
483+
484+
(schema/defn generate-staged-file-install-commands :- [schema/Str]
485+
"Generate install commands for staged files that have :install-spec with :path.
486+
Returns a vector of shell command strings: directory creation followed by file installs."
487+
[staged-results]
488+
(let [with-install (->> staged-results
489+
(filter :install-spec)
490+
(filter #(get-in % [:install-spec :path])))
491+
install-dirs (get-unique-install-dirs with-install)
492+
mkdir-cmds (map generate-mkdir-cmd install-dirs)
493+
install-cmds (map generate-file-install-cmd with-install)]
494+
(vec (concat mkdir-cmds install-cmds))))
495+
496+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
497+
;;; Project File Installation
498+
499+
(schema/defn cp-project-file-to-staging
500+
"Copy a project file to the staging directory for installation.
501+
Returns a map with :file-name, :staged-path, and :install-spec."
502+
[{:keys [file install] :as file-spec} :- ProjectFileSpec]
503+
(let [source-file (io/file file)
504+
dest-dir (fs/file staging-dir project-files-prefix)]
505+
(if (.exists source-file)
506+
(do
507+
(fs/mkdirs dest-dir)
508+
(let [dest-file (fs/file dest-dir (fs/base-name source-file))]
509+
(lein-main/info (format "Copying project file %s to %s" file project-files-prefix))
510+
(fs/copy source-file dest-file)
511+
{:file-name (fs/base-name source-file)
512+
:staged-path (str project-files-prefix (fs/base-name source-file))
513+
:install-spec install}))
514+
(lein-main/abort (format "Could not find project file %s" file)))))
515+
516+
(schema/defn cp-project-files
517+
"Copy all configured project files to the staging directory.
518+
Returns a sequence of maps describing what was copied."
519+
[lein-project]
520+
(let [file-specs (get-in lein-project [:lein-ezbake :project-files] [])]
521+
(mapv cp-project-file-to-staging file-specs)))
522+
388523
(defn get-real-name
389524
[project-name]
390525
(str/replace-first project-name #"^pe-" ""))
@@ -579,7 +714,7 @@ Additional uberjar dependencies:
579714
"Construct the map of variables to pass on to the ezbake.rb template"
580715
[lein-project build-target
581716
config-files system-config-files cli-app-files bin-files terminus-files
582-
upstream-ezbake-configs additional-uberjars timestamp]
717+
upstream-ezbake-configs additional-uberjars classpath-jar-results project-file-results timestamp]
583718
(let [termini (for [[name version files] terminus-files]
584719
{:name (as-ruby-literal name)
585720
:version (as-ruby-literal version)
@@ -592,6 +727,12 @@ Additional uberjar dependencies:
592727
platform
593728
name))
594729
val->ruby #(as-ruby-literal (get-val %1 %2))
730+
all-staged-results (concat classpath-jar-results project-file-results)
731+
all-install-cmds (generate-staged-file-install-commands all-staged-results)
732+
;; For :install, we need to append classpath jar commands to the upstream commands
733+
val->ruby-install (fn [platform]
734+
(as-ruby-literal
735+
(concat (get-val platform :install) all-install-cmds)))
595736
get-local #(get-local-ezbake-var lein-project %1 %2)
596737
local->ruby #(as-ruby-literal (get-local %1 %2))]
597738
{:project (as-ruby-literal (:name lein-project))
@@ -622,7 +763,7 @@ Additional uberjar dependencies:
622763
:debian-prerm (val->ruby :debian :prerm)
623764
:debian-postinst (val->ruby :debian :postinst)
624765
:debian-postinst-install (val->ruby :debian :postinst-install)
625-
:debian-install (val->ruby :debian :install)
766+
:debian-install (val->ruby-install :debian)
626767
:debian-pre-start-action (val->ruby :debian :pre-start-action)
627768
:debian-post-start-action (val->ruby :debian :post-start-action)
628769
:debian-activated-triggers (local->ruby :debian-activated-triggers [])
@@ -635,7 +776,7 @@ Additional uberjar dependencies:
635776
:redhat-preinst (val->ruby :redhat :preinst)
636777
:redhat-postinst (val->ruby :redhat :postinst)
637778
:redhat-postinst-install (val->ruby :redhat :postinst-install)
638-
:redhat-install (val->ruby :redhat :install)
779+
:redhat-install (val->ruby-install :redhat)
639780
:redhat-pre-start-action (val->ruby :redhat :pre-start-action)
640781
:redhat-post-start-action (val->ruby :redhat :post-start-action)
641782
:terminus-map termini
@@ -687,6 +828,8 @@ Additional uberjar dependencies:
687828
terminus-files
688829
upstream-ezbake-configs
689830
additional-uberjars
831+
classpath-jar-results
832+
project-file-results
690833
timestamp]
691834
(lein-main/info "generating ezbake config file")
692835
(spit
@@ -702,6 +845,8 @@ Additional uberjar dependencies:
702845
terminus-files
703846
upstream-ezbake-configs
704847
additional-uberjars
848+
classpath-jar-results
849+
project-file-results
705850
timestamp))))
706851

707852
(defn generate-project-data-yaml
@@ -939,6 +1084,8 @@ Additional uberjar dependencies:
9391084
upstream-ezbake-configs (get-upstream-ezbake-configs lein-project)
9401085
additional-uberjar-info (build-additional-uberjars! lein-project)
9411086
additional-uberjar-filenames (map #(fs/base-name (:uberjar %)) additional-uberjar-info)
1087+
classpath-jar-results (cp-classpath-jars lein-project)
1088+
project-file-results (cp-project-files lein-project)
9421089
timestamp (get-timestamp-string)]
9431090
(cp-shared-files non-excluded-deps get-cli-defaults-files-in)
9441091
(cp-shared-files non-excluded-deps get-build-scripts-files-in)
@@ -965,6 +1112,8 @@ Additional uberjar dependencies:
9651112
terminus-files
9661113
upstream-ezbake-configs
9671114
additional-uberjar-filenames
1115+
classpath-jar-results
1116+
project-file-results
9681117
timestamp)
9691118
(let [project-w-deployed-version (assoc lein-project :version deployed-version)]
9701119
(generate-project-data-yaml project-w-deployed-version build-target additional-uberjar-filenames)

test/unit/puppetlabs/ezbake/core_test.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,5 +90,5 @@
9090
(clojure.data/diff
9191
expected
9292
(core/make-template-map dummy-project "dummy-build-target"
93-
[] [] [] [] [] {} []
93+
[] [] [] [] [] {} [] [] []
9494
(core/get-timestamp-string))))))))

0 commit comments

Comments
 (0)