├── .gitignore
├── README.md
├── basic
├── .gitignore
├── README.md
├── project.clj
└── src
│ └── demo.clj
├── bin
└── set-version.sh
├── blank-project
├── .gitignore
├── README.md
├── project.clj
├── resources
│ └── logback.xml
├── settings.xml
├── src
│ └── blank_project
│ │ └── core.clj
├── test-resources
│ └── logback-test.xml
└── test
│ └── blank_project
│ └── test
│ └── core.clj
├── check-readmes.sh
├── hudson
├── .gitignore
├── README.md
├── project.clj
├── resources
│ ├── log4j.properties
│ └── log4j.properties.debug
├── src
│ └── hudson
│ │ └── ci.clj
└── test
│ └── hudson
│ └── test
│ └── core.clj
├── integration-tests
├── README
├── cake-test.sh
├── lein-test.sh
└── log4j.properties
├── mini-webapp
├── .gitignore
├── README.md
├── project.clj
├── src
│ ├── mini_webapp
│ │ ├── Servlet.clj
│ │ ├── app.clj
│ │ ├── core.clj
│ │ └── jetty.clj
│ └── web.xml
└── test
│ └── mini_webapp
│ └── test
│ └── core.clj
├── nano-webapp
├── pom.xml
└── src
│ └── main
│ └── webapp
│ ├── WEB-INF
│ └── web.xml
│ └── index.jsp
├── test-all.sh
└── webapp-haproxy-nodes
├── README.md
├── config.clj
├── project.clj
├── resources
└── logback.xml
└── src
└── webapp_nodes
├── crates.clj
└── nodes.clj
/.gitignore:
--------------------------------------------------------------------------------
1 | lein
2 | log
3 | logs
4 | *.war
5 | .cake
6 | checkouts
7 | lib
8 | target
9 | tmp
10 | **/test-resources/log4j.properties
11 | **/pom.xml
12 | integration.log
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # pallet-examples
2 |
3 | This repository contains various examples of using
4 | [pallet](https://github.com/pallet/pallet).
5 |
6 |
7 | project | description |
8 |
9 |
10 | basic |
11 | Basic interactive usage. |
12 |
13 |
14 | blank-project |
15 | A project that is configured to use pallet |
16 |
17 |
18 | webapp-haproxy-nodes |
19 | A muilti-node containing webapp and proxy definitions to setup a number of webapps proxied by one node running haproxy |
20 |
21 |
22 | hudson |
23 | (NOTICE: not yet tested for pallet 0.6.x) A project containing pallet node definition for setting up a hudson ci server |
24 |
25 |
26 |
27 |
28 | 
29 |
30 | ## License
31 |
32 | Copyright (C) 2010 Hugo Duncan
33 |
34 | Distributed under the Eclipse Public License.
35 |
--------------------------------------------------------------------------------
/basic/.gitignore:
--------------------------------------------------------------------------------
1 | pom.xml
2 | *jar
3 | lib
4 | classes
5 |
--------------------------------------------------------------------------------
/basic/README.md:
--------------------------------------------------------------------------------
1 | # basic
2 |
3 | Project with basic pallet usage.
4 |
5 | This project assumes you are using some sort of Linux or Unix. It can
6 | work with Windows too, but you might have to manually setup SSH.
7 |
8 | ## Usage
9 |
10 | - `git clone https://github.com/pallet/pallet-examples` or, download
11 | the [tarball](https://github.com/pallet/pallet-examples/tarball/master).
12 |
13 | - Install [Leiningen](http://github.com/technomancy/leiningen).
14 |
15 | - In a shell, assuming the code is in the pallet-examples directory, enter
16 |
17 | $ cd pallet-examples/basic
18 | $ lein deps
19 | $ lein repl
20 |
21 | - Work through the code in [pallet-examples/basic/src/demo.clj](https://github.com/pallet/pallet-examples/blob/master/basic/src/demo.clj)
22 |
23 | ## License
24 |
25 | Copyright (C) 2010 Hugo Duncan
26 |
27 | Distributed under the Eclipse Public License.
28 |
--------------------------------------------------------------------------------
/basic/project.clj:
--------------------------------------------------------------------------------
1 | (defproject basic "0.6.0"
2 | :description "Basic Pallet Usage"
3 | :dependencies [[org.cloudhoist/pallet "0.6.8"]
4 | [org.cloudhoist/pallet-crates-all "0.5.0"]
5 | ;; jclouds imports
6 | [org.jclouds/jclouds-all "1.2.1"]
7 | [org.jclouds/jclouds-compute "1.2.1"]
8 | [org.jclouds/jclouds-blobstore "1.2.1"]
9 | [org.jclouds.driver/jclouds-jsch "1.2.1"]
10 | [org.jclouds.driver/jclouds-slf4j "1.2.1"]
11 | ;; logging
12 | [ch.qos.logback/logback-core "1.0.0"]
13 | [ch.qos.logback/logback-classic "1.0.0"]]
14 | :dev-dependencies [[swank-clojure/swank-clojure "1.3.2"] ; swank
15 | [org.cloudhoist/pallet-lein "0.4.1"]] ; lein
16 | :repositories
17 | {"sonatype" "http://oss.sonatype.org/content/repositories/releases"})
18 |
--------------------------------------------------------------------------------
/basic/src/demo.clj:
--------------------------------------------------------------------------------
1 | (ns #^{:author "Hugo Duncan"}
2 | demo
3 | "This is an introductory example of using pallet.")
4 |
5 | ;; First we load the pallet commands into
6 | (require 'pallet.repl)
7 | (pallet.repl/use-pallet)
8 | (use '[pallet.phase :only [phase-fn]])
9 |
10 |
11 | ;; Supported providers can be found with:
12 | (supported-providers)
13 |
14 | ;; We provide some credentials to our cloud provider...
15 | (def my-user "your user")
16 | (def my-password "your api key")
17 |
18 | ;; ...and log in to the cloud using the credentials defined above.
19 | ;; provider is a string specifiying the provider, as returned
20 | ;; from (supported-providers). For example, for Amazon Web Service's
21 | ;; EC2, the provider is "aws-ec2"
22 | (def my-service
23 | (compute-service "provider" :identity my-user :credential my-password))
24 |
25 | ;; current compute nodes in your account can be listed with the nodes
26 | ;; function (you might see none now if your account is new):
27 | (nodes my-service)
28 |
29 | ;; Pallet does not address nodes directly, the smallest unit it
30 | ;; addresses is a node group or just `group`. A group can have any
31 | ;; number of identical nodes. A single node is then a group with just
32 | ;; one istance of a node.
33 |
34 | ;; In order to create compute nodes, we need to first define a node
35 | ;; group, and we do so with `group-spec`. The group-spec function
36 | ;; takes one mandatory argument: `name` which is the name that pallet
37 | ;; will use to identify nodes in this group created in the cloud
38 | ;; provider. For example, the following is a minimal group
39 | ;; specification, named `webserver`
40 |
41 | (def webserver (group-spec "webserver"))
42 |
43 | ;; The other arguments for group-spec are optional. For now we will
44 | ;; use the parameter `:node-spec` which provides a hardware, OS (image) and
45 | ;; network specificaton for the nodes. For example, the following
46 | ;; group spec defines nodes of the smalles size provided by the cloud
47 | ;; provider and running Ubuntu, and with the network firewalls
48 | ;; configured so that ports 80 and 8080 are publicly accessible.
49 |
50 | (def balancer
51 | (group-spec "balancer"
52 | :node-spec {:image {:os-family :ubuntu}
53 | :hardware {:smallest true}
54 | :network {:inbound-ports [80 8080]}}))
55 |
56 | ;; At this point we can start creating nodes via the cloud provider.
57 | ;; The way it is done is by specifying how many nodes of each group we
58 | ;; want. Pallet will ensure that we have as many nodes as we need. To
59 | ;; do so, it will first check with the cloud provider for existing
60 | ;; nodes of this group, and then will determine if it needs to create
61 | ;; more nodes, destroy some or do nothing.
62 | ;;
63 | ;; converge is the function that will perform this task. In the
64 | ;; following example we instruct pallet to make it so that we have 2
65 | ;; nodes of the `webserver` group. Notice that we specify with which
66 | ;; cloud provider we want pallet to work in `:compute`; in this case
67 | ;; we use the one we just created.
68 |
69 | (converge {webserver 2} :compute my-service)
70 |
71 | ;; Now let's say we want two webservers and one balancer:
72 |
73 | (converge {webserver 2 balancer 1} :compute my-service)
74 |
75 | ;; Finally, if we want to remove all the nodes in one group, we do the
76 | ;; following. (Please NOTE: at this point make sure run this command, as the
77 | ;; rest of the tutorial assumes you did so)
78 |
79 | (converge {webserver 0 balancer 0} :compute my-service)
80 |
81 | ;; Images are configured differently between clouds and os's.
82 | ;; Pallet comes with some \"crates\" that can be used to normalise
83 | ;; the images.
84 | ;;
85 | ;; One very useful examples is `automated-admin-user`, a crate that
86 | ;; creates an admin user for your nodes. The default behavior for this
87 | ;; crate is to use your current login name, and authorize your local
88 | ;; ssh key (id_rsa in ~/.ssh in your home directory). This way, you
89 | ;; can quickly ssh into your node without needing to log into your
90 | ;; cloud provider to download the password or authentication keys.
91 |
92 | ;; The following code creates a new group-spec that contains what's
93 | ;; called a phase (defined under `:phases`. A Phase is just a named
94 | ;; function that can be executed during a converge session.
95 |
96 | ;; By default, when a node is newly created, if a `:bootstrap` phase
97 | ;; is defined, this phase will be run. This is a special phase that is
98 | ;; executed by the cloud provider itself right after the node is
99 | ;; created and doesn't require any authentication, hence is the
100 | ;; perfect time to create our user.
101 |
102 | (use 'pallet.crate.automated-admin-user)
103 |
104 | (def webserver
105 | (group-spec "webserver"
106 | :phases {:bootstrap (phase-fn (automated-admin-user))}))
107 |
108 | ;; Assuming you have deleted all the nodes as instructed above, the
109 | ;; next command will create a new `webserver` node, this time with an
110 | ;; admin user created, named as your user, and with your ssh keys
111 | ;; authenticated to it. The results of this command will be stored in
112 | ;; `results`.
113 |
114 | (def results
115 | (converge {webserver 1} :compute my-service))
116 |
117 | ;; results will contain a large amount of information, including the
118 | ;; logs resulting from Pallet running all the scripts on the nodes on
119 | ;; your behalf (in this case, to create this admin user).
120 |
121 | ;; For now, we want to get the IP address of the nodes in the
122 | ;; `webserver` group. To do so we just inspect the contents of
123 | ;; :all-nodes in the results, which will print some of the relevant
124 | ;; node information, including the public address.
125 |
126 | (:all-nodes results)
127 |
128 | ;; Go ahead and ssh into the public address of your freshly created
129 | ;; node. If all went well, you should be logged right in, no password
130 | ;; needed.
131 |
132 | ;; Crates can do many (every?) things, for example, install software.
133 | ;; The following conde snippet redefines the `webservice` group to
134 | ;; install `Java` during the `:configure` phase. `:configure` is
135 | ;; another special phase that is run by configure by default, uless
136 | ;; otherwise specified. (There is only another special phase,
137 | ;; `:settings`, not covered in this tutorial)
138 |
139 | (use 'pallet.crate.java)
140 | (def webserver
141 | (group-spec "webserver"
142 | :phases {:bootstrap (phase-fn (automated-admin-user))
143 | :configure (phase-fn (java :openjdk))}))
144 |
145 | ;; Reconverging the group will result in Java being installed in all
146 | ;; the nodes of the group.
147 |
148 | (converge {webserver 1} :compute my-service)
149 |
150 | ;; If you do not want to adjust the number of nodes, there is also
151 | ;; a lift function, which can be used to apply the configuration to
152 | ;; all existing nodes of the group.
153 |
154 | (lift webserver :compute my-service)
155 |
156 | ;; The following group-spec redefines `webserver` to add an arbitrary
157 | ;; phase that will install `curl` on the nodes in the group.
158 |
159 | (def webserver
160 | (group-spec "webserver"
161 | :phases {:bootstrap (phase-fn (automated-admin-user))
162 | :configure (phase-fn (java :openjdk))
163 | :install-curl (phase-fn (package "cur"))}))
164 |
165 | ;; Now, if we only wanted to install curl, we'd do the following
166 |
167 | (converge {webserver 1}
168 | :compute my-service
169 | :phase :install-curl)
170 |
171 | ;; But if we wanted both Java and curl to be installed, then we'd do:
172 |
173 | (converge {webserver 1}
174 | :compute my-service
175 | :phase [:configure :install-curl])
176 |
177 | ;; Alternativley, you can define a phase to be executed in a ad-hoc
178 | ;; manner just like in the following example in which instead of a
179 | ;; phase keyword (:install-curl) there is the phase definition. This
180 | ;; is great for quickly running scripts on all the nodes from the REPL
181 | ;; itself
182 |
183 | (converge {webserver 1}
184 | :compute my-service
185 | :phase [:configure (phase-fn (package "curl"))])
186 |
187 | ;; :configure is also the default phase for lift, but unlike with
188 | ;; converge, the :configure phase is not added if not specified. The
189 | ;; following example will *only* run :install-curl, but not configure.
190 |
191 | (lift [webserver] :compute my-service :phase [:install-curl])
192 |
193 |
194 |
--------------------------------------------------------------------------------
/bin/set-version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Script to set the pallet version across the examples
4 | # Note this is OSX specific sed usage
5 | projects="basic blank-project hudson mini-webapp nano-webapp webapp-haproxy-nodes webapp-nodes"
6 |
7 | if [ $# -lt 1 ]; then
8 | echo "Usage: set-version version-string"
9 | echo " eg. set-version 0.4.0-SNAPSHOT"
10 | exit 1
11 | fi
12 |
13 | version=$1
14 | echo Setting version to $version
15 |
16 | for project in $projects; do
17 | if [ -e $project/project.clj ]; then
18 | echo $project/project.clj
19 | sed -E -i .bak \
20 | -e "s!defproject ([^ ]+).*!defproject \1 \"${version}\"!" \
21 | -e "s!hoist/pallet \"[^\"]+\"!hoist/pallet \"${version}\"!" \
22 | -e "s!/pallet-crates-all \"[^\"]+\"!/pallet-crates-all \"${version}\"!" \
23 | $project/project.clj
24 | fi
25 | done
26 |
--------------------------------------------------------------------------------
/blank-project/.gitignore:
--------------------------------------------------------------------------------
1 | pom.xml
2 | *jar
3 | lib
4 | classes
--------------------------------------------------------------------------------
/blank-project/README.md:
--------------------------------------------------------------------------------
1 | # blank-project
2 |
3 | This example is a blank project that contains
4 | [pallet](http://github.com/pallet/pallet). The project can be used as
5 | starting point for your own projects.
6 |
7 | ## Creating
8 |
9 | ### lein
10 |
11 | The first thing we need is
12 | [leiningen](http://github.com/technomancy/leiningen), a build tool for
13 | clojure.
14 |
15 | bash$ curl -O http://github.com/technomancy/leiningen/raw/stable/bin/lein
16 | bash$ chmod +x lein
17 |
18 | Now we can create the project:
19 |
20 | bash$ lein new blank-project
21 | Created new project in: blank-project
22 | bash$ cd blank-project
23 |
24 | Leiningen creates a `project.clj` file, and we need to add pallet and
25 | jclouds to the `:dependencies`, and pallet-lein to the
26 | `:dev-dependencies`, so it looks like:
27 |
28 | (defproject blank-project "0.6.0"
29 | :description "blank-project for pallet"
30 | :dependencies [;; pallet lib
31 | [org.cloudhoist/pallet "0.6.6"]
32 | ;; all pallet crates
33 | [org.cloudhoist/pallet-crates-all "0.5.0"]
34 | ;; jclouds imports
35 | [org.jclouds/jclouds-all "1.2.1"]
36 | [org.jclouds/jclouds-compute "1.2.1"]
37 | [org.jclouds/jclouds-blobstore "1.2.1"]
38 | [org.jclouds.driver/jclouds-jsch "1.2.1"]
39 | [org.jclouds.driver/jclouds-slf4j "1.2.1"]
40 | ;; logging
41 | [ch.qos.logback/logback-core "1.0.0"]
42 | [ch.qos.logback/logback-classic "1.0.0"]]
43 | :dev-dependencies [[swank-clojure/swank-clojure "1.3.2"] ; swank
44 | [org.cloudhoist/pallet-lein "0.4.1"]] ; lein
45 | :repositories
46 | ;; pallet and jclouds libraries live at sonatype
47 | {"sonatype" "https://oss.sonatype.org/content/repositories/releases/"})
48 |
49 | Note that `jclouds-all` is rather heavy. You can use the list of
50 | supported clouds and individual jclouds provider jars to slim the
51 | dependency down.
52 |
53 | lein deps
54 | lein pallet providers
55 |
56 | ## Credentials
57 |
58 | The last configuration step is to specify your cloud credentials.
59 |
60 | ### ~/.pallet/config.clj
61 |
62 | You can create `~/.pallet/config.clj` to include your cloud credentials.
63 |
64 | (defpallet
65 | :services
66 | {:aws {:provider "aws-ec2" :identity "key" :credential "secret-key"}
67 | :rs {:provider "cloudservers-us" :identity "username" :credential "key"}})
68 |
69 |
70 | ## Testing
71 |
72 | To test the configuration, we can use the pallet-lein plugin, to list
73 | the nodes in your cloud account (the first that appears in the
74 | `defpallet` declaration above, in this example being `:aws`.)
75 |
76 | bash$ lein deps
77 | bash$ lein pallet nodes
78 |
79 | If you wanted to pick another provider from your list in `defpallet`,
80 | you can do it by passing the provider as a parameter the following way
81 | (in this case, selecting the second provider `:rs`):
82 |
83 | bash$ lein pallet -P rs nodes
84 |
85 | Alternatively we can start a REPL, to do the same.
86 |
87 | bash$ lein deps
88 | bash$ lein repl
89 | user> (use 'pallet.compute)
90 | user> (def my-service (compute-service-from-config-file))
91 | user> (nodes my-service)
92 |
93 | The above snipped selected the default provider too, but from the REPL
94 | you can also easily select another provider from your list, for
95 | example RackSpace Cloudservers (`:rs` in the `defpallet` declaration).
96 |
97 | user> (def my-service (compute-service-from-config-file :rs))
98 |
99 | Both of these should show any instances that you have running in your
100 | cloud account.
101 |
102 | ## Options
103 |
104 | ### Logging
105 |
106 | The project contains a `resources/logback.xml` file that configures
107 | [logback](http://logback.qos.ch/) logging into the log subdirectory.
108 | Edit this to control the placement and detail level of the logs.
109 |
110 | ### Swank
111 |
112 | If you use [SLIME](http://common-lisp.net/project/slime), you can add
113 | swank-clojure to the `project.clj`.
114 |
115 | :dev-dependencies [[swank-clojure/swank-clojure "1.3.2"]]
116 |
117 | ### jclouds provider specific jars
118 |
119 | When we added jclouds, we specified `jclouds-all` as the dependency.
120 | jclouds also has fine grained jars for each individual cloud provider
121 | that can be used instead to reduce the size of the jclouds dependency.
122 |
123 | ### Eclipse
124 |
125 | If you use eclipse, you can generate the project files using a
126 | combination of lein and mvn. When finished, you can import this as an
127 | existing project.
128 |
129 | bash$ lein pom
130 | bash$ mvn eclipse:eclipse -DdownloadSources=true -DdownloadJavadocs=true
131 |
132 | ## License
133 |
134 | Copyright (C) 2010 Hugo Duncan
135 |
136 | Distributed under the Eclipse Public License.
137 |
--------------------------------------------------------------------------------
/blank-project/project.clj:
--------------------------------------------------------------------------------
1 | (defproject blank-project "0.6.0"
2 | :description "blank-project for pallet"
3 | :dependencies [;; pallet lib
4 | [org.cloudhoist/pallet "0.6.6"]
5 | ;; all pallet crates
6 | [org.cloudhoist/pallet-crates-all "0.5.0"]
7 | ;; jclouds imports
8 | [org.jclouds/jclouds-all "1.2.1"]
9 | [org.jclouds/jclouds-compute "1.2.1"]
10 | [org.jclouds/jclouds-blobstore "1.2.1"]
11 | [org.jclouds.driver/jclouds-jsch "1.2.1"]
12 | [org.jclouds.driver/jclouds-slf4j "1.2.1"]
13 | ;; logging
14 | [ch.qos.logback/logback-core "1.0.0"]
15 | [ch.qos.logback/logback-classic "1.0.0"]]
16 | :dev-dependencies [[swank-clojure/swank-clojure "1.3.2"] ; swank
17 | [org.cloudhoist/pallet-lein "0.4.1"]] ; lein
18 | :repositories
19 | ;; pallet and jclouds libraries live at sonatype
20 | {"sonatype" "https://oss.sonatype.org/content/repositories/releases/"})
21 |
--------------------------------------------------------------------------------
/blank-project/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
5 |
6 |
7 |
8 |
9 | logs/jclouds-compute.log
10 |
11 | logs/old/jclouds-compute.%d{yyyy-MM-dd}.log
12 | 3
13 |
14 |
15 | %date %level [%thread] %logger{10} [%file:%line] %msg%n
16 |
17 |
18 |
19 |
20 | logs/jclouds-wire.log
21 |
22 | logs/old/jclouds-wire.%d{yyyy-MM-dd}.log
23 | 3
24 |
25 |
26 | %date %level [%thread] %logger{10} [%file:%line] %msg%n
27 |
28 |
29 |
30 |
31 | logs/pallet.log
32 |
33 | logs/old/pallet.%d{yyyy-MM-dd}.log
34 | 3
35 |
36 |
37 | %date %level [%thread] %logger{10} [%file:%line] %msg%n
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/blank-project/settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | cloud-credentials
6 |
7 | true
8 |
9 |
10 | cloudservers
11 | username
12 | key
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/blank-project/src/blank_project/core.clj:
--------------------------------------------------------------------------------
1 | (ns blank-project.core)
2 |
--------------------------------------------------------------------------------
/blank-project/test-resources/logback-test.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
5 |
6 |
7 |
8 |
9 | logs/jclouds-compute.log
10 |
11 | logs/old/jclouds-compute.%d{yyyy-MM-dd}.log
12 | 3
13 |
14 |
15 | %date %level [%thread] %logger{10} [%file:%line] %msg%n
16 |
17 |
18 |
19 |
20 | logs/jclouds-wire.log
21 |
22 | logs/old/jclouds-wire.%d{yyyy-MM-dd}.log
23 | 3
24 |
25 |
26 | %date %level [%thread] %logger{10} [%file:%line] %msg%n
27 |
28 |
29 |
30 |
31 | logs/pallet.log
32 |
33 | logs/old/pallet.%d{yyyy-MM-dd}.log
34 | 3
35 |
36 |
37 | %date %level [%thread] %logger{10} [%file:%line] %msg%n
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/blank-project/test/blank_project/test/core.clj:
--------------------------------------------------------------------------------
1 | (ns blank-project.test.core
2 | (:use [blank-project.core] :reload)
3 | (:use [clojure.test]))
4 |
5 | (deftest replace-me ;; FIXME: write
6 | (is false "No tests have been written."))
7 |
--------------------------------------------------------------------------------
/check-readmes.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | grep org.cloudhoist */README*
4 | grep cake-pallet */README*
5 | grep pallet-lein */README*
6 |
--------------------------------------------------------------------------------
/hudson/.gitignore:
--------------------------------------------------------------------------------
1 | pom.xml
2 | *jar
3 | lib
4 | classes
5 |
--------------------------------------------------------------------------------
/hudson/README.md:
--------------------------------------------------------------------------------
1 | # hudson
2 |
3 | This is an example project for launching a fully configured hudson server for a
4 | maven project, using [pallet](http://github.com/hugoduncan/pallet).
5 |
6 | ## Usage
7 |
8 | Create a clojure project with
9 |
10 | bash$ lein new hudson
11 | Created new project in: hudson
12 | bash$ cd hudson
13 |
14 | Leiningen creates a `project.clj` file, and we need to add pallet and jclouds to
15 | the :dependencies, and pallet-lein to the :dev-dependencies, so it looks like:
16 |
17 | (defproject blank-project "0.3.0"
18 | :description "blank-project for pallet"
19 | :dependencies [[org.cloudhoist/pallet "0.4.6"]
20 | [org.cloudhoist/pallet-crates-standalone "0.4.0"]
21 | [org.jclouds/jclouds-all "1.0-beta-8"]
22 | [org.jclouds/jclouds-jsch "1.0-beta-8"]
23 | [org.jclouds/jclouds-log4j "1.0-beta-8"]
24 | [org.jclouds/jclouds-enterprise "1.0-beta-8"]
25 | [log4j/log4j "1.2.14"]]
26 | :dev-dependencies [[org.cloudhoist/pallet-lein "0.4.0"]]
27 | :repositories {"sonatype" "https://oss.sonatype.org/content/repositories/releases"})
28 |
29 | You can create `~/.pallet/config.clj` to include your cloud credentials.
30 |
31 | (defpallet
32 | :serivces
33 | {:aws {:provider "ec2" :identity "key" :credential "secret-key"}
34 | :rs {:provider "cloudservers" :identity "username" :credential "key"}})
35 |
36 | Lein will create `src/hudson/core.clj` which we will rename to `src/hudson/ci.clj`.
37 | See [ci.clj](http://github.com/hugoduncan/pallet-examples/blob/master/hudson/src/hudson/ci.clj)
38 |
39 |
40 | To launch the server:
41 |
42 | bash$ lein deps
43 | bash$ lein pallet converge hudson.ci/hudson 1 :deploy
44 |
45 |
46 |
47 | ## License
48 |
49 | Copyright (C) 2010 Hugo Duncan
50 |
51 | Distributed under the Eclipse Public License.
52 |
--------------------------------------------------------------------------------
/hudson/project.clj:
--------------------------------------------------------------------------------
1 | (defproject blank-project "0.4.0"
2 | :description "hudson example project for pallet"
3 | :dependencies [[org.cloudhoist/pallet "0.4.3"]
4 | [org.cloudhoist/pallet-crates-standalone "0.4.0"]
5 | [org.jclouds/jclouds-all "1.0-beta-8"]
6 | [org.jclouds/jclouds-jsch "1.0-beta-8"]
7 | [org.jclouds/jclouds-log4j "1.0-beta-8"]
8 | [org.jclouds/jclouds-enterprise "1.0-beta-8"]
9 | [log4j/log4j "1.2.14"]]
10 | :dev-dependencies [[swank-clojure/swank-clojure "1.2.1"] ; swank
11 | [vmfest "0.2.2"] ; virtualbox
12 | [org.cloudhoist/pallet-lein "0.4.0"] ; lein
13 | [cake-pallet "0.4.0"]] ; cake
14 | :repositories
15 | {"sonatype" "https://oss.sonatype.org/content/repositories/releases"}
16 | :tasks [cake-pallet.tasks])
17 |
--------------------------------------------------------------------------------
/hudson/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | log4j.rootLogger=debug, stdout, R
2 |
3 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender
4 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
5 | log4j.appender.stdout.Threshold=info
6 |
7 | # Pattern to output the caller's file name and line number.
8 | log4j.appender.stdout.layout.ConversionPattern=%5p %d %c - %m%n
9 |
10 | log4j.appender.R=org.apache.log4j.RollingFileAppender
11 | log4j.appender.R.File=log/webapp-nodes.log
12 | log4j.appender.R.Threshold=trace
13 |
14 | log4j.appender.R.MaxFileSize=100KB
15 | # Keep one backup file
16 | # log4j.appender.R.MaxBackupIndex=1
17 |
18 | log4j.appender.R.layout=org.apache.log4j.PatternLayout
19 | log4j.appender.R.layout.ConversionPattern=%p [%t] %d %c - %m%n
20 |
21 |
22 | log4j.category.org.jclouds=trace, jclouds
23 | log4j.appender.jclouds=org.apache.log4j.RollingFileAppender
24 | log4j.appender.jclouds.File=log/jclouds.log
25 | log4j.appender.jclouds.Threshold=trace
26 |
27 | log4j.appender.jclouds.MaxFileSize=100KB
28 | # Keep one backup file
29 | # log4j.appender.R.MaxBackupIndex=1
30 |
31 | log4j.appender.jclouds.layout=org.apache.log4j.PatternLayout
32 | log4j.appender.jclouds.layout.ConversionPattern=%p [%t] %d %c - %m%n
33 |
--------------------------------------------------------------------------------
/hudson/resources/log4j.properties.debug:
--------------------------------------------------------------------------------
1 | log4j.rootLogger=debug, stdout, R
2 |
3 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender
4 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
5 |
6 | # Pattern to output the caller's file name and line number.
7 | log4j.appender.stdout.layout.ConversionPattern=%5p %d %c - %m%n
8 |
9 | log4j.appender.R=org.apache.log4j.RollingFileAppender
10 | log4j.appender.R.File=log/blank_project.log
11 | log4j.appender.R.Threshold=trace
12 |
13 | log4j.appender.R.MaxFileSize=100KB
14 | # Keep one backup file
15 | # log4j.appender.R.MaxBackupIndex=1
16 |
17 | log4j.appender.R.layout=org.apache.log4j.PatternLayout
18 | log4j.appender.R.layout.ConversionPattern=%p [%t] %d %c - %m%n
19 |
20 |
21 | log4j.category.org.jclouds=trace, jclouds
22 | log4j.appender.jclouds=org.apache.log4j.RollingFileAppender
23 | log4j.appender.jclouds.File=log/jclouds.log
24 | log4j.appender.jclouds.Threshold=trace
25 |
26 | log4j.appender.jclouds.MaxFileSize=100KB
27 | # Keep one backup file
28 | # log4j.appender.R.MaxBackupIndex=1
29 |
30 | log4j.appender.jclouds.layout=org.apache.log4j.PatternLayout
31 | log4j.appender.jclouds.layout.ConversionPattern=%p [%t] %d %c - %m%n
32 |
33 |
34 |
--------------------------------------------------------------------------------
/hudson/src/hudson/ci.clj:
--------------------------------------------------------------------------------
1 | (ns hudson.ci
2 | (:require
3 | [pallet.core :as core]
4 | [pallet.crate.automated-admin-user :as automated-admin-user]
5 | [pallet.crate.git :as git]
6 | [pallet.crate.hudson :as hudson]
7 | [pallet.crate.java :as java]
8 | [pallet.crate.tomcat :as tomcat]
9 | [pallet.crate.maven :as maven]
10 | [pallet.parameter :as parameter]
11 | [pallet.request-map :as request-map]
12 | [pallet.resource :as resource]
13 | [pallet.resource.directory :as directory]
14 | [pallet.resource.package :as package]
15 | [pallet.resource.remote-file :as remote-file]
16 | [pallet.resource.service :as service]
17 | [pallet.resource.user :as user]
18 | [pallet.stevedore :as stevedore])
19 | (:use
20 | pallet.thread-expr))
21 |
22 | (defn setup-users
23 | "Setup the hudson user"
24 | [request]
25 | (let [user (parameter/get-for-target request [:hudson :user])]
26 | (->
27 | request
28 | (user/user user :comment "\"hudson,,,\""))))
29 |
30 | (defn ci-config
31 | [request]
32 | (->
33 | request
34 | (maven/package)
35 | (git/git)
36 | (java/java :sun)
37 | (tomcat/tomcat)
38 | (user/user "testuser" :create-home true :shell :bash)
39 | (service/with-restart "tomcat6"
40 | (tomcat/server-configuration (tomcat/server))
41 | (hudson/tomcat-deploy)
42 | (hudson/config :use-security false)
43 | (setup-users)
44 | (hudson/plugin :git)
45 | (hudson/plugin :github)
46 | (hudson/plugin :instant-messaging)
47 | (hudson/plugin
48 | :ircbot
49 | :enabled true :hostname "irc.freenode.net" :port 6667
50 | :nick "jcloudsci" :nick-serv-password "jcloudsci"
51 | :hudson-login ""
52 | :hudson-password ""
53 | :default-targets [{:name "#jcloudstest"}]
54 | :command-prefix "!jcloudsci")
55 | (hudson/maven "default maven" "2.2.1")
56 | (hudson/job :maven2 "jclouds"
57 | :maven-name "default maven"
58 | :goals "-P clean deploy"
59 | :group-id "org.jclouds"
60 | :artifact-id "jclouds"
61 | :branches ["origin/master"]
62 | :github {:projectUrl "http://github.com/hugoduncan/pallet/"}
63 | :aggregator-style-build true
64 | :maven-opts ""
65 | :scm ["git://github.com/jclouds/jclouds.git"]
66 | :publishers {:ircbot
67 | {:targets [{:name "#jcloudstest"}]
68 | :strategy :all}}))))
69 |
70 | (core/defnode hudson
71 | "Hudson node"
72 | {:inbound-ports [8080 22]}
73 | :bootstrap (resource/phase
74 | (automated-admin-user/automated-admin-user))
75 | :configure (resource/phase
76 | (ci-config))
77 | :restart-tomcat (resource/phase
78 | (service/service "tomcat6" :action :restart))
79 | :reload-configuration (resource/phase
80 | (hudson/reload-configuration))
81 | :build-pallet (resource/phase (hudson/build "jclouds")))
82 |
--------------------------------------------------------------------------------
/hudson/test/hudson/test/core.clj:
--------------------------------------------------------------------------------
1 | (ns hudson.test.core
2 | (:use [hudson.core] :reload)
3 | (:use [clojure.test]))
4 |
5 | (deftest replace-me ;; FIXME: write
6 | (is false "No tests have been written."))
7 |
--------------------------------------------------------------------------------
/integration-tests/README:
--------------------------------------------------------------------------------
1 | This directory contains integration tests run against each of the pallet projects.
2 |
--------------------------------------------------------------------------------
/integration-tests/cake-test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | cake=${CAKE-~/bin/cake}
4 | compute_service=${pallet_compute_service-${PALLET_COMPUTE_SERVICE-live-test}}
5 | let fails=0
6 |
7 | fail() {
8 | r=$?
9 | let fails=(fails + 1)
10 | echo "FAIL: cake $1 failed"
11 | return $r
12 | }
13 |
14 | # test with cake
15 | echo "cake deps"
16 | ${cake} deps || fail "deps"
17 | echo "cake pallet nodes"
18 | ${cake} pallet nodes -- -P $compute_service || fail "pallet nodes"
19 | echo "cake clean"
20 | ${cake} clean || fail "clean"
21 | echo "cake kill"
22 | ${cake} kill -9 || fail "kill"
23 |
24 | exit $fails
25 |
--------------------------------------------------------------------------------
/integration-tests/lein-test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | lein=${LEIN-~/bin/lein}
4 | compute_service=${pallet_compute_service-${PALLET_COMPUTE_SERVICE-live-test}}
5 | let fails=0
6 |
7 | fail() {
8 | r=$?
9 | let fails=(fails + 1)
10 | echo "FAIL: lein $1 failed"
11 | return $r
12 | }
13 |
14 | # test with lein
15 | echo "lein deps"
16 | ${lein} deps || fail "deps"
17 | echo "lein pallet nodes"
18 | ${lein} pallet -P $compute_service nodes || fail "pallet nodes"
19 | echo "lein clean"
20 | ${lein} clean || fail "clean"
21 |
22 | exit $fails
23 |
--------------------------------------------------------------------------------
/integration-tests/log4j.properties:
--------------------------------------------------------------------------------
1 | log4j.rootLogger=debug, stdout, R
2 |
3 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender
4 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
5 | log4j.appender.stdout.Threshold=info
6 |
7 | # Pattern to output the caller's file name and line number.
8 | log4j.appender.stdout.layout.ConversionPattern=%5p %d %c - %m%n
9 |
10 | log4j.appender.R=org.apache.log4j.RollingFileAppender
11 | log4j.appender.R.File=log/webapp-nodes.log
12 | log4j.appender.R.Threshold=trace
13 |
14 | log4j.appender.R.MaxFileSize=100KB
15 | # Keep one backup file
16 | # log4j.appender.R.MaxBackupIndex=1
17 |
18 | log4j.appender.R.layout=org.apache.log4j.PatternLayout
19 | log4j.appender.R.layout.ConversionPattern=%p [%t] %d %c - %m%n
20 |
21 |
22 | log4j.category.pallet.main-invoker=trace, R
23 | log4j.category.pallet.main=trace, R
24 | log4j.category.vmfest=info, R
25 |
26 | log4j.category.root=R
27 |
28 | log4j.category.org.jclouds=trace, jclouds
29 | log4j.appender.jclouds=org.apache.log4j.RollingFileAppender
30 | log4j.appender.jclouds.File=log/jclouds.log
31 | log4j.appender.jclouds.Threshold=trace
32 |
33 | log4j.appender.jclouds.MaxFileSize=100KB
34 | # Keep one backup file
35 | # log4j.appender.R.MaxBackupIndex=1
36 |
37 | log4j.appender.jclouds.layout=org.apache.log4j.PatternLayout
38 | log4j.appender.jclouds.layout.ConversionPattern=%p [%t] %d %c - %m%n
39 |
--------------------------------------------------------------------------------
/mini-webapp/.gitignore:
--------------------------------------------------------------------------------
1 | pom.xml
2 | *jar
3 | lib
4 | classes
--------------------------------------------------------------------------------
/mini-webapp/README.md:
--------------------------------------------------------------------------------
1 | # mini-webapp
2 |
3 | This is a very simple web app for demonstration purposes.
4 |
5 | ## Creating
6 |
7 | We create a blank clojure project.
8 |
9 | ### project.clj
10 | lein new mini-webapp
11 |
12 | We'll use the [ring](http://github.com/mmcgrana/ring) library, so we'll add that
13 | to the project.clj `:depenencies`
14 |
15 | [ring "0.2.6"]
16 |
17 | To create a war file we'll also use the leiningen-war plugin, so we add it to
18 | `:dev-depenencies`
19 |
20 | [uk.org.alienscience/leiningen-war "0.0.7"]
21 |
22 | We also need the servlet to be AOT compiled, so we'll add an :aot entry for
23 | mini-webapp.servlet.
24 |
25 | :aot [mini-webapp.Servlet]
26 |
27 | ### servlet
28 |
29 | We need three files - the servlet, the app and the web descriptor file.
30 |
31 | First the servlet.
32 |
33 |
34 | ## War file
35 |
36 | lein deps
37 | lein compile
38 | lein uberwar
39 |
40 |
41 | ## Installation
42 |
43 | See webapp-haproxy-nodes project.
44 |
45 | ## License
46 |
47 | Copyright (C) 2010 Hugo Duncan
48 |
49 | Distributed under the Eclipse Public License.
50 |
--------------------------------------------------------------------------------
/mini-webapp/project.clj:
--------------------------------------------------------------------------------
1 | (defproject mini-webapp "0.4.0-SNAPSHOT"
2 | :description "mini-webapp"
3 | :aot [mini-webapp.Servlet]
4 | :dependencies [[org.clojure/clojure "1.2.0"]
5 | [org.clojure/clojure-contrib "1.2.0"]
6 | [ring "0.2.6"]]
7 | :dev-dependencies [[uk.org.alienscience/leiningen-war "0.0.7"]
8 | [swank-clojure/swank-clojure "1.2.1"]])
9 |
--------------------------------------------------------------------------------
/mini-webapp/src/mini_webapp/Servlet.clj:
--------------------------------------------------------------------------------
1 | (ns mini-webapp.Servlet
2 | "Servlet stub that delegates to our application."
3 | (:gen-class :extends javax.servlet.http.HttpServlet)
4 | (:require ring.util.servlet))
5 |
6 | ;; Reference to our application code
7 | (defonce the-app (atom nil))
8 |
9 | (defn start-swank
10 | "Function to start swank server. This can be run when the server is
11 | started to give a remote repl. swank-clojure will need to be added
12 | as a dependency tot he war file."
13 | []
14 | (require 'swank.swank)
15 | (let [start-repl (var-get (ns-resolve (the-ns 'swank.swank) 'start-repl))]
16 | (start-repl)))
17 |
18 | (defn resolve-and-start-app
19 | "This ia a workaround for the recursive AOT compilation in closure. By
20 | dynamically requiring and resolving, the rest of the application is not
21 | AOT compiled."
22 | []
23 | (require 'mini-webapp.app)
24 | (do
25 | ;; Uncomment the following line, and add swank-clojure as a dependency,
26 | ;; to run a remote repl inside your web app.
27 | ;; (start-swank)
28 |
29 | ;; there is a potential race condition here, but given that we shall
30 | ;; not be invoking this from multiple threads, I'm not worried
31 | (reset! the-app (var-get (ns-resolve (the-ns 'mini-webapp.app) 'app)))))
32 |
33 | ;; delay app, so that resolve-and-start-app is called once
34 | (def app (delay (resolve-and-start-app)))
35 |
36 |
37 | ;; set up a server that serves heynote-app
38 | (ring.util.servlet/defservice @app)
39 |
--------------------------------------------------------------------------------
/mini-webapp/src/mini_webapp/app.clj:
--------------------------------------------------------------------------------
1 | (ns mini-webapp.app
2 | "mini-webapp application"
3 | (:require
4 | [ring.util.response :as response])
5 | (:import (java.net InetAddress)))
6 |
7 | (defn app [req]
8 | (response/response (str "Hello World! from: "
9 | (.getHostAddress (InetAddress/getLocalHost)))))
10 |
--------------------------------------------------------------------------------
/mini-webapp/src/mini_webapp/core.clj:
--------------------------------------------------------------------------------
1 | (ns mini-webapp.core)
2 |
--------------------------------------------------------------------------------
/mini-webapp/src/mini_webapp/jetty.clj:
--------------------------------------------------------------------------------
1 | (ns mini-webapp.jetty
2 | (:require
3 | [ring.adapter.jetty :as jetty]
4 | [mini-webapp.app :as app]))
5 |
6 |
7 | ;; Keep track of the server, so we can stop it if required
8 | (defonce server (atom nil))
9 |
10 | (defn start
11 | "Start the app, keeping track of the server"
12 | [& {:keys [port join?] :or {port 8080 join? false}}]
13 | (reset! server (jetty/run-jetty #'app/app {:port port :join? join?})))
14 |
15 | (defn stop
16 | "Stop the app"
17 | []
18 | (swap! server (fn [server] (.stop server) nil)))
19 |
--------------------------------------------------------------------------------
/mini-webapp/src/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 | mini_webapp
11 | mini_webapp.Servlet
12 | 1
13 |
14 |
15 |
16 | mini_webapp
17 | /
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/mini-webapp/test/mini_webapp/test/core.clj:
--------------------------------------------------------------------------------
1 | (ns mini-webapp.test.core
2 | (:use [mini-webapp.core] :reload)
3 | (:use [clojure.test]))
4 |
5 | (deftest replace-me ;; FIXME: write
6 | (is false "No tests have been written."))
7 |
--------------------------------------------------------------------------------
/nano-webapp/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | com.cloudhoist
5 | nano-webapp
6 | war
7 | 0.3.0
8 | nano-webapp Maven Webapp
9 | http://maven.apache.org
10 |
11 |
12 | junit
13 | junit
14 | 3.8.1
15 | test
16 |
17 |
18 |
19 | nano-webapp
20 |
21 |
22 |
--------------------------------------------------------------------------------
/nano-webapp/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | Archetype Created Web Application
7 |
8 |
--------------------------------------------------------------------------------
/nano-webapp/src/main/webapp/index.jsp:
--------------------------------------------------------------------------------
1 |
2 | <%@ page language="java" %>
3 |
4 | Hello World! from <%= java.net.InetAddress.getLocalHost().getHostAddress() %>
5 |
6 |
7 |
--------------------------------------------------------------------------------
/test-all.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # run some sanity checks
4 |
5 | projects="basic blank-project hudson webapp-haproxy-nodes webapp-nodes"
6 |
7 | log=${PALLETLOG-$(pwd)/integration.log}
8 | pallet_compute_service=${PALLET_COMPUTE_SERVICE-live-test}
9 | root=$(pwd)
10 | JVM_OPTS="-Xms256M -Xmx256M -Xmn128M -Djava.awt.headless=true -XX:MaxPermSize=128m"
11 |
12 | export root
13 | export pallet_compute_service
14 | export JVM_OPTS
15 | echo "STARTING integration tests $(date)" | tee -a $log
16 |
17 | let fails=0
18 |
19 | for project in ${projects}
20 | do
21 | echo "testing $project"
22 | # propogate log4j.properties
23 | mkdir -p $project/test-resources
24 | cp ${root}/integration-tests/log4j.properties $project/test-resources
25 | ( \
26 | echo "global tests"
27 | cd $project
28 | for script in ${root}/integration-tests/*.sh; do
29 | before="$(date +%s)"
30 | ( /usr/bin/env bash $script ) | tee -a $log 2>&1
31 | let fails=(fails + $?)
32 | after="$(date +%s)"
33 | elapsed_seconds="$(expr $after - $before)"
34 | echo "Test ran in $elapsed_seconds secs : $script"
35 | done
36 | )
37 | ( \
38 | echo "local tests"
39 | if [ -e $project/integration-tests ]; then
40 | cd $project
41 | for script in integration-tests/*.sh; do
42 | ( /usr/bin/env bash $script ) | tee -a $log 2>&1
43 | let fails=(fails + $?)
44 | done
45 | fi
46 | )
47 | done
48 |
49 | echo "FINISHED integration tests $(date)" | tee -a $log
50 | echo "FAILURES $fails" | tee -a $log 2>&1
51 |
--------------------------------------------------------------------------------
/webapp-haproxy-nodes/README.md:
--------------------------------------------------------------------------------
1 | # webapp-haproxy-nodes
2 |
3 | This example is a project that contains
4 | [pallet](http://github.com/hugoduncan/pallet) node configurations and
5 | phases to deploy web applications to the cloud proxied by HAProxy.
6 | The project can be used as starting point for your own multi-node
7 | projects.
8 |
9 | ## Testing
10 |
11 | ### Setting up your environment
12 |
13 | If you haven't created the file `~/.pallet/config.clj` with your cloud
14 | provider data, do it so now by copying the file
15 | [settings.xml](tree/master/webapp-haproxy-nodes/config.clj) into your
16 | `~/.pallet` directory (create the directory if necessary). Change the
17 | provider keys to match your cloud provider and your identity and
18 | credential to sign into the cloud provider. The currently supported
19 | providers are:
20 |
21 | :openhosting-east1
22 | :serverlove-z1-man
23 | :cloudsigma-zrh
24 | :aws-ec2
25 | :eucalyptus-partnercloud-ec2
26 | :bluelock-vcloud-zone01
27 | :bluelock-vcdirector
28 | :cloudservers-us
29 | :elastichosts-lon-p
30 | :skalicloud-sdg-my
31 | :deltacloud
32 | :nova
33 | :trmk-vcloudexpress
34 | :eucalyptus
35 | :bluelock-vcloud-vcenterprise
36 | :elastichosts-lon-b
37 | :stratogen-vcloud-mycloud
38 | :cloudservers-uk
39 | :trmk-ecloud
40 | :elastichosts-sat-p
41 | :slicehost
42 | :gogrid
43 | :stub
44 | :vcloud
45 | :elasticstack
46 | :savvis-symphonyvpdc
47 | :rimuhosting
48 | :byon
49 | :node-list
50 | :virtualbox
51 |
52 | ### Building the demo webapps
53 |
54 | We will use two different web applications for this example:
55 | `nano-webapp` and `mini-webapp`.
56 |
57 | First we build the war file in the
58 | [mini-webapp](http://github.com/pallet/pallet-examples/tree/master/mini-webapp/)
59 | project directory.
60 |
61 | bash$ lein deps
62 | bash$ lein compile
63 | bash$ lein uberwar
64 |
65 | Then we build the war file in the
66 | [nano-webapp](http://github.com/pallet/pallet-examples/tree/master/nano-webapp)
67 | project directory.
68 |
69 | bash$ mvn clean package
70 |
71 | ### Testing from the command line
72 |
73 | To test the configuration, from the webapp-nodes directory, we start a
74 | webapp single instance of the 'proxied' node with nano-webapp
75 | deployed.
76 |
77 | bash$ lein deps
78 | bash$ lein pallet converge webapp-nodes.nodes/proxied 1 :deploy-nano-webapp :restart-tomcat
79 |
80 | Using the public IP address of your new node, check that the newly
81 | deployed application is running by visiting `http://:8080`
82 |
83 | To obtain the IP addresses of your nodes, run the following to get the
84 | list of running nodes and their public (and private) IP addresses:
85 |
86 | bash$ lein pallet nodes
87 |
88 | __NOTE__: When using `lein pallet`, pallet will automatically use the first
89 | provider defined in `~/.pallet/config.clj`. If you want to use another
90 | provider you should pass its name to pallet via the `-P` command line
91 | option to `lein pallet`, e.g.:
92 |
93 | bash$ lein pallet -P converge ...
94 |
95 | ### Testing from the REPL
96 |
97 | Alternatively, we can start a REPL from the webapp-nodes directory,
98 | start a webapp node, and deploy our application (NOTE: in the REPL
99 | examples, replace the key `:aws` for whatever you named the cloud
100 | provider service configuration in `~/.pallet/config.clj`)
101 |
102 | bash$ lein deps
103 | bash$ lein repl
104 | user> (require 'webapp-nodes.nodes)
105 | user> (require 'pallet.compute)
106 | user> (require 'pallet.core)
107 | user> (def service (pallet.compute/compute-service-from-config-file :aws))
108 | user> (pallet.core/converge {webapp-nodes.nodes/proxied 1}
109 | :compute service
110 | :phase [:deploy-nano-webapp :restart-tomcat])
111 |
112 | Using the public IP address of your new node, check that the newly
113 | deployed application is running by visiting `http://:8080`. To get the IP address of your nodes, run the following:
115 |
116 | user> (pallet.compute/nodes service)
117 |
118 | This will return the listing below. What we're looking for is the
119 | public ip address 23.20.96.254 in this case.
120 |
121 | ```
122 | ( proxied
123 | ZONE/us-east-1d.REGION/us-east-1.PROVIDER/aws-ec2 null
124 | amzn-linux paravirtual null amazon/amzn-ami-pv-2012.03.1.x86_64-ebs
125 | RUNNING
126 | public: 23.20.96.254 private: 10.214.221.179)
127 | ```
128 |
129 | ### Redeploying your web application
130 |
131 | Further deploys can be run with the `lift` function.
132 |
133 | bash$ lein pallet lift webapp-nodes.nodes/proxied :deploy-nano-webapp
134 |
135 | or
136 |
137 | user> (pallet.core/lift webapp-nodes.nodes/proxied
138 | :compute service
139 | :phase :deploy-nano-webapp)
140 |
141 | NOTE: The above methods should also work with mini-webapp by using the
142 | phase `:deploy-mini-webapp`.
143 |
144 | ## Tearing down a deployment
145 |
146 | If you want to destroy the node/s you just created, all you need to do
147 | is set the count to 0 on converge, e.g.:
148 |
149 | bash$ lein pallet converge webapp-nodes.nodes/proxied 0
150 |
151 | or
152 |
153 | user> (pallet.core/converge {webapp-nodes.nodes/proxied 0} :compute service)
154 |
155 | ## Multinode deployments
156 |
157 | We are going to deploy a few 'proxied' nodes and a 'haproxy' node that
158 | will be configured with HAProxy. For this job there are not many
159 | changes needed, though.
160 |
161 | ### At the command line
162 |
163 | $ lein pallet converge webapp-nodes.nodes/proxied 2 webapp-nodes.nodes/haproxy 1 :deploy-nano-webapp :restart-tomcat :restart-haproxy
164 |
165 | Visit `http:///` and confirm that the proxy is
166 | working. The IP address reported by the webapps should change between
167 | refreshes of the page, reflecting the fact that the proxy is balancing
168 | the requests. (NOTE: it might take a while for HAProxy to switch
169 | webapps)
170 |
171 | ### At the REPL
172 |
173 | user> (pallet.core/converge {webapp-nodes.nodes/proxied 2
174 | webapp-nodes.nodes/haproxy 1}
175 | :compute service
176 | :phase [:deploy-nano-webapp :restart-tomcat :restart-haproxy])
177 |
178 | ### Finishing up
179 |
180 | To finish up, destroy all the nodes:
181 |
182 | $ lein pallet converge webapp-nodes.nodes/proxied 0 webapp-nodes.nodes/haproxy 0
183 |
184 | or
185 |
186 | user> (pallet.core/converge {webapp-nodes.nodes/proxied 0
187 | webapp-nodes.nodes/haproxy 0}
188 | :compute service)
189 |
190 | ## License
191 |
192 | Copyright (C) 2010 Hugo Duncan
193 |
194 | Distributed under the Eclipse Public License.
195 |
--------------------------------------------------------------------------------
/webapp-haproxy-nodes/config.clj:
--------------------------------------------------------------------------------
1 | (defpallet
2 | :services
3 | {:aws {:proivder "aws-ec2"
4 | :identity ""
5 | :credential ""}})
6 |
--------------------------------------------------------------------------------
/webapp-haproxy-nodes/project.clj:
--------------------------------------------------------------------------------
1 | (defproject webapp-haproxy-nodes "0.6.0"
2 | :description "Webapp with haproxy load balancer"
3 | :dependencies [[org.clojure/clojure "1.2.0"]
4 | [org.clojure/clojure-contrib "1.2.0"]
5 | [org.cloudhoist/pallet "0.6.8"]
6 | [org.cloudhoist/haproxy "0.6.0"]
7 | [org.cloudhoist/java "0.5.1"]
8 | [org.cloudhoist/tomcat "0.6.0"]
9 | [org.cloudhoist/automated-admin-user "0.5.0" ]
10 | [org.jclouds/jclouds-all "1.2.1"]
11 | [org.jclouds.driver/jclouds-jsch "1.2.1"]
12 | [org.jclouds.driver/jclouds-slf4j "1.2.1"]
13 | [org.jclouds/jclouds-compute "1.2.1"]
14 | [org.jclouds/jclouds-blobstore "1.2.1"]
15 | [ch.qos.logback/logback-core "1.0.1"]
16 | [ch.qos.logback/logback-classic "1.0.1"]]
17 | :dev-dependencies [[swank-clojure/swank-clojure "1.3.2"] ; swank
18 | [org.cloudhoist/pallet-lein "0.4.2"]] ; leiningen
19 | :repositories
20 | {"sonatype" "https://oss.sonatype.org/content/repositories/releases/"})
21 |
--------------------------------------------------------------------------------
/webapp-haproxy-nodes/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ERROR
7 |
8 |
9 | %d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n
10 |
11 |
12 |
13 | log/pallet.log
14 |
15 | %date %level %logger{10} %msg%n
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/webapp-haproxy-nodes/src/webapp_nodes/crates.clj:
--------------------------------------------------------------------------------
1 | (ns webapp-nodes.crates
2 | "Crates for configuring and deploying to a web application server"
3 | (:require
4 | [pallet.resource :as resource]
5 | [pallet.crate.automated-admin-user :as automated-admin-user]
6 | [pallet.crate.haproxy :as haproxy]
7 | [pallet.crate.java :as java]
8 | [pallet.crate.tomcat :as tomcat]))
9 |
10 | (defn bootstrap
11 | "Common Bootstrap"
12 | [request]
13 | (automated-admin-user/automated-admin-user request))
14 |
15 | (defn tomcat
16 | "Tomcat server configuration"
17 | [request]
18 | (-> request
19 | (java/java :openjdk)
20 | (tomcat/settings {})
21 | (tomcat/install)))
22 |
23 | (defn tomcat-deploy
24 | "Tomcat deploy as ROOT application"
25 | [request path]
26 | (-> request
27 | (tomcat/settings {})
28 | (tomcat/deploy "ROOT" :local-file path :clear-existing true)))
29 |
30 | (defn haproxy
31 | "haproxy server with app1 on port 80."
32 | [request]
33 | (-> request
34 | (haproxy/install-package)
35 | (haproxy/configure
36 | :listen {:app1 {:server-address "0.0.0.0:80"
37 | :balance "roundrobin"}})))
38 |
39 | (defn reverse-proxy
40 | "Declare node as being reverse proxied by haproxy on tag."
41 | [request tag app port]
42 | (-> request
43 | (haproxy/proxied-by
44 | tag app :server-port port :check true :weight 1 :maxconn 50)))
45 |
--------------------------------------------------------------------------------
/webapp-haproxy-nodes/src/webapp_nodes/nodes.clj:
--------------------------------------------------------------------------------
1 | (ns webapp-nodes.nodes
2 | (:require
3 | [pallet.core :as core]
4 | [pallet.resource :as resource]
5 | [pallet.resource.service :as service]
6 | [webapp-nodes.crates :as crates]))
7 |
8 | (core/defnode haproxy
9 | "Simple haproxy"
10 | {:inbound-ports [80 22]} ;; 80 for haproxy, 22 for SSH
11 | :bootstrap (resource/phase
12 | (crates/bootstrap))
13 | :configure (resource/phase
14 | (crates/haproxy)
15 | (service/service "haproxy" :action :restart))
16 | :restart-haproxy (resource/phase
17 | (service/service "haproxy" :action :restart)))
18 |
19 | (core/defnode proxied
20 | "A proxied web app"
21 | {:inbound-ports [8080 22]} ;; 8080 for tomcat, 22 for SSH
22 | :bootstrap (resource/phase
23 | (crates/bootstrap))
24 | :configure (resource/phase
25 | (crates/tomcat)
26 | (crates/reverse-proxy :haproxy :app1 8080))
27 | :deploy-mini-webapp (resource/phase
28 | (crates/tomcat-deploy
29 | "../mini-webapp/mini-webapp-1.0.0-SNAPSHOT.war"))
30 | :deploy-nano-webapp (resource/phase
31 | (crates/tomcat-deploy
32 | "../nano-webapp/target/nano-webapp.war"))
33 | :restart-tomcat (resource/phase
34 | (service/service "tomcat6" :action :restart)))
35 |
--------------------------------------------------------------------------------