From 607c3aabe3639fa0465d26f767d5cb099795e62c Mon Sep 17 00:00:00 2001 From: Hugo Duncan Date: Tue, 20 Aug 2013 07:29:41 -0400 Subject: [PATCH 1/3] Add deploy recipe for pallet deploy of an app This recipe uses pallet to deploy an artifact from a maven repository. It illustrates the recipe based on deploying a Jenkins instance on EC2. --- .../deploy.asciidoc | 119 ++++++++++++++++++ .../deployer/README.md | 13 ++ .../deployer/pallet.clj | 10 ++ .../deployer/project.clj | 30 +++++ .../deployer/resources/logback.xml | 104 +++++++++++++++ .../deployer/src/deployer/groups/deployer.clj | 37 ++++++ deployment/deployment.asciidoc | 1 + 7 files changed, 314 insertions(+) create mode 100644 deployment/deploy-application-with-pallet/deploy.asciidoc create mode 100644 deployment/deploy-application-with-pallet/deployer/README.md create mode 100644 deployment/deploy-application-with-pallet/deployer/pallet.clj create mode 100644 deployment/deploy-application-with-pallet/deployer/project.clj create mode 100644 deployment/deploy-application-with-pallet/deployer/resources/logback.xml create mode 100644 deployment/deploy-application-with-pallet/deployer/src/deployer/groups/deployer.clj diff --git a/deployment/deploy-application-with-pallet/deploy.asciidoc b/deployment/deploy-application-with-pallet/deploy.asciidoc new file mode 100644 index 00000000..b066f721 --- /dev/null +++ b/deployment/deploy-application-with-pallet/deploy.asciidoc @@ -0,0 +1,119 @@ +//// +:Author: Hugo Duncan +:Email: hugo@hugoduncan.org +//// + +=== Deploy your Clojure Application + +(((Embedded jetty))) +(((jenkins))) + +===== Problem + +You have a clojure application, containing a +main+, and packaged with +lein uberjar+. You want to deploy your clojure application to a server, and run it under process supervision. + +===== Solution + +Use http://palletops.com/[Pallet] to deploy your application to EC2 +(or elsewhere), using http://smarden.org/runit/[runit] to supervise the server +process. + +To demonstrate this, we're going to deploy +http://jenkins-ci.org/[jenkins] using its embedded jetty server. + +To get started you create a new project with leiningen, using the +pallet+ template: + +[source,console] +---- +$ lein new pallet deployer +---- + +Add the +app-deploy-crate+, +java-crate+ and +runit-crate+ to your +:dependencies+ in +the generated +project.clj+ file. Pallet crates are jar files that +contain functions for installing, configuring and running a specific +library or application. + +[source, clojure] +---- +:dependencies [... + [com.palletops/app-deploy-crate "0.8.0-alpha.3"] + [com.palletops/java-crate "0.8.0-beta.5"] + [com.palletops/runit-crate "0.8.0-alpha.1"] + ...] +---- + +We will require these crates in the definition of the +server-spec+ +used by pallet to describe what we want on the server. + +[source, clojure] +---- +(ns deployer.groups.deployer + "Node defintions for deployer" + (:require + [pallet.api :refer [group-spec server-spec node-spec plan-fn]] + [pallet.crate.automated-admin-user :refer [automated-admin-user]] + [pallet.crate.app-deploy :as app-deploy] + [pallet.crate.java :as java] + [pallet.crate.runit :as runit])) + +... + +(def + ^{:doc "Define a server spec for deployer"} + deployer-server + (server-spec + :extends ; <1> + [(java/server-spec {}) + (runit/server-spec {}) + (app-deploy/server-spec + {:app-root "/opt/jenkins" ; <2> + :artifacts + {:from-maven-repo + [{:coord '[org.jenkins-ci.main/jenkins-war "1.529" :extension "war"] + :path "jenkins.war"}]} + :repositories {"jenkins" ; <3> + {:url "http://repo.jenkins-ci.org/public"}} + :run-command "java -jar /opt/jenkins/jenkins.war"}) + (runit/server-spec {})])) ; <4> +... +---- + + 1. extends allows you to compose other +sever-spec+ definitions + 2. the +:app-root+ determines the root directory for the deployment artifacts + 3. your project uberjar will be found by looking in a specific repository + 4. ensures runit is installed + +Now we have the server described, we need to tell Pallet the +credentials we want to use on EC2: + +[source,console] +---- +$ lein pallet add-service aws aws-ec2 "your-aws-key" "your-aws-secret-key" +---- + +Deploy jenkins on a new ec2 node: + +[source,console] +---- +$ lein pallet up --phases install,configure,deploy +---- + +Jenkins will now be running on port 8080. + +You can redploy your application with: + +[source,console] +---- +$ lein pallet up --phases deploy +---- + +===== Discussion + +You have many choices of where to run a server; on EC2 or other cloud, on a VPS host, or on some dedicated machine. Using http://palletops.com/[Pallet], you can deploy to any of these environments using the same code. + +There are also many process supervision frameworks to choose from. We haveusedhttp://smarden.org/runit/[runit] which is the default for the +app-deploy+ crate, but you can use +upstart+ or +initd+, +for example. + +===== See Also + +* <> on using chef or puppet to deploy diff --git a/deployment/deploy-application-with-pallet/deployer/README.md b/deployment/deploy-application-with-pallet/deployer/README.md new file mode 100644 index 00000000..55e21c2c --- /dev/null +++ b/deployment/deploy-application-with-pallet/deployer/README.md @@ -0,0 +1,13 @@ +# deployer + +A pallet project designed to ... well, that part is up to you. + +## Usage + +FIXME + +## License + +Copyright © FIXME + +Distributed under the Eclipse Public License. diff --git a/deployment/deploy-application-with-pallet/deployer/pallet.clj b/deployment/deploy-application-with-pallet/deployer/pallet.clj new file mode 100644 index 00000000..d76f81f3 --- /dev/null +++ b/deployment/deploy-application-with-pallet/deployer/pallet.clj @@ -0,0 +1,10 @@ +(require + '[deployer.groups.deployer :refer [deployer]]) + +(defproject deployer + :provider {:jclouds + {:node-spec + {:image {:os-family :ubuntu :os-version-matches "12.04" + :os-64-bit true}}}} + + :groups [deployer]) diff --git a/deployment/deploy-application-with-pallet/deployer/project.clj b/deployment/deploy-application-with-pallet/deployer/project.clj new file mode 100644 index 00000000..fbe7528a --- /dev/null +++ b/deployment/deploy-application-with-pallet/deployer/project.clj @@ -0,0 +1,30 @@ +(defproject deployer "0.1.0-SNAPSHOT" + :description "FIXME Pallet project for deployer" + :dependencies [[org.clojure/clojure "1.4.0"] + [com.palletops/pallet "0.8.0-RC.1"] + [com.palletops/pallet-jclouds "1.5.3"] + [com.palletops/app-deploy "0.8.0-alpha.2"] + [com.palletops/runit "0.8.0-alpha.1"] + ;; To get started we include all jclouds compute providers. + ;; You may wish to replace this with the specific jclouds + ;; providers you use, to reduce dependency sizes. + [org.jclouds/jclouds-allblobstore "1.5.5"] + [org.jclouds/jclouds-allcompute "1.5.5"] + [org.jclouds.driver/jclouds-slf4j "1.5.5" + ;; the declared version is old and can overrule the + ;; resolved version + :exclusions [org.slf4j/slf4j-api]] + [org.jclouds.driver/jclouds-sshj "1.5.5"] + [ch.qos.logback/logback-classic "1.0.9"]] + :profiles {:dev + {:dependencies + [[com.palletops/pallet "0.8.0-RC.1" + :classifier "tests"]] + :plugins + [[com.palletops/pallet-lein "0.8.0-alpha.1"]]} + :leiningen/reply + {:dependencies [[org.slf4j/jcl-over-slf4j "1.7.2"]] + :exclusions [commons-logging]}} + :local-repo-classpath true + :repositories + {"sonatype" "https://oss.sonatype.org/content/repositories/releases/"}) diff --git a/deployment/deploy-application-with-pallet/deployer/resources/logback.xml b/deployment/deploy-application-with-pallet/deployer/resources/logback.xml new file mode 100644 index 00000000..b4a84195 --- /dev/null +++ b/deployment/deploy-application-with-pallet/deployer/resources/logback.xml @@ -0,0 +1,104 @@ + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + INFO + + + + + 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 + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/deployment/deploy-application-with-pallet/deployer/src/deployer/groups/deployer.clj b/deployment/deploy-application-with-pallet/deployer/src/deployer/groups/deployer.clj new file mode 100644 index 00000000..a51073a6 --- /dev/null +++ b/deployment/deploy-application-with-pallet/deployer/src/deployer/groups/deployer.clj @@ -0,0 +1,37 @@ +(ns deployer.groups.deployer + "Node defintions for deployer" + (:require + [pallet.core :refer [group-spec server-spec node-spec plan-fn]] + [pallet.crate.automated-admin-user :refer [automated-admin-user]] + [pallet.crate.app-deploy :as app-deploy] + [pallet.crate.runit :as runit])) + +(def default-node-spec + (node-spec + :image {:os-family :ubuntu} + :hardware {:min-cores 1})) + +(def + ^{:doc "Defines the type of node deployer will run on"} + base-server + (server-spec + :phases + {:bootstrap (plan-fn (automated-admin-user))})) + +(def + ^{:doc "Define a server spec for deployer"} + deployer-server + (server-spec + :extends [(app-deploy/server-spec + {:artifacts + {:from-maven-repo [{:coord '[your-project-id "0.1.0"] + :path "your-project.jar"}]}}) + (runit/server-spec {})])) + +(def + ^{:doc "Defines a group spec that can be passed to converge or lift."} + deployer + (group-spec + "deployer" + :extends [base-server deployer-server] + :node-spec default-node-spec)) diff --git a/deployment/deployment.asciidoc b/deployment/deployment.asciidoc index 977f8fbf..b21ea49a 100644 --- a/deployment/deployment.asciidoc +++ b/deployment/deployment.asciidoc @@ -2,3 +2,4 @@ == Deployment & Distribution include::deploy-on-lein/deploy-on-lein.asciidoc[] +include::deploy-application-with-pallet/deploy.asciidoc[] From 742ef8cf8738cb26c7f970b6ec368c5cb669eac7 Mon Sep 17 00:00:00 2001 From: Adrian Lanning Date: Thu, 5 Sep 2013 23:11:14 +0800 Subject: [PATCH 2/3] remove redundant (runit/server-spec {}) call; spelling fixes --- deployment/deploy-application-with-pallet/deploy.asciidoc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/deployment/deploy-application-with-pallet/deploy.asciidoc b/deployment/deploy-application-with-pallet/deploy.asciidoc index b066f721..4ce0f6ae 100644 --- a/deployment/deploy-application-with-pallet/deploy.asciidoc +++ b/deployment/deploy-application-with-pallet/deploy.asciidoc @@ -48,7 +48,7 @@ used by pallet to describe what we want on the server. [source, clojure] ---- (ns deployer.groups.deployer - "Node defintions for deployer" + "Node definitions for deployer" (:require [pallet.api :refer [group-spec server-spec node-spec plan-fn]] [pallet.crate.automated-admin-user :refer [automated-admin-user]] @@ -64,7 +64,6 @@ used by pallet to describe what we want on the server. (server-spec :extends ; <1> [(java/server-spec {}) - (runit/server-spec {}) (app-deploy/server-spec {:app-root "/opt/jenkins" ; <2> :artifacts @@ -100,7 +99,7 @@ $ lein pallet up --phases install,configure,deploy Jenkins will now be running on port 8080. -You can redploy your application with: +You can redeploy your application with: [source,console] ---- @@ -111,7 +110,7 @@ $ lein pallet up --phases deploy You have many choices of where to run a server; on EC2 or other cloud, on a VPS host, or on some dedicated machine. Using http://palletops.com/[Pallet], you can deploy to any of these environments using the same code. -There are also many process supervision frameworks to choose from. We haveusedhttp://smarden.org/runit/[runit] which is the default for the +app-deploy+ crate, but you can use +upstart+ or +initd+, +There are also many process supervision frameworks to choose from. We have used http://smarden.org/runit/[runit] which is the default for the +app-deploy+ crate, but you can use +upstart+ or +initd+, for example. ===== See Also From b3ed5de5cf3ad1dff2154e28db81f87a84ddc8e5 Mon Sep 17 00:00:00 2001 From: Hugo Duncan Date: Wed, 11 Sep 2013 08:07:28 -0400 Subject: [PATCH 3/3] Fix extends order --- .../deploy.asciidoc | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/deployment/deploy-application-with-pallet/deploy.asciidoc b/deployment/deploy-application-with-pallet/deploy.asciidoc index 4ce0f6ae..63102078 100644 --- a/deployment/deploy-application-with-pallet/deploy.asciidoc +++ b/deployment/deploy-application-with-pallet/deploy.asciidoc @@ -63,24 +63,25 @@ used by pallet to describe what we want on the server. deployer-server (server-spec :extends ; <1> - [(java/server-spec {}) + [(java/server-spec {}) ; <2> + (runit/server-spec {}) ; <3> (app-deploy/server-spec - {:app-root "/opt/jenkins" ; <2> + {:app-root "/opt/jenkins" ; <4> :artifacts {:from-maven-repo [{:coord '[org.jenkins-ci.main/jenkins-war "1.529" :extension "war"] :path "jenkins.war"}]} - :repositories {"jenkins" ; <3> + :repositories {"jenkins" ; <5> {:url "http://repo.jenkins-ci.org/public"}} - :run-command "java -jar /opt/jenkins/jenkins.war"}) - (runit/server-spec {})])) ; <4> + :run-command "java -jar /opt/jenkins/jenkins.war"})])) ... ---- 1. extends allows you to compose other +sever-spec+ definitions - 2. the +:app-root+ determines the root directory for the deployment artifacts - 3. your project uberjar will be found by looking in a specific repository - 4. ensures runit is installed + 3. ensures java is installed + 3. ensures runit is installed + 4. the +:app-root+ determines the root directory for the deployment artifacts + 5. your project uberjar will be found by looking in a specific repository Now we have the server described, we need to tell Pallet the credentials we want to use on EC2: