From 8fbd0c0e3aa75d9ea372cdbbd1c1e522cde65ec0 Mon Sep 17 00:00:00 2001 From: Hugo Duncan Date: Fri, 5 Apr 2013 20:56:02 -0400 Subject: [PATCH 01/12] Use lein as build tool and deploy to clojars --- .gitignore | 20 ++- README.md | 94 +++++++++++--- dev-resources/logback-test.xml | 117 ++++++++++++++++++ doc-src/FOOTER.md | 10 ++ doc-src/USAGE.md | 88 +++++++++++++ pallet.clj | 13 ++ profiles.clj | 29 +++++ project.clj | 16 +++ .../pallet_crate/postgres_crate/meta.edn | 8 ++ 9 files changed, 375 insertions(+), 20 deletions(-) create mode 100644 dev-resources/logback-test.xml create mode 100644 doc-src/FOOTER.md create mode 100644 doc-src/USAGE.md create mode 100644 pallet.clj create mode 100644 profiles.clj create mode 100644 project.clj create mode 100644 resources/pallet_crate/postgres_crate/meta.edn diff --git a/.gitignore b/.gitignore index 52d4c3e..eea0e79 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,16 @@ -target -doc -checkout -logs +/target +/lib +/classes +/checkouts +/logs +/doc +doc-src/VERSIONS.md +doc-src/INTRO.md +pom.xml +pom.xml.asc +*.jar +*.class +.lein-deps-sum +.lein-failures +.lein-plugins +.lein-repl-history diff --git a/README.md b/README.md index c05e65a..2815d32 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,85 @@ -# Pallet crate for postgres +[Repository](https://github.com/pallet/postgres-crate) · +[Issues](https://github.com/pallet/postgres-crate/issues) · +[API docs](http://palletops.com/postgres-crate/0.8/api) · +[Annotated source](http://palletops.com/postgres-crate/0.8/annotated/uberdoc.html) · +[Release Notes](https://github.com/pallet/postgres-crate/blob/develop/ReleaseNotes.md) + +A Pallet crate to install and configure postgres. + +### Dependency Information + +```clj +:dependencies [[com.palletops/postgres-crate "0.8.0-alpha.1"]] +``` + +### Releases + + + + + + + + + + + + + + + + + + + + + + + +
PalletCrate VersionRepoGroupId
0.8.0-beta.60.8.0-alpha.1clojarscom.palletopsRelease NotesSource
0.7.20.7.0-beta.2clojarscom.palletopsRelease NotesSource
+ +## Usage + +The `server-spec` function provides a convenient pallet server spec for +postgres. It takes a single map as an argument, specifying configuration +choices, as described below for the `settings` function. You can use this +in your own group or server specs in the :extends clause. + +```clj +(require '[pallet/crate/postgres :as postgres]) +(group-spec my-postgres-group + :extends [(postgres/server-spec {})]) +``` + +While `server-spec` provides an all-in-one function, you can use the individual +plan functions as you see fit. + +The `settings` function provides a plan function that should be called in the +`:settings` phase. The function puts the configuration options into the pallet +session, where they can be found by the other crate functions, or by other +crates wanting to interact with postgres. + +The `install` function is responsible for actually installing postgres. + +The `configure` function writes the postgres configuration file, using the form +passed to the :config key in the `settings` function. -This a crate to install and run postgres via [Pallet](http://pallet.github.com/pallet). - -[Release Notes](ReleaseNotes.md) - -## Server Spec - -The postgres crate defines the `postgres` function, that takes a settings map -and returns a server-spec for installing postgres. ## Settings The postgres crate uses the following settings: -* `:version` - a string to specify the point version of PostgreSQL (e.g., `"9.1"`). The default is the version provided by the system's packaging system +* `:version` + a string to specify the point version of PostgreSQL (e.g., `"9.1"`). The + default is the version provided by the system's packaging system * `:components` - a set of one or more recognized keywords. The set of every component is `#{:server :libs :client}`. + a set of one or more recognized keywords. The set of every component is + `#{:server :libs :client}`. * `:strategy` - allows override of the install strategy (`:packages`, `:package-source`, or `:rpm`) + allows override of the install strategy (`:packages`, `:package-source`, or + `:rpm`) * `:packages` the packages that are used to install @@ -29,7 +88,9 @@ The postgres crate uses the following settings: a non-default package source for the packages * `:rpm` - takes a map of [`remote-file` options](http://palletops.com/pallet/api/0.7/pallet.action.remote-file.html) specifying an RPM file to install + takes a map of + [`remote-file` options](http://palletops.com/pallet/api/0.7/pallet.action.remote-file.html) + specifying an RPM file to install * `:default-cluster-name` name of the default cluster created by the installer @@ -44,7 +105,8 @@ The postgres crate uses the following settings: path to `postgresql.conf` * `:has-pg-wrapper` - boolean flag for availability of a wrapper allowing command execution against a specified cluster. + boolean flag for availability of a wrapper allowing command execution against + a specified cluster. * `:has-multicluster-service` boolean flag specifying whether the init service is multi-cluster capable. @@ -74,4 +136,4 @@ The postgres crate uses the following settings: Licensed under [EPL](http://www.eclipse.org/legal/epl-v10.html) -Copyright 2010, 2011, 2012 Hugo Duncan. +Copyright 2013 Hugo Duncan. diff --git a/dev-resources/logback-test.xml b/dev-resources/logback-test.xml new file mode 100644 index 0000000..a32bc4b --- /dev/null +++ b/dev-resources/logback-test.xml @@ -0,0 +1,117 @@ + + + + + + INFO + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - %msg%n + + + + + logs/jclouds-compute.log + + logs/old/jclouds-compute.%d{yyyy-MM-dd}.log + 3 + + + %date %level [%thread] %logger{10} [%file:%line] %msg%n + + + + + logs/jclouds-wire.log + + logs/old/jclouds-wire.%d{yyyy-MM-dd}.log + 3 + + + %date %level [%thread] %logger{10} [%file:%line] %msg%n + + + + + logs/pallet.log + false + + logs/old/pallet.%d{yyyy-MM-dd}.log + 3 + + + %date %level [%thread] %logger{10} %msg%n + + + + + logs/vmfest.log + + logs/old/vmfest.%d{yyyy-MM-dd}.log + 3 + + + %date %level [%thread] %logger{10} %msg%n + + + + + + target + unspecified + + + + logs/target-${target}.log + false + + %msg%n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc-src/FOOTER.md b/doc-src/FOOTER.md new file mode 100644 index 0000000..fb3ffd9 --- /dev/null +++ b/doc-src/FOOTER.md @@ -0,0 +1,10 @@ +## Support + +[On the group](http://groups.google.com/group/pallet-clj), or +[#pallet](http://webchat.freenode.net/?channels=#pallet) on freenode irc. + +## License + +Licensed under [EPL](http://www.eclipse.org/legal/epl-v10.html) + +Copyright 2013 Hugo Duncan. diff --git a/doc-src/USAGE.md b/doc-src/USAGE.md new file mode 100644 index 0000000..1b8ddca --- /dev/null +++ b/doc-src/USAGE.md @@ -0,0 +1,88 @@ +## Usage + +The `server-spec` function provides a convenient pallet server spec for +postgres. It takes a single map as an argument, specifying configuration +choices, as described below for the `settings` function. You can use this +in your own group or server specs in the :extends clause. + +```clj +(require '[pallet/crate/postgres :as postgres]) +(group-spec my-postgres-group + :extends [(postgres/server-spec {})]) +``` + +While `server-spec` provides an all-in-one function, you can use the individual +plan functions as you see fit. + +The `settings` function provides a plan function that should be called in the +`:settings` phase. The function puts the configuration options into the pallet +session, where they can be found by the other crate functions, or by other +crates wanting to interact with postgres. + +The `install` function is responsible for actually installing postgres. + +The `configure` function writes the postgres configuration file, using the form +passed to the :config key in the `settings` function. + + +## Settings + +The postgres crate uses the following settings: + +* `:version` + a string to specify the point version of PostgreSQL (e.g., `"9.1"`). The + default is the version provided by the system's packaging system + +* `:components` + a set of one or more recognized keywords. The set of every component is + `#{:server :libs :client}`. + +* `:strategy` + allows override of the install strategy (`:packages`, `:package-source`, or + `:rpm`) + +* `:packages` + the packages that are used to install + +* `:package-source` + a non-default package source for the packages + +* `:rpm` + takes a map of + [`remote-file` options](http://palletops.com/pallet/api/0.7/pallet.action.remote-file.html) + specifying an RPM file to install + +* `:default-cluster-name` + name of the default cluster created by the installer + +* `:bin` + path to binaries + +* `:owner` + unix owner for Postgres files + +* `:postgresql_file` + path to `postgresql.conf` + +* `:has-pg-wrapper` + boolean flag for availability of a wrapper allowing command execution against + a specified cluster. + +* `:has-multicluster-service` + boolean flag specifying whether the init service is multi-cluster capable. + +* `:initdb-via` + whether to use the initdb (`:initdb`), or service (`:service`) to run initdb + +* `:options` + A map of options: + - `:data_directory` + path to storage location + - `:hba_file` + path to `pg_hba.conf` location + - `:ident_file` + path to `pg_ident.conf` location + - `:external_pid_file` + path to pid file + - `:unix_socket_directory` + path to directory for unix sockets diff --git a/pallet.clj b/pallet.clj new file mode 100644 index 0000000..06653cc --- /dev/null +++ b/pallet.clj @@ -0,0 +1,13 @@ +;;; Pallet project configuration file + +(require + '[pallet.crate.postgres-test + :refer [postgres-test-spec]] + '[pallet.crates.test-nodes :refer [node-specs]]) + +(defproject postgres-crate + :provider node-specs ; supported pallet nodes + :groups [(group-spec "postgres-test" + :extends [with-automated-admin-user + postgres-test-spec] + :roles #{:live-test :default :postgres})]) diff --git a/profiles.clj b/profiles.clj new file mode 100644 index 0000000..6a4635f --- /dev/null +++ b/profiles.clj @@ -0,0 +1,29 @@ +{:dev + {:dependencies [[com.palletops/pallet "0.8.0-beta.7" :classifier "tests"] + [com.palletops/crates "0.1.0"] + [ch.qos.logback/logback-classic "1.0.9"]] + :plugins [[lein-set-version "0.3.0"] + [lein-resource "0.3.2"] + [com.palletops/pallet-lein "0.6.0-beta.8"]] + :aliases {"live-test-up" + ["pallet" "up" + "--phases" "install,configure,test" + "--selector" "live-test"] + "live-test-down" ["pallet" "down" "--selector" "live-test"] + "live-test" ["do" "live-test-up," "live-test-down"]} + :test-selectors {:default (complement :live-test) + :live-test :live-test + :all (constantly true)}} + :doc {:dependencies [[com.palletops/pallet-codox "0.1.0"]] + :plugins [[codox/codox.leiningen "0.6.4"] + [lein-marginalia "0.7.1"]] + :codox {:writer codox-md.writer/write-docs + :output-dir "doc/0.8/api" + :src-dir-uri "https://github.com/pallet/postgres-crate/blob/develop" + :src-linenum-anchor-prefix "L"} + :aliases {"marg" ["marg" "-d" "doc/0.8/annotated"] + "codox" ["doc"] + "doc" ["do" "codox," "marg"]}} + :release + {:set-version + {:updates [{:path "README.md" :no-snapshot true}]}}} diff --git a/project.clj b/project.clj new file mode 100644 index 0000000..1e7be14 --- /dev/null +++ b/project.clj @@ -0,0 +1,16 @@ +(defproject com.palletops/postgres-crate "0.8.0-SNAPSHOT" + :description "Pallet crate to install, configure and use postgres" + :url "http://palletops.com" + :license {:name "Eclipse Public License" + :url "http://www.eclipse.org/legal/epl-v10.html"} + :scm {:url "git@github.com:pallet/runit-crate.git"} + + :dependencies [[org.clojure/clojure "1.4.0"] + [com.palletops/pallet "0.8.0-beta.7"]] + :repositories {"sonatype" + {:url "https://oss.sonatype.org/content/repositories/releases/" + :snapshots false}} + :resource {:resource-paths ["doc-src"] + :target-path "target/classes/pallet_crate/postgres_crate/" + :includes [#"doc-src/USAGE.*"]} + :prep-tasks ["resource" "crate-doc"]) diff --git a/resources/pallet_crate/postgres_crate/meta.edn b/resources/pallet_crate/postgres_crate/meta.edn new file mode 100644 index 0000000..567ce35 --- /dev/null +++ b/resources/pallet_crate/postgres_crate/meta.edn @@ -0,0 +1,8 @@ +{:header "postgres" + :title "A Pallet crate to install and configure postgres." + :git-repo "https://github.com/pallet/postgres-crate" + :api-docs "http://palletops.com/postgres-crate/0.8/api" + :annotated-docs "http://palletops.com/postgres-crate/0.8/annotated/uberdoc.html" + :tag-prefix "" + :versions [{:pallet "0.8.0-beta.6" :version "0.8.0-alpha.1"} + {:pallet "0.7.2" :version "0.7.0-beta.2"}]} From 5d8841edf57a8a32fbbfdf55a5ae7554a79134e9 Mon Sep 17 00:00:00 2001 From: Hugo Duncan Date: Sat, 6 Apr 2013 11:52:08 -0400 Subject: [PATCH 02/12] Initial port to pallet 0.8.0 --- pallet.clj | 6 +- src/pallet/crate/postgres.clj | 727 +++++++++++++--------------- test/pallet/crate/postgres_test.clj | 106 ++-- 3 files changed, 408 insertions(+), 431 deletions(-) diff --git a/pallet.clj b/pallet.clj index 06653cc..f94ef48 100644 --- a/pallet.clj +++ b/pallet.clj @@ -2,12 +2,12 @@ (require '[pallet.crate.postgres-test - :refer [postgres-test-spec]] + :refer [test-server-spec]] '[pallet.crates.test-nodes :refer [node-specs]]) (defproject postgres-crate :provider node-specs ; supported pallet nodes - :groups [(group-spec "postgres-test" + :groups [(group-spec "pgtest" :extends [with-automated-admin-user - postgres-test-spec] + test-server-spec] :roles #{:live-test :default :postgres})]) diff --git a/src/pallet/crate/postgres.clj b/src/pallet/crate/postgres.clj index 8574486..8aa30d3 100644 --- a/src/pallet/crate/postgres.clj +++ b/src/pallet/crate/postgres.clj @@ -39,34 +39,30 @@ Links: " (:require [pallet.action :as action] - [pallet.action.directory :as directory] - [pallet.action.exec-script :as exec-script] - [pallet.action.file :as file] - [pallet.action.package :as package] - [pallet.action.package.debian-backports :as debian-backports] - [pallet.action.remote-file :as remote-file] - [pallet.action.service :as service] + [pallet.actions :refer [add-rpm content-options directory exec-checked-script + exec-script file package package-manager + package-source remote-file] + :as actions] + [pallet.api :refer [plan-fn] :as api] + [pallet.compute :as compute] + [pallet.core.session :refer [session]] + [pallet.crate :refer [assoc-settings defplan get-settings os-family + update-settings]] + [pallet.crate-install :as crate-install] [pallet.crate.etc-default :as etc-default] - [pallet.parameter :as parameter] [pallet.script.lib :as lib] - [pallet.session :as session] [pallet.stevedore :as stevedore] - [pallet.thread-expr :as thread-expr] + [pallet.utils :refer [apply-map]] [clojure.tools.logging :as logging] [clojure.string :as string]) (:use - pallet.thread-expr - [pallet.action.package :only [package package-manager package-source]] - [pallet.action.package.debian-backports :only [debian-backports-repository]] - [pallet.core :only [server-spec]] - [pallet.phase :only [phase-fn]] + [pallet.crate.package.debian-backports :only [add-debian-backports]] [pallet.script :only [defscript]] [pallet.version-dispatch - :only [defmulti-version-crate defmulti-version defmulti-os-crate - multi-version-session-method multi-version-method - multi-os-session-method]] - [pallet.versions :only [as-version-vector version-string]] - [slingshot.slingshot :only [throw+]])) + :only [defmethod-version defmulti-version defmulti-version-plan + defmethod-version-plan defmulti-version-plan os-map] + :as version-dispatch] + [pallet.versions :only [as-version-vector version-string]])) (def ^{:private true} pallet-cfg-preamble "# This file was auto-generated by Pallet. Do not edit it manually unless you @@ -78,20 +74,21 @@ Links: postgresql-config-changed-flag "postgresql-config") ;;; Default Postgres package version -(defmulti-os-crate postgres-package-version [session]) - -(multi-os-session-method - postgres-package-version {:os :linux} - [os os-version session] - [8]) - -(multi-os-session-method - postgres-package-version {:os :ubuntu :os-version [12]} - [os os-version session] - [9 1]) +(def postgres-package-version + (atom ; allow for open extension + (os-map + {{:os :linux} [8] + {:os :ubuntu :os-version [12]} [9 1]}))) + +;;; TODO temporary until next pallet beta +(defn os-map-lookup + [os-map] + (get os-map {:os (pallet.crate/os-family) + :os-version (pallet.versions/as-version-vector + (pallet.crate/os-version))})) ;;; Install strategy -(defmulti-version-crate install-strategy [version session settings]) +(defmulti-version-plan install-strategy [version settings]) (def ^{:dynamic true} *pgdg-repo-versions* {"9.0" "9.0-5" @@ -107,24 +104,24 @@ Links: (string/replace version "." "") (*pgdg-repo-versions* version))) -(multi-version-session-method +(defmethod-version-plan install-strategy {:os :rh-base} - [os os-version version session settings] + [os os-version version settings] (-> (cond - (:strategy settings) settings - (:package-source settings) (assoc settings :strategy :package-source) - :else (let [default-version (postgres-package-version session) + (:install-strategy settings) settings + (:package-source settings) (assoc settings :install-strategy :package-source) + :else (let [default-version (os-map-lookup @postgres-package-version) target-version (:version settings)] (if (= (version-string default-version) target-version) (assoc settings - :strategy :packages + :install-strategy :packages :packages (map #(str "postgresql-" (name %)) (:components settings #{:server :libs})) :layout :rh-base) (assoc settings - :strategy :rpm-repo + :install-strategy :rpm-repo :rpm {:name "pgdg.rpm" :url (pgdg-url (version-string version) (if (= os :rhel) "redhat" os))} @@ -134,99 +131,97 @@ Links: "-" (name %)) (:components settings #{:server :libs})) :layout :pgdg)))))) - -(multi-version-session-method - install-strategy {:os :debian} - [os os-version version session settings] - (-> - (cond - (:strategy settings) settings - (:package-source settings) (assoc settings :strategy :package-source) - :else (let [default-version (postgres-package-version session) - target-version (:version settings)] - (if (= (version-string default-version) target-version) - (assoc settings - :strategy :packages - :packages ["postgresql"] - :layout :debian-base) - (assoc settings - :strategy :package-source - :package-source (debian-backports-repository) - :packages ["libpq5" (str "postgresql-" target-version)] - :layout :debian-base)))))) - -(multi-version-session-method +;; TODO +;; (defmethod-version-plan +;; install-strategy {:os :debian} +;; [os os-version version settings] +;; (-> +;; (cond +;; (:install-strategy settings) settings +;; (:package-source settings) (assoc settings :install-strategy :package-source) +;; :else (let [default-version (os-map-lookup @postgres-package-version) +;; target-version (:version settings)] +;; (if (= (version-string default-version) target-version) +;; (assoc settings +;; :install-strategy :packages +;; :packages ["postgresql"] +;; :layout :debian-base) +;; (assoc settings +;; :install-strategy :package-source +;; ; :package-source (debian-backports-repository) +;; :packages ["libpq5" (str "postgresql-" target-version)] +;; :layout :debian-base)))))) + +(defmethod-version-plan install-strategy {:os :ubuntu} - [os os-version version session settings] + [os os-version version settings] (-> (cond - (:strategy settings) settings - (:package-source settings) (assoc settings :strategy :package-source) - :else (let [default-version (postgres-package-version session) + (:install-strategy settings) settings + (:package-source settings) (assoc settings :install-strategy :package-source) + :else (let [default-version (os-map-lookup @postgres-package-version) target-version (:version settings)] (if (= (version-string default-version) target-version) (assoc settings - :strategy :packages + :install-strategy :packages :packages ["postgresql"] :layout :debian-base) (assoc settings - :strategy :package-source + :install-strategy :package-source :package-source {:name "Martin Pitt backports" :aptitude {:url "ppa:pitti/postgresql"} :apt {:url "ppa:pitti/postgresql"}} :packages [(str "postgresql-" target-version)] :layout :debian-base)))))) -(multi-version-session-method +(defmethod-version-plan install-strategy {:os :arch} - [os os-version version session settings] + [os os-version version settings] (-> (cond - (:strategy settings) settings - (:package-source settings) (assoc settings :strategy :package-source) - :else (let [default-version (postgres-package-version session) + (:install-strategy settings) settings + (:package-source settings) (assoc settings :install-strategy :package-source) + :else (let [default-version (os-map-lookup @postgres-package-version) target-version (:version settings)] (if (= (version-string default-version) target-version) (assoc settings - :strategy :packages + :install-strategy :packages :packages ["postgresql"] :layout :arch) - (throw+ - {:reason :no-install-strategy} - "No install strategy for postgres %s on %s %s" - version os os-version)))))) + (throw + (ex-info + (format "No install strategy for postgres %s on %s %s" + version os os-version) + {:reason :no-install-strategy + :version version :os os :os-version os-version}))))))) ;;; Dispatch to install strategy -(defmulti install-method (fn [session settings] (:strategy settings))) - -(defmethod install-method :packages [session settings] - (reduce package session (:packages settings))) - -(defmethod install-method :package-source - [session {:keys [package-source packages] :as settings}] - (-> - session - (apply-map-> package/package-source (:name package-source) package-source) - (package/package-manager :update) - (when-> (= package-source :debian-backports) - (debian-backports/add-debian-backports) - (package/package-manager :update)) - (for-> [pkg packages] (package pkg)))) - -(defmethod install-method :rpm - [session {:keys [rpm] :as settings}] - (-> - session - (action/with-precedence {:always-before `package/package} - (apply-map-> package/add-rpm (:name rpm) rpm)))) - -(defmethod install-method :rpm-repo - [session {:keys [rpm packages] :as settings}] - (-> - session - (action/with-precedence {:always-before `package/package} - (apply-map-> package/add-rpm (:name rpm) rpm)) - (for-> [pkg packages] (package pkg)))) +;; (defmulti install-method (fn [session settings] (:strategy settings))) + +;; (defmethod install-method :packages [session settings] +;; (reduce package session (:packages settings))) + +;; (defmethod install-method :package-source +;; [session {:keys [package-source packages] :as settings}] +;; (apply-map package-source (:name package-source) package-source) +;; (package-manager :update) +;; (when (= package-source :debian-backports) +;; (add-debian-backports) +;; (package-manager :update)) +;; (doseq [pkg packages] +;; (package pkg))) + +;; (defmethod install-method :rpm +;; [session {:keys [rpm] :as settings}] +;; (action/with-action-options {:always-before `package/package} +;; (apply-map add-rpm (:name rpm) rpm))) + +;; (defmethod install-method :rpm-repo +;; [session {:keys [rpm packages] :as settings}] +;; (action/with-action-options {:always-before `package/package} +;; (apply-map add-rpm (:name rpm) rpm)) +;; (doseq [pkg packages] +;; (package pkg))) ;;; Default settings @@ -268,10 +263,10 @@ Links: (defmulti default-settings "Determine the default settings for the specified " - (fn [session os-family layout settings] + (fn [os-family layout settings] layout)) -(defn base-settings [session] +(defn base-settings [] {:service "postgresql" :owner "postgres" :initdb-via :initdb @@ -279,10 +274,10 @@ Links: "/postgresql.pid")}}) (defmethod default-settings :debian-base - [session os-family layout settings] + [os-family layout settings] (let [version (:version settings)] (merge-settings - (base-settings session) + (base-settings) {:default-cluster-name "main" :bin (format "/usr/lib/postgresql/%s/bin/" version) :share (format "/usr/lib/postgresql/%s/share/" version) @@ -299,10 +294,10 @@ Links: :unix_socket_directory "/var/run/postgresql"}}))) (defmethod default-settings :rh-base - [session os-family layout settings] + [os-family layout settings] (let [version (:version settings)] (merge-settings - (base-settings session) + (base-settings) {:default-cluster-name "data" :wal_directory (format "/var/lib/pgsql/%s/%%s/archive" version) :postgresql_file (format "/var/lib/pgsql/%s/%%s/postgresql.conf" version) @@ -313,11 +308,11 @@ Links: :external_pid_file (format "/var/run/postmaster-%s-%%s.pid" version)}}))) (defmethod default-settings :pgdg - [session os-family package-source settings] + [os-family package-source settings] (let [version (:version settings)] (merge-settings - (base-settings session) - (default-settings session os-family :rh-base settings) + (base-settings) + (default-settings os-family :rh-base settings) {:bin (format "/usr/pgsql-%s/bin/" version) :share (format "/usr/pgsql-%s/share/" version) :default-cluster-name "data" @@ -332,10 +327,10 @@ Links: :ident_file (format "/var/lib/pgsql/%s/%%s/pg_ident.conf" version)}}))) (defmethod default-settings :arch - [session os-family package-source settings] + [os-family package-source settings] (let [version (:version settings)] (merge-settings - (base-settings session) + (base-settings) {:components [] :default-cluster-name "data" :initdb-via :initdb @@ -396,28 +391,30 @@ Links: :address :auth-method :auth-options] record)) - (throw+ - {:type :postgres-invalid-hba-record - :message + (throw + (ex-info (format "The fifth item in %s does not appear to be an IP mask or auth method." - (pr-str record))})))) - (throw+ - {:type :postgres-invalid-hba-record - :message (format - "The first item in %s is not a valid connection type." - (name record))}))) + (pr-str record)) + {:type :postgres-invalid-hba-record}))))) + (throw + (ex-info + (format + "The first item in %s is not a valid connection type." + (name record))) + {:type :postgres-invalid-hba-record}))) (defn- record-to-map "Takes a record given as a map or vector, and turns it into the map version." [record] (cond - (map? record) record - (vector? record) (vector-to-map record) - :else - (throw+ - {:type :postgres-invalid-hba-record - :message (format "The record %s must be a vector or map." (name record))}))) + (map? record) record + (vector? record) (vector-to-map record) + :else + (throw + (ex-info + (format "The record %s must be a vector or map." (name record)) + {:type :postgres-invalid-hba-record})))) (defn- format-auth-options "Given the auth-options map, returns a string suitable for inserting into the @@ -461,13 +458,14 @@ Links: (or (= value true) (= value false)) (str value) :else - (throw+ - {:type :postgres-invalid-parameter - :message (format - (str - "Parameters must be numbers, strings, or vectors of such. " - "Invalid value %s") (pr-str value)) - :value value}))) + (throw + (ex-info + (format + (str + "Parameters must be numbers, strings, or vectors of such. " + "Invalid value %s") (pr-str value)) + {:type :postgres-invalid-parameter + :value value})))) (defn- format-parameter "Given a key/value pair in a vector, formats it suitably for the @@ -551,61 +549,52 @@ Links: (defn settings-for-cluster "Returns the settings for the specified cluster" - [session cluster & {:keys [instance]}] + [cluster {:keys [instance-id] :as options}] (get-in - (parameter/get-target-settings session :postgresql instance) + (get-settings :postgresql options) [:clusters (keyword cluster)])) (defn check-settings "Check that settings are valid" - [session settings cluster-settings cluster & keys] - (let [error-fn (fn [session ^String message] + [settings cluster-settings cluster & keys] + (let [error-fn (fn [^String message] (logging/error (format message cluster settings)) - (assert false) - session) + (assert false)) missing-keys (remove #(get-in cluster-settings %) keys)] - (-> - session - (thread-expr/when-> - (not settings) + (when (not settings) (error-fn "No settings found %s %s")) - (thread-expr/when-> - (not cluster-settings) + (when (not cluster-settings) (error-fn "No cluster settings found %s %s")) - (thread-expr/when-> - (seq missing-keys) - (error-fn (format "Missing keys %s %%s %%s" (vec missing-keys))))))) + (when (seq missing-keys) + (error-fn (format "Missing keys %s %%s %%s" (vec missing-keys)))))) (defn conf-file "Generates a postgresql configuration file" - [session file-keys values-kw formatter & {:keys [instance cluster]}] - (let [settings (parameter/get-target-settings session :postgresql instance) + [file-keys values-kw formatter {:keys [instance-id cluster] :as options}] + (let [settings (get-settings :postgresql options) cluster (or cluster (:default-cluster-name settings)) - cluster-settings (settings-for-cluster - session cluster :instance instance) + cluster-settings (settings-for-cluster cluster options) conf-path (get-in cluster-settings file-keys) hba-contents (apply str pallet-cfg-preamble (map formatter (values-kw cluster-settings)))] - (-> - session - (check-settings settings cluster-settings cluster file-keys) - (directory/directory - (stevedore/script @(~lib/dirname ~conf-path)) - :owner (:owner settings "postgres") :mode "0700" :path true) - (remote-file/remote-file - conf-path - :content hba-contents - :literal true - :flag-on-changed postgresql-config-changed-flag - :owner (:owner settings))))) + (check-settings settings cluster-settings cluster file-keys) + (directory + (stevedore/script @(~lib/dirname ~conf-path)) + :owner (:owner settings "postgres") :mode "0700" :path true) + (remote-file + conf-path + :content hba-contents + :literal true + :flag-on-changed postgresql-config-changed-flag + :owner (:owner settings)))) (defn default-cluster-name "Returns the default cluster name" - [session & {:keys [instance]}] - (let [settings (parameter/get-target-settings session :postgresql instance)] + [& {:keys [instance-id] :as options}] + (let [settings (get-settings :postgresql options)] (:default-cluster-name settings))) -;;; Crate functions +;;; # Crate functions (defn settings-map "Build a settings map for postgresql. @@ -631,65 +620,61 @@ Links: `settings`. Options: - - instance Specify the postgres instance to use for the cluster + - instance-id Specify the postgres instance to use for the cluster - variant Specify a variant for the cluster. Current options are :hot-standby-master and :hot-standby-replica For variant :hot-standby-replica, you will need to pass :primary_conninfo in the `settings-map`" - [session cluster-name settings-map & {:keys [instance variant]}] - (let [settings (parameter/get-target-settings session :postgresql instance) + [cluster-name settings-map & {:keys [instance-id variant] :as options}] + (let [settings (get-settings :postgresql options) settings (cluster-settings-with-defaults cluster-name settings-map settings) settings (case variant :hot-standby-master (hot-standby-master settings) :hot-standby-replica (hot-standby-replica settings) settings)] - (parameter/update-target-settings - session :postgresql instance + (update-settings + :postgresql instance-id assoc-in [:clusters (keyword cluster-name)] settings))) -(defn postgres-settings +(defn base-distribution + "Base distribution of the target-node." + [] + (compute/base-distribution (-> (session) :server :image))) + +(defn settings "Add postgresql settings to the session map." - [session - {:keys [version] - :or {version (version-string (postgres-package-version session))} + [{:keys [version] + :or {version (version-string (os-map-lookup @postgres-package-version))} :as settings} - & {:keys [instance]}] + & {:keys [instance-id] :as options}] (let [settings (assoc settings :version version) - settings (install-strategy session version settings) + settings (install-strategy version settings) settings (merge-settings (default-settings - session - (session/base-distribution session) + (base-distribution) (:layout settings) settings) settings) - old-settings (parameter/get-target-settings - session :postgresql instance nil)] + old-settings (get-settings :postgresql options)] (logging/debugf "Postgresql Settings %s" settings) - (-> - session - (parameter/assoc-target-settings - :postgresql instance - (assoc settings :clusters (:clusters old-settings))) - (thread-expr/when-let-> - [cluster-name (:default-cluster-name settings)] - (cluster-settings cluster-name {} :instance instance))))) + (assoc-settings + :postgresql (assoc settings :clusters (:clusters old-settings)) + options) + (when-let [cluster-name (:default-cluster-name settings)] + (cluster-settings cluster-name {} :instance-id instance-id)))) -(defn install-postgres +;;; ## Install +(defn install "Install postgres." - [session & {:keys [instance]}] - (let [os-family (session/os-family session) - settings (parameter/get-target-settings session :postgresql instance) - packages (:packages settings) - package-source (:package-source settings) - version (:version settings)] - (logging/debugf - "postgresql %s from %s packages [%s]" - version (:name package-source) (string/join ", " packages)) - (install-method session settings))) + [{:keys [instance-id] :as options}] + (logging/debugf "install postgresql") + (crate-install/install :postgresql instance-id)) + + +;;; ## Configure (defn hba-conf "Generates a pg_hba.conf file from the arguments. Each record is either a @@ -705,33 +690,27 @@ Links: Options: :cluster The database cluster to use - :instance The postgres instance to use" - [session & {:keys [instance cluster]}] - (conf-file - session [:options :hba_file] :permissions format-hba-record - :instance instance :cluster cluster)) + :instance-id The postgres instance to use" + [{:keys [instance-id cluster] :as options}] + (conf-file [:options :hba_file] :permissions format-hba-record options)) (defn postgresql-conf "Generates a postgresql.conf file from the arguments. Options: :cluster The database cluster to use - :instance The postgres instance to use" - [session & {:keys [instance cluster]}] - (conf-file - session [:postgresql_file] :options format-parameter - :instance instance :cluster cluster)) + :instance-id The postgres instance to use" + [{:keys [instance-id cluster] :as options}] + (conf-file [:postgresql_file] :options format-parameter options)) (defn recovery-conf "Generates a recovery.conf file from the arguments. Options: :cluster The database cluster to use - :instance The postgres instance to use" - [session & {:keys [instance cluster]}] - (conf-file - session [:recovery_file] :recovery format-parameter - :instance instance :cluster cluster)) + :instance-id The postgres instance to use" + [{:keys [instance-id cluster] :as options}] + (conf-file [:recovery_file] :recovery format-parameter options)) (defn start-conf "Generates a start.conf file from the arguments. This is debian specific. See @@ -739,11 +718,9 @@ Links: Options: :cluster The database cluster to use - :instance The postgres instance to use" - [session & {:keys [instance cluster]}] - (conf-file - session [:start_file] :start format-start - :instance instance :cluster cluster)) + :instance-id The postgres instance to use" + [{:keys [instance-id cluster] :as options}] + (conf-file [:start_file] :start format-start options)) (defn install-service "Generates a start.conf file from the arguments. This is specific to @@ -752,65 +729,60 @@ Links: Options: :cluster The database cluster to use - :instance The postgres instance to use" - [session & {:keys [instance cluster]}] - (let [settings (parameter/get-target-settings session :postgresql instance)] - (-> - session - (thread-expr/for-> - [cluster (keys (:clusters settings))] - (thread-expr/let-> - [cluster-name (name cluster) - cluster-settings (settings-for-cluster session cluster-name)] - (thread-expr/when-> - (not= cluster-name (:default-cluster-name settings)) - (service/init-script - (:service cluster-settings) - :remote-file (service/init-script-path (:default-service settings))) - (etc-default/write - (str "pgsql/" (:service cluster-settings)) - :PGDATA (-> cluster-settings :options :data_directory) - :PGPORT (-> cluster-settings :options :port)) - (thread-expr/if-> - (= :auto (-> cluster-settings :start :start)) - (service/service (:service cluster-settings) :action :enable) - (service/service (:service cluster-settings) :action :disable)))))))) + :instance-id The postgres instance to use" + [{:keys [instance-id cluster] :as options}] + (let [settings (get-settings :postgresql options)] + (doseq [cluster (keys (:clusters settings))] + (let [cluster-name (name cluster) + cluster-settings (settings-for-cluster cluster-name options)] + (when (not= cluster-name (:default-cluster-name settings)) + ;; TODO + ;; (service/init-script + ;; (:service cluster-settings) + ;; :remote-file (service/init-script-path (:default-service settings))) + (etc-default/write + (str "pgsql/" (:service cluster-settings)) + :PGDATA (-> cluster-settings :options :data_directory) + :PGPORT (-> cluster-settings :options :port)) + ;; TODO + ;; (if (= :auto (-> cluster-settings :start :start)) + ;; (service/service (:service cluster-settings) :action :enable) + ;; (service/service (:service cluster-settings) :action :disable)) + ))))) (defn service-config "Configure the service architecture." - [session & {:keys [instance cluster]}] - (let [settings (parameter/get-target-settings session :postgresql instance)] + [{:keys [instance-id cluster] :as options}] + (let [settings (get-settings :postgresql options)] (if (:has-multicluster-service settings) - (start-conf session :instance instance :cluster cluster) - (install-service session :instance instance :cluster cluster)))) + (start-conf options) + (install-service options)))) -(declare service) +; (declare service) (defn initdb "Initialise a cluster" - [session & {:keys [instance cluster]}] - (let [settings (parameter/get-target-settings session :postgresql instance) + [{:keys [instance-id cluster] :as options}] + (let [settings (get-settings :postgresql options) cluster (or cluster (:default-cluster-name settings)) initdb-via (:initdb-via settings :initdb) - cluster-settings (settings-for-cluster - session cluster :instance instance) + cluster-settings (settings-for-cluster cluster options) data-dir (-> cluster-settings :options :data_directory)] (case initdb-via - :service (service session :action :initdb) - :initdb (-> - session - (directory/directory - data-dir - :owner (:owner settings "postgres") - :mode "0700" - :path true) - (exec-script/exec-checked-script - "initdb" - (if (not (file-exists? ~(str data-dir "/PG_VERSION"))) - (sudo - -u ~(:owner settings "postgres") - (str ~(or (:bin settings) "") initdb) - -D ~data-dir))))))) + :service (actions/service :action :initdb) + :initdb (do + (directory + data-dir + :owner (:owner settings "postgres") + :mode "0700" + :path true) + (exec-checked-script + "initdb" + (if (not (file-exists? ~(str data-dir "/PG_VERSION"))) + ("sudo" + -u ~(:owner settings "postgres") + (str ~(or (:bin settings) "") initdb) + -D ~data-dir))))))) ;;; Scripts @@ -825,52 +797,50 @@ Links: user. Default: postgres :db-name database - the name of the database to connect to :cluster cluster-name - the name of the cluster to connect to - :instance instance-name - the instance (pg install) to use + :instance-id instance-name - the instance (pg install) to use :ignore-result - Ignore any error return value out of psql :title string - A title to be used in script output." - [session & {:keys [as-user instance cluster db-name ignore-result show-stdout - title] - :or {show-stdout true} - :as options}] - (let [settings (parameter/get-target-settings session :postgresql instance) + [& {:keys [as-user instance-id cluster db-name ignore-result show-stdout + title] + :or {show-stdout true} + :as options}] + (let [settings (get-settings :postgresql options) cluster (or cluster (:default-cluster-name settings)) - cluster-settings (settings-for-cluster session cluster) + cluster-settings (settings-for-cluster cluster options) as-user (or as-user (-> settings :owner)) file (str (stevedore/script @TMPDIR:-/tmp) "/" (gensym "postgresql") ".sql")] - (-> session - (apply-map-> - remote-file/remote-file - file - :no-versioning true - :owner as-user - (select-keys options remote-file/content-options)) - (exec-script/exec-checked-script - ;; Note that we stuff all output. This is because certain commands in - ;; PostgreSQL are idempotent but spit out an error and an error exit - ;; anyways (eg, create database on a database that already exists does - ;; nothing, but is counted as an error). - ;; Subshell used to isolate any cd - (str "psql script" (if title (str " - " title) "")) - ("(\n" - cd (~lib/user-home ~as-user) "&&" - sudo "-u" ~as-user - ~(if (:has-pg-wrapper settings) - "" - (format - "env PGDATA=%s PGPORT=%s" - (-> cluster-settings :options :data_directory) - (-> cluster-settings :options :port))) - psql - ~(if (:has-pg-wrapper settings) - (format "--cluster %s/%s" (:version settings) cluster) - "") - ~(if db-name (str "-d " db-name) "") - "-f" ~file - ~(if show-stdout "" ">-") - ~(if ignore-result "2>-" "") - ~(if ignore-result "|| true" "") "\n )")) - (remote-file/remote-file file :action :delete)))) + + (apply-map remote-file file + :no-versioning true + :owner as-user + (select-keys options content-options)) + (exec-checked-script + ;; Note that we stuff all output. This is because certain commands in + ;; PostgreSQL are idempotent but spit out an error and an error exit + ;; anyways (eg, create database on a database that already exists does + ;; nothing, but is counted as an error). + ;; Subshell used to isolate any cd + (str "psql script" (if title (str " - " title) "")) + ("(\n" + cd (~lib/user-home ~as-user) "&&" + sudo "-u" ~as-user + ~(if (:has-pg-wrapper settings) + "" + (format + "env PGDATA=%s PGPORT=%s" + (-> cluster-settings :options :data_directory) + (-> cluster-settings :options :port))) + psql + ~(if (:has-pg-wrapper settings) + (format "--cluster %s/%s" (:version settings) cluster) + "") + ~(if db-name (str "-d " db-name) "") + "-f" ~file + ~(if show-stdout "" ">-") + ~(if ignore-result "2>-" "") + ~(if ignore-result "|| true" "") "\n )")) + (remote-file file :action :delete))) (defn create-database "Create a database if it does not exist. @@ -882,19 +852,19 @@ Links: Example: (create-database \"my-database\" :db-parameters [:encoding \"'LATIN1'\"])" - [session db-name & rest] - (let [{:keys [db-parameters db] :as options} rest - db-parameters-str (string/join " " (map name db-parameters))] + [db-name & {:keys [db-parameters db] :as options}] + (let [db-parameters-str (string/join " " (map name db-parameters))] ;; Postgres simply has no way to check if a database exists and issue a ;; "CREATE DATABASE" only in the case that it doesn't. That would require a ;; function, but create database can't be done within a transaction, so ;; you're screwed. Instead, we just use the fact that trying to create an ;; existing database does nothing and stuff the output/error return. - (apply postgresql-script - session - :content (format "CREATE DATABASE %s %s;" db-name db-parameters-str) - :literal true - (conj (vec rest) :ignore-result true)))) + (apply-map + postgresql-script + :content (format "CREATE DATABASE %s %s;" db-name db-parameters-str) + :literal true + :ignore-result true + options))) ;; This is a format string that generates a temporary PL/pgsql function to ;; check if a given role exists, and if not create it. The first argument @@ -933,20 +903,19 @@ END$$;" Example (create-role \"myuser\" :user-parameters [:encrypted :password \"'mypasswd'\"])" - [session username & rest] - (let [{:keys [user-parameters db instance] :as options} rest - settings (parameter/get-target-settings session :postgresql instance) + [username & {:keys [user-parameters db instance-id] :as options}] + (let [settings (get-settings :postgresql options) user-parameters-str (string/join " " (map name user-parameters))] - (apply postgresql-script - session - :content (format - (create-role-pgsql (:version settings)) - username - (if (string/blank? user-parameters-str) - "" - (str "WITH " user-parameters-str))) - :literal true - rest))) + (apply-map + postgresql-script + :content (format + (create-role-pgsql (:version settings)) + username + (if (string/blank? user-parameters-str) + "" + (str "WITH " user-parameters-str))) + :literal true + options))) (defn service @@ -957,35 +926,29 @@ END$$;" Other options are as for `pallet.action.service/service`. The service name is looked up in the request parameters." - [session & {:keys [action if-config-changed if-flag instance] :as options}] - (let [settings (parameter/get-target-settings session :postgresql instance) - service (:service settings) + [& {:keys [action if-config-changed if-flag instance-id] :as options}] + (let [settings (get-settings :postgresql options) + service-name (:service settings) options (if if-config-changed (assoc options :if-flag postgresql-config-changed-flag) options)] - (-> - session - (thread-expr/if-> - (:has-multicluster-service settings) - (thread-expr/apply-map-> service/service service options) - (thread-expr/for-> - [cluster (keys (:clusters settings))] - (thread-expr/let-> - [cluster-name (name cluster) - cluster-settings (settings-for-cluster session cluster-name)] - (thread-expr/if-> - (= :auto (-> cluster-settings :start :start)) - (thread-expr/apply-map-> - service/service (:service cluster-settings) options)))))))) + (if (:has-multicluster-service settings) + (apply-map actions/service service-name options) + (doseq [cluster (keys (:clusters settings))] + (let [cluster-name (name cluster) + cluster-settings (settings-for-cluster cluster-name options)] + (if (= :auto (-> cluster-settings :start :start)) + (apply-map + actions/service (:service cluster-settings) options))))))) (defn controldata-script - [session {:keys [as-user instance cluster] :as options}] - (let [settings (parameter/get-target-settings session :postgresql instance) + [{:keys [as-user instance-id cluster] :as options}] + (let [settings (get-settings :postgresql options) cluster (or cluster (:default-cluster-name settings)) - cluster-settings (settings-for-cluster session cluster) + cluster-settings (settings-for-cluster cluster options) as-user (or as-user (-> settings :owner))] (stevedore/script - (sudo "-u" ~as-user + ("sudo" "-u" ~as-user ~(if-let [bin (:bin settings)] (str bin "/pg_controldata") "pg_controldata") @@ -993,28 +956,36 @@ END$$;" (defn controldata "Execute pg_controldata." - [session & {:keys [as-user instance cluster] :as options}] - (-> session - (exec-script/exec-checked-script - "pg_controldata" - (~controldata-script session options)))) + [session & {:keys [as-user instance-id cluster] :as options}] + (exec-checked-script + "pg_controldata" + (~controldata-script session options))) (defn log-settings "Log postgresql settings" - [session & {:keys [instance level] :or {level :info}}] - (let [settings (parameter/get-target-settings session :postgresql instance)] - (logging/log level (format "Postgresql %s %s" (or instance "") settings)) - session)) - -(defn postgres - [settings] - (server-spec - :phases {:settings (phase-fn - (postgres-settings (settings-map settings))) - :configure (phase-fn - (initdb) - (hba-conf) - (postgresql-conf) - (service-config) - (service + [& {:keys [instance-id level] :or {level :info} :as options}] + (let [settings (get-settings :postgresql options)] + (logging/log level + (format "Postgresql %s %s" (or instance-id "") settings)))) + +(defplan configure + [{:keys [instance-id] :as options}] + (initdb options) + (hba-conf options) + (postgresql-conf options) + (service-config options)) + + +(defn server-spec + "Return a postgres server-spec using the specified `settings`." + [settings & {:keys [instance-id] :as options}] + (api/server-spec + :phases {:settings (plan-fn + (pallet.crate.postgres/settings + (settings-map settings))) + :install (plan-fn + (install options)) + :configure (plan-fn + (configure options) + (service :action :restart :if-config-changed true))})) diff --git a/test/pallet/crate/postgres_test.clj b/test/pallet/crate/postgres_test.clj index f996016..ec0c8dd 100644 --- a/test/pallet/crate/postgres_test.clj +++ b/test/pallet/crate/postgres_test.clj @@ -1,14 +1,15 @@ (ns pallet.crate.postgres-test (:require - [pallet.action.exec-script :as exec-script] - [pallet.action.package :as package] - [pallet.build-actions :as build-actions] - [pallet.core :as core] + [pallet.actions + :refer [exec-checked-script package package-manager minimal-packages]] + [pallet.build-actions :refer [build-actions]] + [pallet.api :refer [lift node-spec plan-fn server-spec] :as api] [pallet.crate.automated-admin-user :as automated-admin-user] [pallet.crate.network-service :as network-service] [pallet.crate.postgres :as postgres] [pallet.live-test :as live-test] - [pallet.phase :as phase] + [pallet.script :refer [with-script-context]] + [pallet.stevedore :refer [with-script-language]] [pallet.test-utils :as test-utils] [clojure.tools.logging :as logging]) (:use clojure.test)) @@ -31,55 +32,49 @@ (deftest default-settings-test (is (-> - (pallet.stevedore/with-script-language - :pallet.stevedore.bash/bash - (pallet.script/with-script-context - [:ubuntu :aptitude] + (with-script-language :pallet.stevedore.bash/bash + (with-script-context [:ubuntu :aptitude] (postgres/default-settings {:server {:image {:os-family :ubuntu} :node-id :id}} :debian :debian-base (postgres/settings-map {})))) :options :data_directory))) (deftest settings-test - (let [settings (pallet.stevedore/with-script-language - :pallet.stevedore.bash/bash - (pallet.script/with-script-context - [:ubuntu :aptitude] - (pallet.crate.postgres/postgres-settings - {:server {:image {:os-family :ubuntu} :node-id :id}} - (pallet.crate.postgres/settings-map - {:layout :debian-base}))))] + (let [settings (with-script-language :pallet.stevedore.bash/bash + (with-script-context [:ubuntu :aptitude] + (postgres/settings + {:server {:image {:os-family :ubuntu} :node-id :id}} + (postgres/settings-map + {:layout :debian-base}))))] (is (-> settings :parameters :host :id :postgresql :default :options :data_directory)))) (deftest postgres-test - (is ; just check for compile errors for now - (build-actions/build-actions - {} - (postgres/postgres-settings (postgres/settings-map {:version "8.0"})) - (postgres/install-postgres) - (postgres/postgres-settings (postgres/settings-map {:version "9.0"})) - (postgres/cluster-settings "db1" {}) - (postgres/install-postgres) - (postgres/hba-conf) - (postgres/postgresql-script :content "some script") - (postgres/create-database "db") - (postgres/create-role "user")))) + (is ; just check for compile errors for now + (build-actions {} + (postgres/settings (postgres/settings-map {:version "8.0"})) + (postgres/install) + (postgres/settings (postgres/settings-map {:version "9.0"})) + (postgres/cluster-settings "db1" {}) + (postgres/install) + (postgres/hba-conf) + (postgres/postgresql-script :content "some script") + (postgres/create-database "db") + (postgres/create-role "user")))) (deftest cluster-settings-test (let [settings - (second (build-actions/build-actions - {} - (postgres/postgres-settings - (postgres/settings-map - {:version "9.0" - :wal_directory "/var/lib/postgres/%s/archive/"})) - (postgres/cluster-settings "db1" {}) - (postgres/cluster-settings "db2" {}) - (postgres/postgres-settings - (postgres/settings-map {:version "9.0"})))) + (second (build-actions {} + (postgres/settings + (postgres/settings-map + {:version "9.0" + :wal_directory "/var/lib/postgres/%s/archive/"})) + (postgres/cluster-settings "db1" {}) + (postgres/cluster-settings "db2" {}) + (postgres/settings + (postgres/settings-map {:version "9.0"})))) pg-settings (-> settings :parameters :host :id :postgresql :default)] (is (-> pg-settings :clusters :db1)) (is (-> pg-settings :clusters :db2)) @@ -88,6 +83,18 @@ (is (re-find #"db2/archive" (-> pg-settings :clusters :db2 :wal_directory))))) + +(def test-server-spec + (server-spec + :extends [(postgres/server-spec {})] + :phases {:settings (plan-fn + (postgres/cluster-settings + "db1" {:options {:port 5433}})) + :init (plan-fn + (postgres/create-database "db") + (postgres/create-role "u1"))})) + + (def pgsql-9-unsupported [{:os-family :debian :os-version-matches "5.0.7"} {:os-family :debian :os-version-matches "5.0"}]) @@ -100,18 +107,17 @@ [compute node-map node-types] {:pgtest (-> - (core/server-spec + (server-spec :phases - {:bootstrap (phase/phase-fn - (package/minimal-packages) - (package/package-manager :update) + {:bootstrap (plan-fn + (minimal-packages) + (package-manager :update) (automated-admin-user/automated-admin-user)) - :settings (phase/phase-fn - (postgres/postgres-settings (postgres/settings-map {})) + :settings (plan-fn + (postgres/settings (postgres/settings-map {})) (postgres/cluster-settings "db1" {:options {:port 5433}})) - :configure (phase/phase-fn - (postgres/install-postgres)) - :verify (phase/phase-fn + :configure (plan-fn (postgres/install)) + :verify (plan-fn (postgres/log-settings) (postgres/initdb) (postgres/initdb :cluster "db1") @@ -134,7 +140,7 @@ (pallet.crate.network-service/wait-for-port-listen 5432) (pallet.crate.network-service/wait-for-port-listen 5433))} :count 1 - :node-spec (core/node-spec :image image)))} + :node-spec (node-spec :image image)))} (is - (core/lift + (lift (val (first node-types)) :phase [:settings :verify] :compute compute))))) From f38991aeea63f8dff69f74722a34e74cbb50d7c3 Mon Sep 17 00:00:00 2001 From: Hugo Duncan Date: Sat, 6 Apr 2013 11:54:31 -0400 Subject: [PATCH 03/12] Change version to 0.8.0-313-SNAPSHOT --- project.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project.clj b/project.clj index 1e7be14..72cb7bc 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject com.palletops/postgres-crate "0.8.0-SNAPSHOT" +(defproject com.palletops/postgres-crate "0.8.0-313-SNAPSHOT" :description "Pallet crate to install, configure and use postgres" :url "http://palletops.com" :license {:name "Eclipse Public License" From e5d6aabaca16cad739729401079303ba29d184c2 Mon Sep 17 00:00:00 2001 From: Hugo Duncan Date: Sat, 6 Apr 2013 13:35:53 -0400 Subject: [PATCH 04/12] Remove pom.xml --- pom.xml | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 pom.xml diff --git a/pom.xml b/pom.xml deleted file mode 100644 index b90cd32..0000000 --- a/pom.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - 4.0.0 - - org.cloudhoist - pallet-crate-pom - 0.7.1 - - postgres - 0.7.0-SNAPSHOT - - - scm:git:git://github.com/pallet/postgres-crate.git - scm:git:ssh://git@github.com/pallet/postgres-crate.git - https://github.com/pallet/postgres-crate - - From d7aaee4d01af09d5d7b77423ad88b68ee5e10400 Mon Sep 17 00:00:00 2001 From: Hugo Duncan Date: Sat, 6 Apr 2013 13:36:30 -0400 Subject: [PATCH 05/12] Add a test phase to the postgres test-server-spec --- test/pallet/crate/postgres_test.clj | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/pallet/crate/postgres_test.clj b/test/pallet/crate/postgres_test.clj index ec0c8dd..0973f70 100644 --- a/test/pallet/crate/postgres_test.clj +++ b/test/pallet/crate/postgres_test.clj @@ -5,7 +5,7 @@ [pallet.build-actions :refer [build-actions]] [pallet.api :refer [lift node-spec plan-fn server-spec] :as api] [pallet.crate.automated-admin-user :as automated-admin-user] - [pallet.crate.network-service :as network-service] + [pallet.crate.network-service :refer [wait-for-port-listen]] [pallet.crate.postgres :as postgres] [pallet.live-test :as live-test] [pallet.script :refer [with-script-context]] @@ -89,10 +89,12 @@ :extends [(postgres/server-spec {})] :phases {:settings (plan-fn (postgres/cluster-settings - "db1" {:options {:port 5433}})) + "db1" {:options {:port 5432}})) :init (plan-fn (postgres/create-database "db") - (postgres/create-role "u1"))})) + (postgres/create-role "u1")) + :test (plan-fn + (wait-for-port-listen 5432))})) (def pgsql-9-unsupported @@ -137,8 +139,8 @@ (postgres/postgresql-script :content "create temporary table table2 ();" :show-stdout true :cluster "db1") - (pallet.crate.network-service/wait-for-port-listen 5432) - (pallet.crate.network-service/wait-for-port-listen 5433))} + (wait-for-port-listen 5432) + (wait-for-port-listen 5433))} :count 1 :node-spec (node-spec :image image)))} (is From 53e49b87bfb8f5d659d876155f8cd87a0f57edba Mon Sep 17 00:00:00 2001 From: Hugo Duncan Date: Sat, 6 Apr 2013 13:44:53 -0400 Subject: [PATCH 06/12] Remove the additional cluster --- test/pallet/crate/postgres_test.clj | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/pallet/crate/postgres_test.clj b/test/pallet/crate/postgres_test.clj index 0973f70..ea44489 100644 --- a/test/pallet/crate/postgres_test.clj +++ b/test/pallet/crate/postgres_test.clj @@ -88,8 +88,9 @@ (server-spec :extends [(postgres/server-spec {})] :phases {:settings (plan-fn - (postgres/cluster-settings - "db1" {:options {:port 5432}})) + ;; (postgres/cluster-settings + ;; "db1" {:options {:port 5432}}) + ) :init (plan-fn (postgres/create-database "db") (postgres/create-role "u1")) From c08a2efc69fe0682c28a7654fe8644874ce89114 Mon Sep 17 00:00:00 2001 From: Hugo Duncan Date: Sat, 6 Apr 2013 15:53:34 -0400 Subject: [PATCH 07/12] Update test to give access from vbox host --- test/pallet/crate/postgres_test.clj | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/pallet/crate/postgres_test.clj b/test/pallet/crate/postgres_test.clj index ea44489..5a12378 100644 --- a/test/pallet/crate/postgres_test.clj +++ b/test/pallet/crate/postgres_test.clj @@ -86,7 +86,14 @@ (def test-server-spec (server-spec - :extends [(postgres/server-spec {})] + :extends [(postgres/server-spec + (postgres/settings-map {:options {:listen_addresses "*"} + :permissions + [{:connection-type "host" + :database "all" + :user "all" + :address "10.0.2.2/24" + :auth-method "trust"}]}))] :phases {:settings (plan-fn ;; (postgres/cluster-settings ;; "db1" {:options {:port 5432}}) From 5f8b632233f714f86709d08c8a10d90f93144bcf Mon Sep 17 00:00:00 2001 From: Hugo Duncan Date: Sat, 25 May 2013 11:24:56 -0400 Subject: [PATCH 08/12] Add lein-pallet-crate plugin --- profiles.clj | 1 + 1 file changed, 1 insertion(+) diff --git a/profiles.clj b/profiles.clj index 6a4635f..7718d25 100644 --- a/profiles.clj +++ b/profiles.clj @@ -4,6 +4,7 @@ [ch.qos.logback/logback-classic "1.0.9"]] :plugins [[lein-set-version "0.3.0"] [lein-resource "0.3.2"] + [com.palletops/lein-pallet-crate "0.1.0"] [com.palletops/pallet-lein "0.6.0-beta.8"]] :aliases {"live-test-up" ["pallet" "up" From 6e8815ef748ed32ee8fef814de69f2e936283b8e Mon Sep 17 00:00:00 2001 From: Hugo Duncan Date: Tue, 29 Apr 2014 11:35:56 -0400 Subject: [PATCH 09/12] WIP - simple ubuntu support test passing --- dev-resources/logback-test.xml | 1 - profiles.clj | 39 +- project.clj | 13 +- src/pallet/crate/postgres.clj | 508 +++++--------------- src/pallet/crate/postgres/config.clj | 161 +++++++ src/pallet/crate/postgres/kb.clj | 221 +++++++++ test/pallet/crate/postgres/config_test.clj | 10 + test/pallet/crate/postgres/kb_test.clj | 21 + test/pallet/crate/postgres/support_test.clj | 102 ++++ test/pallet/crate/postgres_test.clj | 108 +---- 10 files changed, 654 insertions(+), 530 deletions(-) create mode 100644 src/pallet/crate/postgres/config.clj create mode 100644 src/pallet/crate/postgres/kb.clj create mode 100644 test/pallet/crate/postgres/config_test.clj create mode 100644 test/pallet/crate/postgres/kb_test.clj create mode 100644 test/pallet/crate/postgres/support_test.clj diff --git a/dev-resources/logback-test.xml b/dev-resources/logback-test.xml index a32bc4b..584feb5 100644 --- a/dev-resources/logback-test.xml +++ b/dev-resources/logback-test.xml @@ -34,7 +34,6 @@ logs/pallet.log - false logs/old/pallet.%d{yyyy-MM-dd}.log 3 diff --git a/profiles.clj b/profiles.clj index 7718d25..7120acf 100644 --- a/profiles.clj +++ b/profiles.clj @@ -1,30 +1,13 @@ {:dev - {:dependencies [[com.palletops/pallet "0.8.0-beta.7" :classifier "tests"] - [com.palletops/crates "0.1.0"] + {:dependencies [[com.palletops/pallet "0.8.0-SNAPSHOT" :classifier "tests"] + [com.palletops/crates "0.1.2-SNAPSHOT"] + [com.palletops/pallet-test-env "RELEASE"] [ch.qos.logback/logback-classic "1.0.9"]] - :plugins [[lein-set-version "0.3.0"] - [lein-resource "0.3.2"] - [com.palletops/lein-pallet-crate "0.1.0"] - [com.palletops/pallet-lein "0.6.0-beta.8"]] - :aliases {"live-test-up" - ["pallet" "up" - "--phases" "install,configure,test" - "--selector" "live-test"] - "live-test-down" ["pallet" "down" "--selector" "live-test"] - "live-test" ["do" "live-test-up," "live-test-down"]} - :test-selectors {:default (complement :live-test) - :live-test :live-test - :all (constantly true)}} - :doc {:dependencies [[com.palletops/pallet-codox "0.1.0"]] - :plugins [[codox/codox.leiningen "0.6.4"] - [lein-marginalia "0.7.1"]] - :codox {:writer codox-md.writer/write-docs - :output-dir "doc/0.8/api" - :src-dir-uri "https://github.com/pallet/postgres-crate/blob/develop" - :src-linenum-anchor-prefix "L"} - :aliases {"marg" ["marg" "-d" "doc/0.8/annotated"] - "codox" ["doc"] - "doc" ["do" "codox," "marg"]}} - :release - {:set-version - {:updates [{:path "README.md" :no-snapshot true}]}}} + :plugins [[com.palletops/lein-pallet-crate "RELEASE"] + [lein-pallet-release "RELEASE"] + [com.palletops/lein-test-env "RELEASE"]]} + :provided + {:dependencies [[org.clojure/clojure "1.6.0"] + [com.palletops/pallet "0.8.0-SNAPSHOT"]]} + :vmfest {:pallet/test-env {:test-specs + [{:selector :ubuntu-13-04}]}}} diff --git a/project.clj b/project.clj index 72cb7bc..5fe0f27 100644 --- a/project.clj +++ b/project.clj @@ -1,16 +1,7 @@ -(defproject com.palletops/postgres-crate "0.8.0-313-SNAPSHOT" +(defproject com.palletops/postgres-crate "0.8.0-SNAPSHOT" :description "Pallet crate to install, configure and use postgres" :url "http://palletops.com" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :scm {:url "git@github.com:pallet/runit-crate.git"} - - :dependencies [[org.clojure/clojure "1.4.0"] - [com.palletops/pallet "0.8.0-beta.7"]] - :repositories {"sonatype" - {:url "https://oss.sonatype.org/content/repositories/releases/" - :snapshots false}} - :resource {:resource-paths ["doc-src"] - :target-path "target/classes/pallet_crate/postgres_crate/" - :includes [#"doc-src/USAGE.*"]} - :prep-tasks ["resource" "crate-doc"]) + :dependencies [[prismatic/schema "0.2.1"]]) diff --git a/src/pallet/crate/postgres.clj b/src/pallet/crate/postgres.clj index 8aa30d3..0771916 100644 --- a/src/pallet/crate/postgres.clj +++ b/src/pallet/crate/postgres.clj @@ -47,11 +47,16 @@ Links: [pallet.compute :as compute] [pallet.core.session :refer [session]] [pallet.crate :refer [assoc-settings defplan get-settings os-family - update-settings]] + target-node update-settings]] [pallet.crate-install :as crate-install] [pallet.crate.etc-default :as etc-default] + [pallet.crate.postgres.config :as config] + [pallet.crate.postgres.kb :as kb] + [pallet.crate.service + :refer [supervisor-config supervisor-config-map] :as service] [pallet.script.lib :as lib] [pallet.stevedore :as stevedore] + [pallet.node :refer [is-64bit?]] [pallet.utils :refer [apply-map]] [clojure.tools.logging :as logging] [clojure.string :as string]) @@ -60,80 +65,79 @@ Links: [pallet.script :only [defscript]] [pallet.version-dispatch :only [defmethod-version defmulti-version defmulti-version-plan - defmethod-version-plan defmulti-version-plan os-map] + defmethod-version-plan defmulti-version-plan os-map os-map-lookup] :as version-dispatch] [pallet.versions :only [as-version-vector version-string]])) + +(def facility + "The settings facility for postgres." + ::postgresql) + (def ^{:private true} pallet-cfg-preamble "# This file was auto-generated by Pallet. Do not edit it manually unless you # know what you are doing. If you are still using Pallet, you probably want to # edit your Pallet scripts and rerun them.\n\n") - (def ^{:doc "Flag for recognising changes to configuration"} postgresql-config-changed-flag "postgresql-config") -;;; Default Postgres package version -(def postgres-package-version - (atom ; allow for open extension - (os-map - {{:os :linux} [8] - {:os :ubuntu :os-version [12]} [9 1]}))) - -;;; TODO temporary until next pallet beta -(defn os-map-lookup - [os-map] - (get os-map {:os (pallet.crate/os-family) - :os-version (pallet.versions/as-version-vector - (pallet.crate/os-version))})) - ;;; Install strategy -(defmulti-version-plan install-strategy [version settings]) - -(def ^{:dynamic true} *pgdg-repo-versions* - {"9.0" "9.0-5" - "9.1" "9.1-5" - "9.2" "9.2-5"}) - -(defn pgdg-url - [version os-family] - (format - "http://yum.pgrpms.org/reporpms/%s/pgdg-%s%s-%s.noarch.rpm" - version - (name os-family) - (string/replace version "." "") - (*pgdg-repo-versions* version))) - -(defmethod-version-plan - install-strategy {:os :rh-base} - [os os-version version settings] - (-> - (cond - (:install-strategy settings) settings - (:package-source settings) (assoc settings :install-strategy :package-source) - :else (let [default-version (os-map-lookup @postgres-package-version) - target-version (:version settings)] - (if (= (version-string default-version) target-version) - (assoc settings - :install-strategy :packages - :packages (map - #(str "postgresql-" (name %)) - (:components settings #{:server :libs})) - :layout :rh-base) - (assoc settings - :install-strategy :rpm-repo - :rpm {:name "pgdg.rpm" - :url (pgdg-url (version-string version) - (if (= os :rhel) "redhat" os))} - :packages (map - #(str "postgresql" - (string/replace target-version "." "") - "-" (name %)) - (:components settings #{:server :libs})) - :layout :pgdg)))))) -;; TODO +(defn postgres-rpm-settings + "Returns a settings map for install via the Postgres RPM repository." + [version components os-family os-version arch] + (let [arch (if (is-64bit? (target-node)) "x86_64" "i386")] + {:install-strategy :rpm-repo + :rpm {:name "pgdg.rpm" + :url (kb/pgdg-url (version-string version) os-family os-version arch)} + :packages (kb/pgdg-packages + (version-string version) + components) + :layout :pgdg})) + +(defn postgres-apt-settings + [version] + {:install-strategy :package-source + :package-source + {:name "Postgres Apt" + :aptitude kb/postgres-apt + :apt kb/postgres-apt} + :packages (kb/postgres-apt-packages (version-string version)) + :layout :debian-base}) + +(defn yum-packages-settings + [version components] + {:install-strategy :packages + :packages (kb/yum-packages + (version-string version) + (or components #{:server :libs})) + :layout :rh-base}) + +(defn apt-packages-settings + [version components] + {:install-strategy :packages + :packages (kb/apt-packages + (version-string version) + components) + :layout :debian-base}) + +;; (def xx "aa" :a :b +;; ) + +(defmulti-version-plan install-strategy + ;; Default install strategy, if none supplied. + [version settings]) + +(defmethod-version-plan install-strategy {:os :rh-base} + [os os-version version settings] + (yum-packages-settings version nil)) + +(defmethod-version-plan install-strategy {:os :debian-base} + [os os-version version settings] + (apt-packages-settings version nil)) + ;; (defmethod-version-plan -;; install-strategy {:os :debian} +;; install-strategy {:os :arch} ;; [os os-version version settings] ;; (-> ;; (cond @@ -145,83 +149,13 @@ Links: ;; (assoc settings ;; :install-strategy :packages ;; :packages ["postgresql"] -;; :layout :debian-base) -;; (assoc settings -;; :install-strategy :package-source -;; ; :package-source (debian-backports-repository) -;; :packages ["libpq5" (str "postgresql-" target-version)] -;; :layout :debian-base)))))) - -(defmethod-version-plan - install-strategy {:os :ubuntu} - [os os-version version settings] - (-> - (cond - (:install-strategy settings) settings - (:package-source settings) (assoc settings :install-strategy :package-source) - :else (let [default-version (os-map-lookup @postgres-package-version) - target-version (:version settings)] - (if (= (version-string default-version) target-version) - (assoc settings - :install-strategy :packages - :packages ["postgresql"] - :layout :debian-base) - (assoc settings - :install-strategy :package-source - :package-source {:name "Martin Pitt backports" - :aptitude {:url "ppa:pitti/postgresql"} - :apt {:url "ppa:pitti/postgresql"}} - :packages [(str "postgresql-" target-version)] - :layout :debian-base)))))) - -(defmethod-version-plan - install-strategy {:os :arch} - [os os-version version settings] - (-> - (cond - (:install-strategy settings) settings - (:package-source settings) (assoc settings :install-strategy :package-source) - :else (let [default-version (os-map-lookup @postgres-package-version) - target-version (:version settings)] - (if (= (version-string default-version) target-version) - (assoc settings - :install-strategy :packages - :packages ["postgresql"] - :layout :arch) - (throw - (ex-info - (format "No install strategy for postgres %s on %s %s" - version os os-version) - {:reason :no-install-strategy - :version version :os os :os-version os-version}))))))) - -;;; Dispatch to install strategy -;; (defmulti install-method (fn [session settings] (:strategy settings))) - -;; (defmethod install-method :packages [session settings] -;; (reduce package session (:packages settings))) - -;; (defmethod install-method :package-source -;; [session {:keys [package-source packages] :as settings}] -;; (apply-map package-source (:name package-source) package-source) -;; (package-manager :update) -;; (when (= package-source :debian-backports) -;; (add-debian-backports) -;; (package-manager :update)) -;; (doseq [pkg packages] -;; (package pkg))) - -;; (defmethod install-method :rpm -;; [session {:keys [rpm] :as settings}] -;; (action/with-action-options {:always-before `package/package} -;; (apply-map add-rpm (:name rpm) rpm))) - -;; (defmethod install-method :rpm-repo -;; [session {:keys [rpm packages] :as settings}] -;; (action/with-action-options {:always-before `package/package} -;; (apply-map add-rpm (:name rpm) rpm)) -;; (doseq [pkg packages] -;; (package pkg))) +;; :layout :arch) +;; (throw +;; (ex-info +;; (format "No install strategy for postgres %s on %s %s" +;; version os os-version) +;; {:reason :no-install-strategy +;; :version version :os os :os-version os-version}))))))) ;;; Default settings @@ -261,225 +195,6 @@ Links: [:permissions])))) settings)) -(defmulti default-settings - "Determine the default settings for the specified " - (fn [os-family layout settings] - layout)) - -(defn base-settings [] - {:service "postgresql" - :owner "postgres" - :initdb-via :initdb - :options {:external_pid_file (str (stevedore/script (~lib/pid-root)) - "/postgresql.pid")}}) - -(defmethod default-settings :debian-base - [os-family layout settings] - (let [version (:version settings)] - (merge-settings - (base-settings) - {:default-cluster-name "main" - :bin (format "/usr/lib/postgresql/%s/bin/" version) - :share (format "/usr/lib/postgresql/%s/share/" version) - :wal_directory (format "/var/lib/postgresql/%s/%%s/archive" version) - :postgresql_file (format - "/etc/postgresql/%s/%%s/postgresql.conf" version) - :has-pg-wrapper true - :has-multicluster-service true - :options - {:data_directory (format "/var/lib/postgresql/%s/%%s" version) - :hba_file (format "/etc/postgresql/%s/%%s/pg_hba.conf" version) - :ident_file (format "/etc/postgresql/%s/%%s/pg_ident.conf" version) - :external_pid_file (format "/var/run/postgresql/%s-%%s.pid" version) - :unix_socket_directory "/var/run/postgresql"}}))) - -(defmethod default-settings :rh-base - [os-family layout settings] - (let [version (:version settings)] - (merge-settings - (base-settings) - {:default-cluster-name "data" - :wal_directory (format "/var/lib/pgsql/%s/%%s/archive" version) - :postgresql_file (format "/var/lib/pgsql/%s/%%s/postgresql.conf" version) - :options - {:data_directory (format "/var/lib/pgsql/%s/%%s" version) - :hba_file (format "/var/lib/pgsql/%s/%%s/pg_hba.conf" version) - :ident_file (format "/var/lib/pgsql/%s/%%s/pg_ident.conf" version) - :external_pid_file (format "/var/run/postmaster-%s-%%s.pid" version)}}))) - -(defmethod default-settings :pgdg - [os-family package-source settings] - (let [version (:version settings)] - (merge-settings - (base-settings) - (default-settings os-family :rh-base settings) - {:bin (format "/usr/pgsql-%s/bin/" version) - :share (format "/usr/pgsql-%s/share/" version) - :default-cluster-name "data" - :service (str "postgresql-" version "-%s") - :default-service (str "postgresql-" version) - :use-port-in-pidfile true - :wal_directory (format "/var/lib/pgsql/%s/%%s/archive" version) - :postgresql_file (format "/var/lib/pgsql/%s/%%s/postgresql.conf" version) - :options - {:data_directory (format "/var/lib/pgsql/%s/%%s" version) - :hba_file (format "/var/lib/pgsql/%s/%%s/pg_hba.conf" version) - :ident_file (format "/var/lib/pgsql/%s/%%s/pg_ident.conf" version)}}))) - -(defmethod default-settings :arch - [os-family package-source settings] - (let [version (:version settings)] - (merge-settings - (base-settings) - {:components [] - :default-cluster-name "data" - :initdb-via :initdb - :wal_directory "/var/lib/postgres/%%s/archive/" - :postgresql_file "/var/lib/postgres/%%s/postgresql.conf" - :options - {:data_directory "/var/lib/postgres/%%s/" - :hba_file "/var/lib/postgres/%%s/pg_hba.conf" - :ident_file "/var/lib/postgres/%%s/pg_ident.conf"}}))) - -;;; pg_hba.conf - -(def ^{:private true} - auth-methods #{"trust" "reject" "md5" "password" "gss" "sspi" "krb5" - "ident" "ldap" "radius" "cert" "pam"}) -(def ^{:private true} - ip-addr-regex #"[0-9]{1,3}.[0-9]{1,3}+.[0-9]{1,3}+.[0-9]{1,3}+") - -(defn- valid-hba-record? - "Takes an hba-record as input and minimally checks that it could be a valid - record." - [{:keys [connection-type database user auth-method address ip-mask] - :as record-map}] - (and (#{"local" "host" "hostssl" "hostnossl"} (name connection-type)) - (every? #(not (nil? %)) [database user auth-method]) - (auth-methods (name auth-method)))) - -(defn- vector-to-map - [record] - (case (name (first record)) - "local" (apply - hash-map - (interleave - [:connection-type :database :user :auth-method - :auth-options] - record)) - ("host" - "hostssl" - "hostnossl") (let [[connection-type database user address - & remainder] record] - (if (re-matches - ip-addr-regex (first remainder)) - ;; Not nil so must be an IP mask. - (apply - hash-map - (interleave - [:connection-type :database :user - :address :ip-mask :auth-method - :auth-options] - record)) - ;; Otherwise, it may be an auth-method. - (if (auth-methods - (name (first remainder))) - (apply - hash-map - (interleave - [:connection-type :database :user - :address :auth-method - :auth-options] - record)) - (throw - (ex-info - (format - "The fifth item in %s does not appear to be an IP mask or auth method." - (pr-str record)) - {:type :postgres-invalid-hba-record}))))) - (throw - (ex-info - (format - "The first item in %s is not a valid connection type." - (name record))) - {:type :postgres-invalid-hba-record}))) - -(defn- record-to-map - "Takes a record given as a map or vector, and turns it into the map version." - [record] - (cond - (map? record) record - (vector? record) (vector-to-map record) - :else - (throw - (ex-info - (format "The record %s must be a vector or map." (name record)) - {:type :postgres-invalid-hba-record})))) - -(defn- format-auth-options - "Given the auth-options map, returns a string suitable for inserting into the - file." - [auth-options] - (string/join "," (map #(str (first %) "=" (second %)) auth-options))) - -(defn- format-hba-record - [record] - (let [record-map (record-to-map record) - record-map (assoc record-map :auth-options - (format-auth-options (:auth-options record-map))) - ordered-fields (map #(% record-map "") - [:connection-type :database :user :address :ip-mask - :auth-method :auth-options]) - ordered-fields (map name ordered-fields)] - (if (valid-hba-record? record-map) - (str (string/join "\t" ordered-fields) "\n")))) - -;;; postgresql.conf - -(defn database-data-directory - "Given a settings map and a database name, return the data directory - for the database." - [settings cluster] - (format "%s/%s/recovery.conf" (-> settings :options :data_directory) cluster)) - -(defn- parameter-escape-string - "Given a string, escapes any single-quotes." - [string] - (apply str (replace {\' "''"} string))) - -(defn- format-parameter-value - [value] - (cond (number? value) - (str value) - (string? value) - (str "'" value "'") - (vector? value) - (str "'" (string/join "," (map name value)) "'") - (or (= value true) (= value false)) - (str value) - :else - (throw - (ex-info - (format - (str - "Parameters must be numbers, strings, or vectors of such. " - "Invalid value %s") (pr-str value)) - {:type :postgres-invalid-parameter - :value value})))) - -(defn- format-parameter - "Given a key/value pair in a vector, formats it suitably for the - postgresql.conf file. - The value should be either a number, a string, or a vector of such." - [[key value]] - (let [key-str (name key) - parameter-str (format-parameter-value value)] - (str key-str " = " parameter-str "\n"))) - -(defn- format-start - [[key value]] - (name value)) - ;;; database cluster variants (defn hot-standby-master @@ -551,7 +266,7 @@ Links: "Returns the settings for the specified cluster" [cluster {:keys [instance-id] :as options}] (get-in - (get-settings :postgresql options) + (get-settings facility options) [:clusters (keyword cluster)])) (defn check-settings @@ -571,12 +286,12 @@ Links: (defn conf-file "Generates a postgresql configuration file" [file-keys values-kw formatter {:keys [instance-id cluster] :as options}] - (let [settings (get-settings :postgresql options) + (let [settings (get-settings facility options) cluster (or cluster (:default-cluster-name settings)) cluster-settings (settings-for-cluster cluster options) conf-path (get-in cluster-settings file-keys) - hba-contents (apply str pallet-cfg-preamble - (map formatter (values-kw cluster-settings)))] + hba-contents (str pallet-cfg-preamble + (formatter (values-kw cluster-settings)))] (check-settings settings cluster-settings cluster file-keys) (directory (stevedore/script @(~lib/dirname ~conf-path)) @@ -591,7 +306,7 @@ Links: (defn default-cluster-name "Returns the default cluster name" [& {:keys [instance-id] :as options}] - (let [settings (get-settings :postgresql options)] + (let [settings (get-settings facility options)] (:default-cluster-name settings))) ;;; # Crate functions @@ -627,7 +342,7 @@ Links: For variant :hot-standby-replica, you will need to pass :primary_conninfo in the `settings-map`" [cluster-name settings-map & {:keys [instance-id variant] :as options}] - (let [settings (get-settings :postgresql options) + (let [settings (get-settings facility options) settings (cluster-settings-with-defaults cluster-name settings-map settings) settings (case variant @@ -635,32 +350,35 @@ Links: :hot-standby-replica (hot-standby-replica settings) settings)] (update-settings - :postgresql instance-id + facility instance-id assoc-in [:clusters (keyword cluster-name)] settings))) -(defn base-distribution - "Base distribution of the target-node." - [] - (compute/base-distribution (-> (session) :server :image))) +;; (defn base-distribution +;; "Base distribution of the target-node." +;; [] +;; (compute/base-distribution (target-node))) (defn settings "Add postgresql settings to the session map." - [{:keys [version] - :or {version (version-string (os-map-lookup @postgres-package-version))} - :as settings} - & {:keys [instance-id] :as options}] - (let [settings (assoc settings :version version) - settings (install-strategy version settings) + [{:keys [instance-id version] + :or {version (version-string (os-map-lookup @kb/postgres-package-version))} + :as settings}] + (let [options (select-keys settings [:instance-id]) + settings (-> settings + (assoc :version version) + (dissoc :instance-id)) + settings (if (:install-strategy settings) + settings + (merge (install-strategy version settings) settings)) settings (merge-settings - (default-settings - (base-distribution) - (:layout settings) settings) + (kb/layout-settings + (os-family) (:layout settings) version) settings) - old-settings (get-settings :postgresql options)] + old-settings (get-settings facility options)] (logging/debugf "Postgresql Settings %s" settings) (assoc-settings - :postgresql (assoc settings :clusters (:clusters old-settings)) + facility (assoc settings :clusters (:clusters old-settings)) options) (when-let [cluster-name (:default-cluster-name settings)] (cluster-settings cluster-name {} :instance-id instance-id)))) @@ -671,8 +389,7 @@ Links: "Install postgres." [{:keys [instance-id] :as options}] (logging/debugf "install postgresql") - (crate-install/install :postgresql instance-id)) - + (crate-install/install facility instance-id)) ;;; ## Configure @@ -692,7 +409,7 @@ Links: :cluster The database cluster to use :instance-id The postgres instance to use" [{:keys [instance-id cluster] :as options}] - (conf-file [:options :hba_file] :permissions format-hba-record options)) + (conf-file [:options :hba_file] :permissions config/hba options)) (defn postgresql-conf "Generates a postgresql.conf file from the arguments. @@ -701,7 +418,7 @@ Links: :cluster The database cluster to use :instance-id The postgres instance to use" [{:keys [instance-id cluster] :as options}] - (conf-file [:postgresql_file] :options format-parameter options)) + (conf-file [:postgresql_file] :options config/conf options)) (defn recovery-conf "Generates a recovery.conf file from the arguments. @@ -710,7 +427,7 @@ Links: :cluster The database cluster to use :instance-id The postgres instance to use" [{:keys [instance-id cluster] :as options}] - (conf-file [:recovery_file] :recovery format-parameter options)) + (conf-file [:recovery_file] :recovery config/conf options)) (defn start-conf "Generates a start.conf file from the arguments. This is debian specific. See @@ -720,7 +437,7 @@ Links: :cluster The database cluster to use :instance-id The postgres instance to use" [{:keys [instance-id cluster] :as options}] - (conf-file [:start_file] :start format-start options)) + (conf-file [:start_file] :start config/start options)) (defn install-service "Generates a start.conf file from the arguments. This is specific to @@ -731,7 +448,7 @@ Links: :cluster The database cluster to use :instance-id The postgres instance to use" [{:keys [instance-id cluster] :as options}] - (let [settings (get-settings :postgresql options)] + (let [settings (get-settings facility options)] (doseq [cluster (keys (:clusters settings))] (let [cluster-name (name cluster) cluster-settings (settings-for-cluster cluster-name options)] @@ -753,7 +470,7 @@ Links: (defn service-config "Configure the service architecture." [{:keys [instance-id cluster] :as options}] - (let [settings (get-settings :postgresql options)] + (let [settings (get-settings facility options)] (if (:has-multicluster-service settings) (start-conf options) (install-service options)))) @@ -763,7 +480,7 @@ Links: (defn initdb "Initialise a cluster" [{:keys [instance-id cluster] :as options}] - (let [settings (get-settings :postgresql options) + (let [settings (get-settings facility options) cluster (or cluster (:default-cluster-name settings)) initdb-via (:initdb-via settings :initdb) cluster-settings (settings-for-cluster cluster options) @@ -804,7 +521,7 @@ Links: title] :or {show-stdout true} :as options}] - (let [settings (get-settings :postgresql options) + (let [settings (get-settings facility options) cluster (or cluster (:default-cluster-name settings)) cluster-settings (settings-for-cluster cluster options) as-user (or as-user (-> settings :owner)) @@ -904,7 +621,7 @@ END$$;" Example (create-role \"myuser\" :user-parameters [:encrypted :password \"'mypasswd'\"])" [username & {:keys [user-parameters db instance-id] :as options}] - (let [settings (get-settings :postgresql options) + (let [settings (get-settings facility options) user-parameters-str (string/join " " (map name user-parameters))] (apply-map postgresql-script @@ -927,7 +644,7 @@ END$$;" Other options are as for `pallet.action.service/service`. The service name is looked up in the request parameters." [& {:keys [action if-config-changed if-flag instance-id] :as options}] - (let [settings (get-settings :postgresql options) + (let [settings (get-settings facility options) service-name (:service settings) options (if if-config-changed (assoc options :if-flag postgresql-config-changed-flag) @@ -943,7 +660,7 @@ END$$;" (defn controldata-script [{:keys [as-user instance-id cluster] :as options}] - (let [settings (get-settings :postgresql options) + (let [settings (get-settings facility options) cluster (or cluster (:default-cluster-name settings)) cluster-settings (settings-for-cluster cluster options) as-user (or as-user (-> settings :owner))] @@ -964,7 +681,7 @@ END$$;" (defn log-settings "Log postgresql settings" [& {:keys [instance-id level] :or {level :info} :as options}] - (let [settings (get-settings :postgresql options)] + (let [settings (get-settings facility options)] (logging/log level (format "Postgresql %s %s" (or instance-id "") settings)))) @@ -988,4 +705,5 @@ END$$;" :configure (plan-fn (configure options) (service - :action :restart :if-config-changed true))})) + :action :restart :if-config-changed true))} + :default-phases [:install :configure])) diff --git a/src/pallet/crate/postgres/config.clj b/src/pallet/crate/postgres/config.clj new file mode 100644 index 0000000..48fefd1 --- /dev/null +++ b/src/pallet/crate/postgres/config.clj @@ -0,0 +1,161 @@ +(ns pallet.crate.postgres.config + "Postgres configuration" + (:require + [clojure.string :as string :refer [join]])) + +;;; pg_hba.conf + +(def ^{:private true} + auth-methods #{"trust" "reject" "md5" "password" "gss" "sspi" "krb5" + "ident" "ldap" "radius" "cert" "pam"}) +(def ^{:private true} + ip-addr-regex #"[0-9]{1,3}.[0-9]{1,3}+.[0-9]{1,3}+.[0-9]{1,3}+") + +(defn- valid-hba-record? + "Takes an hba-record as input and minimally checks that it could be a valid + record." + [{:keys [connection-type database user auth-method address ip-mask] + :as record-map}] + (and (#{"local" "host" "hostssl" "hostnossl"} (name connection-type)) + (every? #(not (nil? %)) [database user auth-method]) + (auth-methods (name auth-method)))) + +(defn- vector-to-map + [record] + (case (name (first record)) + "local" (apply + hash-map + (interleave + [:connection-type :database :user :auth-method + :auth-options] + record)) + ("host" + "hostssl" + "hostnossl") (let [[connection-type database user address + & remainder] record] + (if (re-matches + ip-addr-regex (first remainder)) + ;; Not nil so must be an IP mask. + (apply + hash-map + (interleave + [:connection-type :database :user + :address :ip-mask :auth-method + :auth-options] + record)) + ;; Otherwise, it may be an auth-method. + (if (auth-methods + (name (first remainder))) + (apply + hash-map + (interleave + [:connection-type :database :user + :address :auth-method + :auth-options] + record)) + (throw + (ex-info + (format + "The fifth item in %s does not appear to be an IP mask or auth method." + (pr-str record)) + {:type :postgres-invalid-hba-record}))))) + (throw + (ex-info + (format + "The first item in %s is not a valid connection type." + (name record))) + {:type :postgres-invalid-hba-record}))) + +(defn- record-to-map + "Takes a record given as a map or vector, and turns it into the map version." + [record] + (cond + (map? record) record + (vector? record) (vector-to-map record) + :else + (throw + (ex-info + (format "The record %s must be a vector or map." (name record)) + {:type :postgres-invalid-hba-record})))) + +(defn- format-auth-options + "Given the auth-options map, returns a string suitable for inserting into the + file." + [auth-options] + (string/join "," (map #(str (first %) "=" (second %)) auth-options))) + +(defn format-hba + [record] + (let [record-map (record-to-map record) + record-map (assoc record-map :auth-options + (format-auth-options (:auth-options record-map))) + ordered-fields (map #(% record-map "") + [:connection-type :database :user :address :ip-mask + :auth-method :auth-options]) + ordered-fields (map name ordered-fields)] + (if (valid-hba-record? record-map) + (str (string/join "\t" ordered-fields) "\n")))) + +(defn hba + "Return content for pg_hba.conf given a sequence of hba permission + entries." + [permissions] + (join (map format-hba permissions))) + +;;; postgresql.conf, recovery.conf + +(defn database-data-directory + "Given a settings map and a database name, return the data directory + for the database." + [settings cluster] + (format "%s/%s/recovery.conf" (-> settings :options :data_directory) cluster)) + +(defn- parameter-escape-string + "Given a string, escapes any single-quotes." + [string] + (apply str (replace {\' "''"} string))) + +(defn- format-parameter-value + [value] + (cond (number? value) + (str value) + (string? value) + (str "'" value "'") + (vector? value) + (str "'" (string/join "," (map name value)) "'") + (or (= value true) (= value false)) + (str value) + :else + (throw + (ex-info + (format + (str + "Parameters must be numbers, strings, or vectors of such. " + "Invalid value %s") (pr-str value)) + {:type :postgres-invalid-parameter + :value value})))) + +(defn format-conf + "Given a key/value pair in a vector, formats it suitably for the + postgresql.conf file. + The value should be either a number, a string, or a vector of such." + [[key value]] + (let [key-str (name key) + parameter-str (format-parameter-value value)] + (str key-str " = " parameter-str "\n"))) + +(defn conf + "Return content for postgresql.conf given a sequence of entries." + [entries] + (join (map format-conf entries))) + +;;; start.conf + +(defn format-start + [[key value]] + (name value)) + +(defn start + "Return content for postgresql.conf given a sequence of entries." + [entries] + (join (map format-start entries))) diff --git a/src/pallet/crate/postgres/kb.clj b/src/pallet/crate/postgres/kb.clj new file mode 100644 index 0000000..d81d38e --- /dev/null +++ b/src/pallet/crate/postgres/kb.clj @@ -0,0 +1,221 @@ +(ns pallet.crate.postgres.kb + "Knowledge base for postgres install and configuration" + (:require + [clojure.string :as string] + [pallet.version-dispatch :refer [os-map]] + [pallet.compute :refer [os-hierarchy]] + [pallet.utils :refer [deep-merge]] + [schema.core :as schema :refer [enum validate]])) + +(def Layout + {:bin String + :default-cluster-name String + ;; :default-service String + :has-multicluster-service schema/Bool + :has-pg-wrapper schema/Bool + :initdb-via (enum :initdb :service) + :postgresql_file String + :service String + :share String + :use-port-in-pidfile schema/Bool + :owner String + :wal_directory String + :options {:external_pid_file String + :data_directory String + :hba_file String + :ident_file String + :unix_socket_directory String + schema/Keyword schema/Any}}) + +(defmulti layout-settings + "Determine the layout of packages for the specified os-family or layout." + (fn [os-family layout version] + {:pre [(keyword? layout) + (string? version)]} + layout)) + +(defn base-layout + "Base layout used as a default with common options." + [] + {:service "postgresql" + :owner "postgres" + :has-pg-wrapper false + :has-multicluster-service false + :initdb-via :initdb + :use-port-in-pidfile false + :options {:external_pid_file "/var/run/postgresql.pid"}}) + + +;;; # System Packages + +;;; Default Postgres package version + +(def postgres-package-version + "Default version for distros." + (atom ; allow for open extension + (os-map + {{:os :linux} [8] + {:os :ubuntu :os-version [[12] [13 10]]} [9 1] + {:os :ubuntu :os-version [[14 04]]} [9 3]}))) + + +;;; ## Yum system packages +(defn yum-packages + "Return a sequence of package names for system packages on yum based + systems." + [version components] + {:pre [(string? version)]} + (map + #(format "postgresql-%s-%s" (name %) version) + components)) + +;;; ## Apt system packages +(defn apt-packages + "Return a sequence of package names for system packages on apt based + systems." + [version components] + {:pre [(string? version)]} + (conj + (map + #(format "postgresql-%s-%s" version (name %)) + components) + (format "postgresql-%s" version))) + +;;; # Postgres RPM Repository + +;;; See http://yum.postgresql.org/ + +(def ^{:dynamic true} *pgdg-repo-versions* + "Versions available from the postgres RPM repository." + {"9.0" "9.0-5" + "9.1" "9.1-6" + "9.2" "9.2-7" + "9.3" "9.3-1"}) + +(defn base-name + [os-family] + (if (= os-family :fedora) + "fedora" + "redhat")) + +(defn base-pkg-name + [os-family] + (if (= os-family :fedora) + "fedora" + "rhel")) + +(defn distro-name + [os-family] + (name os-family)) + +(def pkg-distro-names + {:rhel "redhat"}) + +(defn pkg-distro-name + [os-family] + (os-family pkg-distro-names (name os-family))) + +(defn pgdg-url + [version os-family os-version arch] + {:pre [(string? version) + (#{"i386" "x86_64"} arch)]} + (format + "http://yum.postgresql.org/%s/%s/%s-%s-%s/pgdg-%s%s-%s.noarch.rpm" + version + (base-name os-family) + (base-pkg-name os-family) os-version arch + (pkg-distro-name os-family) + (string/replace version "." "") + (*pgdg-repo-versions* version))) + +(defn pgdg-packages + "Return package names for Postgres RPM repository packages, for the given + postgres version and sequence of component keywords." + [version components] + (map + #(str "postgresql" (string/replace version "." "") "-" (name %)) + components)) + +;;; # Postgres APT Repository + +;;; See http://wiki.postgresql.org/wiki/Apt + +(def postgres-apt + "Repository for postgres Apt packages." + {:url "http://apt.postgresql.org/pub/repos/apt/" + :key-url "https://www.postgresql.org/media/keys/ACCC4CF8.asc"}) + +(defn postgres-apt-packages + "Return a sequence of package names for the given version." + [version] + {:pre [(string? version)]} + [(str "postgresql-" version)]) + + +(defmethod layout-settings :debian-base + [os-family layout version] + {:post [(validate Layout %)]} + (deep-merge + (base-layout) + {:default-cluster-name "main" + :bin (format "/usr/lib/postgresql/%s/bin/" version) + :share (format "/usr/lib/postgresql/%s/share/" version) + :wal_directory (format "/var/lib/postgresql/%s/%%s/archive" version) + :postgresql_file (format + "/etc/postgresql/%s/%%s/postgresql.conf" version) + :has-pg-wrapper true + :has-multicluster-service true + :options + {:data_directory (format "/var/lib/postgresql/%s/%%s" version) + :hba_file (format "/etc/postgresql/%s/%%s/pg_hba.conf" version) + :ident_file (format "/etc/postgresql/%s/%%s/pg_ident.conf" version) + :external_pid_file (format "/var/run/postgresql/%s-%%s.pid" version) + :unix_socket_directory "/var/run/postgresql"}})) + +(defmethod layout-settings :rh-base + [os-family layout version] + {:post [(validate Layout %)]} + (deep-merge + (base-layout) + {:default-cluster-name "data" + :wal_directory (format "/var/lib/pgsql/%s/%%s/archive" version) + :postgresql_file (format "/var/lib/pgsql/%s/%%s/postgresql.conf" version) + :options + {:data_directory (format "/var/lib/pgsql/%s/%%s" version) + :hba_file (format "/var/lib/pgsql/%s/%%s/pg_hba.conf" version) + :ident_file (format "/var/lib/pgsql/%s/%%s/pg_ident.conf" version) + :external_pid_file (format "/var/run/postmaster-%s-%%s.pid" version)}})) + +(defmethod layout-settings :pgdg + [os-family package-source version] + {:post [(validate Layout %)]} + (deep-merge + (base-layout) + (layout-settings os-family :rh-base version) + {:bin (format "/usr/pgsql-%s/bin/" version) + :share (format "/usr/pgsql-%s/share/" version) + :default-cluster-name "data" + :service (str "postgresql-" version "-%s") + :default-service (str "postgresql-" version) + :use-port-in-pidfile true + :wal_directory (format "/var/lib/pgsql/%s/%%s/archive" version) + :postgresql_file (format "/var/lib/pgsql/%s/%%s/postgresql.conf" version) + :options + {:data_directory (format "/var/lib/pgsql/%s/%%s" version) + :hba_file (format "/var/lib/pgsql/%s/%%s/pg_hba.conf" version) + :ident_file (format "/var/lib/pgsql/%s/%%s/pg_ident.conf" version)}})) + +(defmethod layout-settings :arch + [os-family package-source version] + {:post [(validate Layout %)]} + (deep-merge + (base-layout) + {:components [] + :default-cluster-name "data" + :initdb-via :initdb + :wal_directory "/var/lib/postgres/%%s/archive/" + :postgresql_file "/var/lib/postgres/%%s/postgresql.conf" + :options + {:data_directory "/var/lib/postgres/%%s/" + :hba_file "/var/lib/postgres/%%s/pg_hba.conf" + :ident_file "/var/lib/postgres/%%s/pg_ident.conf"}})) diff --git a/test/pallet/crate/postgres/config_test.clj b/test/pallet/crate/postgres/config_test.clj new file mode 100644 index 0000000..dd01d19 --- /dev/null +++ b/test/pallet/crate/postgres/config_test.clj @@ -0,0 +1,10 @@ +(ns pallet.crate.postgres.config-test + (:require + [clojure.test :refer :all] + [pallet.crate.postgres.config :refer [conf hba]])) + +(deftest hba-test + (is (= "" (hba [])))) + +(deftest conf-test + (is (= "" (conf [])))) diff --git a/test/pallet/crate/postgres/kb_test.clj b/test/pallet/crate/postgres/kb_test.clj new file mode 100644 index 0000000..5dc21da --- /dev/null +++ b/test/pallet/crate/postgres/kb_test.clj @@ -0,0 +1,21 @@ +(ns pallet.crate.postgres.kb-test + (:require + [clojure.test :refer :all] + [pallet.crate.postgres.kb :as kb])) + +;; This is brittle +(deftest pgdg-url-test + (is (= "http://yum.postgresql.org/9.3/fedora/fedora-19-x86_64/pgdg-fedora93-9.3-1.noarch.rpm" + (kb/pgdg-url "9.3" :fedora "19" "x86_64"))) + (is (= "http://yum.postgresql.org/9.3/fedora/fedora-20-i386/pgdg-fedora93-9.3-1.noarch.rpm" + (kb/pgdg-url "9.3" :fedora "20" "i386"))) + (is (= "http://yum.postgresql.org/9.3/redhat/rhel-6-i386/pgdg-redhat93-9.3-1.noarch.rpm" + (kb/pgdg-url "9.3" :rhel "6" "i386"))) + (is (= "http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/pgdg-centos93-9.3-1.noarch.rpm" + (kb/pgdg-url "9.3" :centos "6" "x86_64")))) + +(deftest layout-settings-test + (is + (-> + (kb/layout-settings :ubuntu :debian-base "9.1") + :options :data_directory))) diff --git a/test/pallet/crate/postgres/support_test.clj b/test/pallet/crate/postgres/support_test.clj new file mode 100644 index 0000000..acc26ac --- /dev/null +++ b/test/pallet/crate/postgres/support_test.clj @@ -0,0 +1,102 @@ +(ns pallet.crate.postgres.support-test + (:require + [clojure.test :refer :all] + [pallet.actions + :refer [exec-checked-script package package-manager minimal-packages]] + [pallet.api :refer [lift plan-fn group-spec]] + [pallet.core.api :refer [phase-errors]] + [pallet.crate.automated-admin-user :as automated-admin-user] + [pallet.crate.network-service :refer [wait-for-port-listen]] + [pallet.crate.postgres :as postgres] + [pallet.crates.test-nodes :as test-nodes] + [pallet.repl :refer [explain-session]] + [pallet.test-env + :refer [*compute-service* *node-spec-meta* + with-group-spec test-env unique-name]] + [pallet.test-env.project :as project])) + +(test-env test-nodes/node-specs project/project) + +(deftest ^:support port-listen-test + (let [spec (group-spec (unique-name) + :node-spec (:node-spec *node-spec-meta*) + :extends [automated-admin-user/with-automated-admin-user + (postgres/server-spec + (postgres/settings-map + {:options {:listen_addresses "*"} + :permissions + [{:connection-type "host" + :database "all" + :user "all" + :address "10.0.2.2/24" + :auth-method "md5"} + {:connection-type "host" + :database "all" + :user "all" + :address "192.168.56.1/24" + :auth-method "md5"}]}))] + :phases {:settings (plan-fn + ;; (postgres/cluster-settings + ;; "db1" {:options {:port 5432}}) + ) + :init (plan-fn + (postgres/create-database "db") + (postgres/create-role + "u3" + :user-parameters [:login :encrypted + :password ""'mypasswd'""])) + :test (plan-fn + (wait-for-port-listen 5432))})] + (with-group-spec spec + (let [session (lift spec + :phase [:install :configure :init :test] + :compute *compute-service*)] + (testing "configure postgres" + (is session) + (is (not (phase-errors session))) + (when (phase-errors session) + (explain-session session))))))) + +(deftest postgres + (let [spec (group-spec (unique-name) + :phases + {:bootstrap (plan-fn + (minimal-packages) + (package-manager :update) + (automated-admin-user/automated-admin-user)) + :settings (plan-fn + (postgres/settings (postgres/settings-map {})) + (postgres/cluster-settings "db1" {:options {:port 5433}})) + :configure (plan-fn (postgres/install)) + :verify (plan-fn + (postgres/log-settings) + (postgres/initdb) + (postgres/initdb :cluster "db1") + (postgres/hba-conf) + (postgres/hba-conf :cluster "db1") + (postgres/postgresql-conf) + (postgres/postgresql-conf :cluster "db1") + (postgres/service-config) + (postgres/service :action :restart :if-config-changed false) + (postgres/create-database "db") + (postgres/postgresql-script + :content "create temporary table table1 ();" + :show-stdout true) + (postgres/create-role "user1") + (postgres/create-database "db" :cluster "db1") + (postgres/create-role "user1" :cluster "db1") + (postgres/postgresql-script + :content "create temporary table table2 ();" + :show-stdout true :cluster "db1") + (wait-for-port-listen 5432) + (wait-for-port-listen 5433))} + :count 1 + :node-spec (:node-spec *node-spec-meta*))] + (let [session (lift spec + :phase [:settings :install :configure :init :verify] + :compute *compute-service*)] + (testing "configure postgres" + (is session) + (is (not (phase-errors session))) + (when (phase-errors session) + (explain-session session)))))) diff --git a/test/pallet/crate/postgres_test.clj b/test/pallet/crate/postgres_test.clj index 5a12378..f7d8d23 100644 --- a/test/pallet/crate/postgres_test.clj +++ b/test/pallet/crate/postgres_test.clj @@ -29,37 +29,26 @@ :recovery {:bb 2} :start {:start :disable}})))) -(deftest default-settings-test - (is - (-> - (with-script-language :pallet.stevedore.bash/bash - (with-script-context [:ubuntu :aptitude] - (postgres/default-settings - {:server {:image {:os-family :ubuntu} :node-id :id}} - :debian :debian-base (postgres/settings-map {})))) - :options :data_directory))) (deftest settings-test - (let [settings (with-script-language :pallet.stevedore.bash/bash - (with-script-context [:ubuntu :aptitude] - (postgres/settings - {:server {:image {:os-family :ubuntu} :node-id :id}} - (postgres/settings-map - {:layout :debian-base}))))] - (is - (-> - settings - :parameters :host :id :postgresql :default :options :data_directory)))) + (build-actions {} + (let [settings (postgres/settings + (postgres/settings-map + {:layout :debian-base}))] + (is + (get-in + settings + [:plan-state :host :id postgres/facility nil :options :data_directory]))))) (deftest postgres-test (is ; just check for compile errors for now (build-actions {} (postgres/settings (postgres/settings-map {:version "8.0"})) - (postgres/install) + (postgres/install {}) (postgres/settings (postgres/settings-map {:version "9.0"})) (postgres/cluster-settings "db1" {}) - (postgres/install) - (postgres/hba-conf) + (postgres/install {}) + (postgres/hba-conf {}) (postgres/postgresql-script :content "some script") (postgres/create-database "db") (postgres/create-role "user")))) @@ -75,82 +64,11 @@ (postgres/cluster-settings "db2" {}) (postgres/settings (postgres/settings-map {:version "9.0"})))) - pg-settings (-> settings :parameters :host :id :postgresql :default)] + pg-settings (get-in settings + [:plan-state :host :id postgres/facility nil])] (is (-> pg-settings :clusters :db1)) (is (-> pg-settings :clusters :db2)) (is (re-find #"db1/archive" (-> pg-settings :clusters :db1 :wal_directory))) (is (re-find #"db2/archive" (-> pg-settings :clusters :db2 :wal_directory))))) - - -(def test-server-spec - (server-spec - :extends [(postgres/server-spec - (postgres/settings-map {:options {:listen_addresses "*"} - :permissions - [{:connection-type "host" - :database "all" - :user "all" - :address "10.0.2.2/24" - :auth-method "trust"}]}))] - :phases {:settings (plan-fn - ;; (postgres/cluster-settings - ;; "db1" {:options {:port 5432}}) - ) - :init (plan-fn - (postgres/create-database "db") - (postgres/create-role "u1")) - :test (plan-fn - (wait-for-port-listen 5432))})) - - -(def pgsql-9-unsupported - [{:os-family :debian :os-version-matches "5.0.7"} - {:os-family :debian :os-version-matches "5.0"}]) - -(deftest live-test - (live-test/test-for - [image (live-test/exclude-images (live-test/images) pgsql-9-unsupported)] - (logging/tracef "postgres live test: image %s" (pr-str image)) - (live-test/test-nodes - [compute node-map node-types] - {:pgtest - (-> - (server-spec - :phases - {:bootstrap (plan-fn - (minimal-packages) - (package-manager :update) - (automated-admin-user/automated-admin-user)) - :settings (plan-fn - (postgres/settings (postgres/settings-map {})) - (postgres/cluster-settings "db1" {:options {:port 5433}})) - :configure (plan-fn (postgres/install)) - :verify (plan-fn - (postgres/log-settings) - (postgres/initdb) - (postgres/initdb :cluster "db1") - (postgres/hba-conf) - (postgres/hba-conf :cluster "db1") - (postgres/postgresql-conf) - (postgres/postgresql-conf :cluster "db1") - (postgres/service-config) - (postgres/service :action :restart :if-config-changed false) - (postgres/create-database "db") - (postgres/postgresql-script - :content "create temporary table table1 ();" - :show-stdout true) - (postgres/create-role "user1") - (postgres/create-database "db" :cluster "db1") - (postgres/create-role "user1" :cluster "db1") - (postgres/postgresql-script - :content "create temporary table table2 ();" - :show-stdout true :cluster "db1") - (wait-for-port-listen 5432) - (wait-for-port-listen 5433))} - :count 1 - :node-spec (node-spec :image image)))} - (is - (lift - (val (first node-types)) :phase [:settings :verify] :compute compute))))) From b5c119193675ea888c9920a131461fe2b18032a9 Mon Sep 17 00:00:00 2001 From: Hugo Duncan Date: Tue, 29 Apr 2014 14:44:43 -0400 Subject: [PATCH 10/12] WIP - simple amazon linux support test passing --- profiles.clj | 12 ++++++++ src/pallet/crate/postgres.clj | 39 +++++------------------ src/pallet/crate/postgres/kb.clj | 53 ++++++++++++++++++++++++-------- 3 files changed, 59 insertions(+), 45 deletions(-) diff --git a/profiles.clj b/profiles.clj index 7120acf..94f2871 100644 --- a/profiles.clj +++ b/profiles.clj @@ -9,5 +9,17 @@ :provided {:dependencies [[org.clojure/clojure "1.6.0"] [com.palletops/pallet "0.8.0-SNAPSHOT"]]} + :aws {:pallet/test-env + {:test-specs + [;; {:selector :ubuntu-13-10} + ;; {:selector :ubuntu-13-04 + ;; :expected [{:feature ["oracle-java-8"] + ;; :expected? :not-supported}]} + ;; {:selector :ubuntu-12-04} + {:selector :amzn-linux-2013-092} + ;; {:selector :centos-6-5} + ;; {:selector :debian-7-4} + ;; {:selector :debian-6-0} + ]}} :vmfest {:pallet/test-env {:test-specs [{:selector :ubuntu-13-04}]}}} diff --git a/src/pallet/crate/postgres.clj b/src/pallet/crate/postgres.clj index 0771916..9e3c282 100644 --- a/src/pallet/crate/postgres.clj +++ b/src/pallet/crate/postgres.clj @@ -89,7 +89,8 @@ Links: (let [arch (if (is-64bit? (target-node)) "x86_64" "i386")] {:install-strategy :rpm-repo :rpm {:name "pgdg.rpm" - :url (kb/pgdg-url (version-string version) os-family os-version arch)} + :url (kb/pgdg-url + (version-string version) os-family os-version arch)} :packages (kb/pgdg-packages (version-string version) components) @@ -110,19 +111,14 @@ Links: {:install-strategy :packages :packages (kb/yum-packages (version-string version) - (or components #{:server :libs})) - :layout :rh-base}) + (or components #{:server :libs}))}) (defn apt-packages-settings [version components] {:install-strategy :packages :packages (kb/apt-packages (version-string version) - components) - :layout :debian-base}) - -;; (def xx "aa" :a :b -;; ) + components)}) (defmulti-version-plan install-strategy ;; Default install strategy, if none supplied. @@ -136,28 +132,6 @@ Links: [os os-version version settings] (apt-packages-settings version nil)) -;; (defmethod-version-plan -;; install-strategy {:os :arch} -;; [os os-version version settings] -;; (-> -;; (cond -;; (:install-strategy settings) settings -;; (:package-source settings) (assoc settings :install-strategy :package-source) -;; :else (let [default-version (os-map-lookup @postgres-package-version) -;; target-version (:version settings)] -;; (if (= (version-string default-version) target-version) -;; (assoc settings -;; :install-strategy :packages -;; :packages ["postgresql"] -;; :layout :arch) -;; (throw -;; (ex-info -;; (format "No install strategy for postgres %s on %s %s" -;; version os os-version) -;; {:reason :no-install-strategy -;; :version version :os os :os-version os-version}))))))) - - ;;; Default settings (def default-settings-map {:components #{:server :contrib} @@ -349,6 +323,7 @@ Links: :hot-standby-master (hot-standby-master settings) :hot-standby-replica (hot-standby-replica settings) settings)] + (logging/debugf "Postgresql cluster %s settings %s" cluster-name settings) (update-settings facility instance-id assoc-in [:clusters (keyword cluster-name)] @@ -373,7 +348,7 @@ Links: (merge (install-strategy version settings) settings)) settings (merge-settings (kb/layout-settings - (os-family) (:layout settings) version) + (os-family) (:layout settings (os-family)) version) settings) old-settings (get-settings facility options)] (logging/debugf "Postgresql Settings %s" settings) @@ -498,7 +473,7 @@ Links: (if (not (file-exists? ~(str data-dir "/PG_VERSION"))) ("sudo" -u ~(:owner settings "postgres") - (str ~(or (:bin settings) "") initdb) + (lib/file ~(:bin settings) initdb) -D ~data-dir))))))) ;;; Scripts diff --git a/src/pallet/crate/postgres/kb.clj b/src/pallet/crate/postgres/kb.clj index d81d38e..b52f497 100644 --- a/src/pallet/crate/postgres/kb.clj +++ b/src/pallet/crate/postgres/kb.clj @@ -1,7 +1,7 @@ (ns pallet.crate.postgres.kb "Knowledge base for postgres install and configuration" (:require - [clojure.string :as string] + [clojure.string :as string :refer [split]] [pallet.version-dispatch :refer [os-map]] [pallet.compute :refer [os-hierarchy]] [pallet.utils :refer [deep-merge]] @@ -32,7 +32,10 @@ (fn [os-family layout version] {:pre [(keyword? layout) (string? version)]} - layout)) + layout) + :hierarchy #'os-hierarchy) + +(prefer-method layout-settings :amzn-linux :rh-base) (defn base-layout "Base layout used as a default with common options." @@ -55,6 +58,7 @@ (atom ; allow for open extension (os-map {{:os :linux} [8] + {:os :amzn-linux :os-version [[2013]]} [9 2] {:os :ubuntu :os-version [[12] [13 10]]} [9 1] {:os :ubuntu :os-version [[14 04]]} [9 3]}))) @@ -66,7 +70,7 @@ [version components] {:pre [(string? version)]} (map - #(format "postgresql-%s-%s" (name %) version) + #(format "postgresql%s-%s" (first (split version #"\.")) (name %)) components)) ;;; ## Apt system packages @@ -175,16 +179,39 @@ (defmethod layout-settings :rh-base [os-family layout version] {:post [(validate Layout %)]} - (deep-merge - (base-layout) - {:default-cluster-name "data" - :wal_directory (format "/var/lib/pgsql/%s/%%s/archive" version) - :postgresql_file (format "/var/lib/pgsql/%s/%%s/postgresql.conf" version) - :options - {:data_directory (format "/var/lib/pgsql/%s/%%s" version) - :hba_file (format "/var/lib/pgsql/%s/%%s/pg_hba.conf" version) - :ident_file (format "/var/lib/pgsql/%s/%%s/pg_ident.conf" version) - :external_pid_file (format "/var/run/postmaster-%s-%%s.pid" version)}})) + (let [major (first (split version #"\."))] + (deep-merge + (base-layout) + {:bin "/usr/bin" + :default-cluster-name "data" + :share "/usr/share/pgsql" + :wal_directory (format "/var/lib/pgsql/%s/%%s/archive" version) + :postgresql_file (format "/var/lib/pgsql/%s/%%s/postgresql.conf" version) + :options + {:data_directory (format "/var/lib/pgsql/%s/%%s" version) + :hba_file (format "/var/lib/pgsql/%s/%%s/pg_hba.conf" version) + :ident_file (format "/var/lib/pgsql/%s/%%s/pg_ident.conf" version) + :external_pid_file (format "/var/run/postmaster-%s-%%s.pid" version) + :unix_socket_directory "/var/run/postgresql"}}))) + +(defmethod layout-settings :amzn-linux + [os-family layout version] + {:post [(validate Layout %)]} + (let [major (first (split version #"\.")) + data (format "/var/lib/pgsql%s/data/" major)] + (deep-merge + (base-layout) + {:bin "/usr/bin" + :default-cluster-name "data" + :share "/usr/share/pgsql" + :wal_directory (format "%s/%%s/archive" data) + :postgresql_file (format "%s/%%s/postgresql.conf" data) + :options + {:data_directory data + :hba_file (format "%s/pg_hba.conf" data) + :ident_file (format "%s/pg_ident.conf" data) + :external_pid_file (format "/var/run/postmaster-%s.pid" version) + :unix_socket_directory "/var/run/postgresql"}}))) (defmethod layout-settings :pgdg [os-family package-source version] From 0ec01258be6c044d5e2cc88fcf43927403f6aeea Mon Sep 17 00:00:00 2001 From: Hugo Duncan Date: Tue, 29 Apr 2014 16:10:47 -0400 Subject: [PATCH 11/12] WIP - simple debian support test passing --- profiles.clj | 6 +++--- src/pallet/crate/postgres/kb.clj | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/profiles.clj b/profiles.clj index 94f2871..692eee0 100644 --- a/profiles.clj +++ b/profiles.clj @@ -16,9 +16,9 @@ ;; :expected [{:feature ["oracle-java-8"] ;; :expected? :not-supported}]} ;; {:selector :ubuntu-12-04} - {:selector :amzn-linux-2013-092} - ;; {:selector :centos-6-5} - ;; {:selector :debian-7-4} + ;; {:selector :amzn-linux-2013-092} + {:selector :centos-6-5} + ;; {:selector :debian-7-5} ;; {:selector :debian-6-0} ]}} :vmfest {:pallet/test-env {:test-specs diff --git a/src/pallet/crate/postgres/kb.clj b/src/pallet/crate/postgres/kb.clj index b52f497..0c53c91 100644 --- a/src/pallet/crate/postgres/kb.clj +++ b/src/pallet/crate/postgres/kb.clj @@ -59,6 +59,9 @@ (os-map {{:os :linux} [8] {:os :amzn-linux :os-version [[2013]]} [9 2] + {:os :debian :os-version [6]} [8 4] + {:os :debian :os-version [7]} [9 1] + {:os :debian :os-version [8]} [9 3] {:os :ubuntu :os-version [[12] [13 10]]} [9 1] {:os :ubuntu :os-version [[14 04]]} [9 3]}))) From a28a42ebfd8d815d2cedd760be3ee1d88bcfaf85 Mon Sep 17 00:00:00 2001 From: Hugo Duncan Date: Wed, 30 Apr 2014 16:33:38 -0400 Subject: [PATCH 12/12] WIP - simple centos support test passing --- src/pallet/crate/postgres.clj | 77 +++++++++++++++++++++++++------- src/pallet/crate/postgres/kb.clj | 54 +++++++++++++++------- 2 files changed, 99 insertions(+), 32 deletions(-) diff --git a/src/pallet/crate/postgres.clj b/src/pallet/crate/postgres.clj index 9e3c282..c7a4144 100644 --- a/src/pallet/crate/postgres.clj +++ b/src/pallet/crate/postgres.clj @@ -106,17 +106,11 @@ Links: :packages (kb/postgres-apt-packages (version-string version)) :layout :debian-base}) -(defn yum-packages-settings +(defn packages-settings [version components] {:install-strategy :packages - :packages (kb/yum-packages - (version-string version) - (or components #{:server :libs}))}) - -(defn apt-packages-settings - [version components] - {:install-strategy :packages - :packages (kb/apt-packages + :packages (kb/package-names + (os-family) (version-string version) components)}) @@ -126,11 +120,11 @@ Links: (defmethod-version-plan install-strategy {:os :rh-base} [os os-version version settings] - (yum-packages-settings version nil)) + (packages-settings version nil)) (defmethod-version-plan install-strategy {:os :debian-base} [os os-version version settings] - (apt-packages-settings version nil)) + (packages-settings version nil)) ;;; Default settings (def default-settings-map @@ -142,7 +136,8 @@ Links: :shared_buffers "24MB" :log_line_prefix "%t " :datestyle "iso, ymd" - :default_text_search_config "pg_catalog.english"} + :default_text_search_config "pg_catalog.english" + :logging_collector "on"} :permissions [["local" "all" "postgres" "ident" ""] ["local" "postgres" "postgres" "ident" ""]] :start {:start :auto} @@ -275,7 +270,11 @@ Links: :content hba-contents :literal true :flag-on-changed postgresql-config-changed-flag - :owner (:owner settings)))) + :owner (:owner settings)) + (when-let [t (:selunix-file-t settings)] + (exec-checked-script + (str "SELinux chcon " conf-path " type " t) + (lib/selinux-file-type ~conf-path ~t))))) (defn default-cluster-name "Returns the default cluster name" @@ -450,7 +449,50 @@ Links: (start-conf options) (install-service options)))) -; (declare service) +(defn- port-config* [settings] + (when-let [t (:selunix-port-t settings)] + (let [p (-> settings :options :port)] + (exec-checked-script + (str "SELinux manage port " p " type " t) + (if (&& (lib/has-command? semanage) + (&& (directory? "/etc/selinux") + (file-exists? "/selinux/enforce"))) + (if (pipe ("semanage" port -l) ("fgrep" ~p)) + ("semanage" port -m -t ~t -p tcp ~p) + ("semanage" port -a -t ~t -p tcp ~p))))))) + +(defn port-config + "Manage the SELinux port type of the configured port" + [{:keys [instance-id cluster] :as options}] + (let [settings (get-settings facility options)] + (if (:has-multicluster-service settings) + (doseq [cluster (keys (:clusters settings)) + :let [cluster-name (name cluster) + cluster-settings (settings-for-cluster + cluster-name options)]] + (port-config* cluster-settings)) + (port-config* settings)))) + +(defn dir-config* + [{:keys [owner selunix-file-t options] :as settings}] + (let [d (:unix_socket_directory options)] + (directory d :owner owner) + (when selunix-file-t + (exec-checked-script + (str "SELinux chcon " d " type " selunix-file-t) + (lib/selinux-file-type ~d ~selunix-file-t))))) + +(defn dir-config + "Ensure required directories exist" + [{:keys [instance-id cluster] :as options}] + (let [settings (get-settings facility options)] + (if (:has-multicluster-service settings) + (doseq [cluster (keys (:clusters settings)) + :let [cluster-name (name cluster) + cluster-settings (settings-for-cluster + cluster-name options)]] + (dir-config* settings)) + (dir-config* settings)))) (defn initdb "Initialise a cluster" @@ -520,7 +562,8 @@ Links: ~(if (:has-pg-wrapper settings) "" (format - "env PGDATA=%s PGPORT=%s" + "env PGHOST=%s PGDATA=%s PGPORT=%s" + (-> cluster-settings :options :unix_socket_directory) (-> cluster-settings :options :data_directory) (-> cluster-settings :options :port))) psql @@ -665,7 +708,9 @@ END$$;" (initdb options) (hba-conf options) (postgresql-conf options) - (service-config options)) + (service-config options) + (port-config options) + (dir-config options)) (defn server-spec diff --git a/src/pallet/crate/postgres/kb.clj b/src/pallet/crate/postgres/kb.clj index 0c53c91..227c4aa 100644 --- a/src/pallet/crate/postgres/kb.clj +++ b/src/pallet/crate/postgres/kb.clj @@ -5,7 +5,7 @@ [pallet.version-dispatch :refer [os-map]] [pallet.compute :refer [os-hierarchy]] [pallet.utils :refer [deep-merge]] - [schema.core :as schema :refer [enum validate]])) + [schema.core :as schema :refer [enum maybe validate]])) (def Layout {:bin String @@ -20,6 +20,8 @@ :use-port-in-pidfile schema/Bool :owner String :wal_directory String + :selunix-port-t (maybe String) + :selunix-file-t (maybe String) :options {:external_pid_file String :data_directory String :hba_file String @@ -46,6 +48,8 @@ :has-multicluster-service false :initdb-via :initdb :use-port-in-pidfile false + :selunix-port-t nil + :selunix-file-t nil :options {:external_pid_file "/var/run/postgresql.pid"}}) @@ -58,6 +62,7 @@ (atom ; allow for open extension (os-map {{:os :linux} [8] + {:os :centos :os-version [6]} [8 4] {:os :amzn-linux :os-version [[2013]]} [9 2] {:os :debian :os-version [6]} [8 4] {:os :debian :os-version [7]} [9 1] @@ -67,20 +72,33 @@ ;;; ## Yum system packages -(defn yum-packages - "Return a sequence of package names for system packages on yum based - systems." - [version components] +(defmulti package-names + "Return a sequence of package names for system packages." + (fn [os version components] + os) + :hierarchy #'os-hierarchy) + +(prefer-method package-names :amzn-linux :rh-base) + +(defmethod package-names :rh-base + [os version components] + {:pre [(string? version)]} + (conj + (map + #(format "postgresql-%s" (name %)) + (or components #{:server :libs})) + "postgresql")) + +(defmethod package-names :amzn-linux + [os version components] {:pre [(string? version)]} (map #(format "postgresql%s-%s" (first (split version #"\.")) (name %)) - components)) + (or components #{:server :libs}))) ;;; ## Apt system packages -(defn apt-packages - "Return a sequence of package names for system packages on apt based - systems." - [version components] +(defmethod package-names :debian-base + [os version components] {:pre [(string? version)]} (conj (map @@ -88,6 +106,8 @@ components) (format "postgresql-%s" version))) +(prefer-method package-names :amzn-linux :rh-base) + ;;; # Postgres RPM Repository ;;; See http://yum.postgresql.org/ @@ -188,13 +208,15 @@ {:bin "/usr/bin" :default-cluster-name "data" :share "/usr/share/pgsql" - :wal_directory (format "/var/lib/pgsql/%s/%%s/archive" version) - :postgresql_file (format "/var/lib/pgsql/%s/%%s/postgresql.conf" version) + :wal_directory "/var/lib/pgsql/archive" + :postgresql_file "/var/lib/pgsql/data/postgresql.conf" + :selunix-port-t "postgresql_port_t" + :selunix-file-t "postgresql_db_t" :options - {:data_directory (format "/var/lib/pgsql/%s/%%s" version) - :hba_file (format "/var/lib/pgsql/%s/%%s/pg_hba.conf" version) - :ident_file (format "/var/lib/pgsql/%s/%%s/pg_ident.conf" version) - :external_pid_file (format "/var/run/postmaster-%s-%%s.pid" version) + {:data_directory "/var/lib/pgsql/data" + :hba_file "/var/lib/pgsql/data/pg_hba.conf" + :ident_file "/var/lib/pgsql/data/pg_ident.conf" + :external_pid_file "/var/run/postmaster.pid" :unix_socket_directory "/var/run/postgresql"}}))) (defmethod layout-settings :amzn-linux