conan_deploy 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,216 @@
1
+ conan
2
+ =====
3
+
4
+ Conan da Deployer
5
+
6
+ This project provides automation for a [deployment pipeline](http://martinfowler.com/bliki/DeploymentPipeline.html) (ala 'Continous Delivery') which provisions, configures and deploys applications (Java and Ruby) to "ship-clouds". Configuration is modeled through a DSL as a list of logical target environments, each with a number of ship-clouds. Endpoints for web applications and Stackato PaaS APIs are created based on conventions, including support for [Blue/Green deployments](http://martinfowler.com/bliki/BlueGreenDeployment.html).
7
+
8
+ Applications are deployed from a Sonotype Nexus artifact repository, and not from the source repository. Java applications must be executable jars, and must the provide deployment resources needed in the jar. Ruby apps (Rails or otherwise) must be vendored and packaged as a tar ball, with a compatible structrue to provide the deployment resources.
9
+
10
+ Application artifacts are idenitifed and provisioned by Maven coordinates - group id, artifact id, packaging and version. The most recent version available on the repository will be used, or a promotion workflow along the pipeline(s) can be implemented by pinning the versions. Artifacts are pinned by keeping the build meta-data in an `environments` directory structure that mirrors the configuration model, which should be commited to version control after successful deployment and testing. _At this time, the `environments` directory and the `manifest.rb` are located from the execution directory, which is assumed to be the [nexus-apps-manifest](https://github.com/MTNSatelliteComm/nexus-app-manifest) project._
11
+
12
+ Conan is also designed to be idempotent. It can be executed against a target deployment over and over, and it should not change an application unless it out of alignment with the configuration model. Applications are also assumed to support standard set of managments APIs which provide build metadata, and health to support this.
13
+
14
+
15
+ #Configuration
16
+
17
+ Configuration for the deployment pipline is loaded through a DSL which models a target environment(s). The DSL is loaded from a `manifest.rb` file that should be provided in the execution directory.
18
+
19
+ ```ruby
20
+ pipeline(:'team1') {
21
+ app(:foo, 'com.mtnsat:foo', :jvm)
22
+ app(:bar, 'com.mtnsat:bar', :rails_zip)
23
+ }
24
+ pipeline(:'team2')
25
+ app(:baz, 'com.mtnsat:baz-web', :rails_zip)
26
+ app(:bang, 'com.mtnsat:bang', :rails_zip)
27
+ }
28
+
29
+ environment(:integ) {
30
+ org('mtn') {
31
+ deploy('aws') {
32
+ apps :foo
33
+ }
34
+ deploy('sea1') {
35
+ apps :foo, :bar
36
+ facility '999'
37
+ }
38
+ deploy('mia1') {
39
+ apps :foo, :bar, :baz
40
+ facility '888'
41
+ }
42
+ }
43
+ }
44
+
45
+ environment(:prod) {
46
+ promotes_from :integ
47
+ org('mtn') {
48
+ deploy('aws') {
49
+ apps :foo
50
+ }
51
+ }
52
+ org('acme') {
53
+ deploy('minnow1') {
54
+ enabled false
55
+ apps :foo, :bar, :baz
56
+ facility '42'
57
+ }
58
+ deploy('minnow1') {
59
+ apps :bang
60
+ option 'mapping', 'acme-stuff.com'
61
+ option 'do-dad', 'flim-flam'
62
+ }
63
+ deploy('bounty1') {
64
+ apps :foo, :bar, :baz
65
+ facility '100'
66
+ }
67
+ deploy('bounty1') {
68
+ apps :bang
69
+ option 'mapping', 'acme-stuff.com'
70
+ option 'do-dad', 'woo-woo'
71
+ }
72
+ }
73
+ }
74
+ ```
75
+
76
+ <dl>
77
+ <dt>pipeline</dt>
78
+ <dd>any number of application pipelines. Takes a symbol for the pipeline, and defines the apps that are delivered by that pipeline</dd>
79
+
80
+ <dt>app</dt>
81
+ <dd>any number of applications. Takes a symbol for the app, a maven group_id:artifact_id and the type of platform the app uses (:jvm or :rails_zip)</dd>
82
+
83
+ <dt>environment</dt>
84
+ <dd>any number of environments. takes a symbol for the environment, and any number of `deploy`s. NOTE: the order is _not_ significant.</dd>
85
+
86
+ <dt>promotes_from</dt>
87
+ <dd>a declaration to control what environment the provisioning uses to check for new versions to promote. The absence of this declartation means that the artifact repository will be checked for the latest version</dd>
88
+
89
+ <dt>org</dt>
90
+ <dd>scopes the deployment to the organization served by those deployments.</dd>
91
+
92
+ <dt>deploy</dt>
93
+ <dd>describes a deployment to the given ship-cloud. It takes a key for the ship, and some attributes</dd>
94
+
95
+ <dt>endabled</dt>
96
+ <dd>deployments will be avoided if not 'true', default value is 'true' if absent</dd>
97
+
98
+ <dt>apps</dt>
99
+ <dd>a list of symbols for applications (defined in `pipeline/app` above) which should be deployed to the environment</dd>
100
+
101
+ <dt>facility</dt>
102
+ <dd>the facitility id</dd>
103
+
104
+ <dt>option</dt>
105
+ <dd>a way to define a key/value pair for deploy/app specific configurations (can be used multiple times to define N number key/value pairs)</dd>
106
+ <dl>
107
+
108
+ ## Usage
109
+
110
+ ```
111
+ $ conan [options] pipeline environment"
112
+
113
+ pipeline - name of the pipeline to use
114
+ environment - name of a the target environment: integ,stage,prod
115
+
116
+ Options:
117
+ -d, --output-dir [DIR] Generate manifest data to this directory
118
+ -f, --output-format [FORMAT] The format used to write output. Either "properties" for Jenkins build properties
119
+ or "stackato" (default) to provision binaries and write stackato yml files
120
+ from project templates.
121
+ -a, --action [ACTION] The action(s) to perform. Either "provision" (default), "configure","deploy" or "all".
122
+ Support for blue/green deployments use actions: "provision", "bg_configure", "bg_deploy",
123
+ "bg_switch", "bg_clean" or "bg_all".
124
+ -u, --paas-user [USER] The stackato user name for deployments
125
+ -p, --paas-password [PASSWORD] The stackato password name for deployments
126
+ -F, --force-deploy Force deployment to bypass version checks.
127
+ -N, --new-relic-api-key New Relic API key for deployment alerts
128
+ -s [ORG-SHIP], Only include deployments for the given shipcloud (org-ship)
129
+ --deploy-shipcloud
130
+ -D, --dry-run Deployment dry-run. Prints Stackato commands
131
+ -V, --verbose Verbose console output
132
+ -v, --version Show the software version
133
+ -h, --help Display this screen
134
+
135
+
136
+ ```
137
+
138
+
139
+ There are three phases... provision, configure, deploy, The current pipeline only preforms the provision phase.
140
+
141
+ 1. provision: Locate the binaries to deploy, download them from the artifact repository, and persist version information used to pin artifact versions and provides a workflow/promotion process. Version information (now really just the artifact meta-data from the artifact repository, instead of a properties file) is persisted in the `environments` directory tree. Artifacts that are downloaded are staged for configuration and deployment in `tmp/apps`. Artifacts which are tar-balls are extracted in the staging directory. Projects should provide configuration templates in a `deploy-templates` directory (assuming that get's approval from the Rails crowd). For jar artifacts, it attempts to extract configuration templates from the jar, at `META-INF/deploy/templates` and puts them in the staging directory at the same `deploy-templates` location.
142
+
143
+ 2. configure: Generate deployment-time configuration files from the model. It uses any ERB templates found at `deploy-templates` in the staging directory. The templates generate files in the staging root directory, with the same name as the template, but the extension is removed. e.g. `stackato.yml.erb` -> `stackato.yml`
144
+
145
+ 3. deploy: Run Stackato deployment of the application staging directory. It will avoid doing the deployment unless no service is found at the target hostname, the version check shows an older version running at the target hostname, or the `-F` flag forces deployment.
146
+
147
+ _TBD: B/G actions_
148
+
149
+ ## Templates
150
+
151
+ Templates for deloyment artifacts are .erb files (Erubis user guide: http://www.kuwata-lab.com/erubis/users-guide.html).
152
+
153
+ The templates are given a Context when it is evaluated. The Context provides the template with a set of key/values. The expected set of
154
+ these is still maturing but here is an example of what is currently provided for a seanetsevice deployment, which has options defined:
155
+
156
+ ```
157
+ app.artifact_id = "seanetservice"
158
+ app.extension =
159
+ app.group_id = "com.mtnsat"
160
+ app.id = foo
161
+ app.platform_type = rails_zip
162
+ app.sha1 =
163
+ app.version =
164
+ deploy.app_ids = [:foo]
165
+ deploy.apps = []
166
+ deploy.enabled? = true
167
+ deploy.environment.deployments = [mtn-central, mtn-minnow1, mtn-minnow1, mtn-minnow1]
168
+ deploy.environment.id = integ
169
+ deploy.environment.upstream_env =
170
+ deploy.facility_id = "10007"
171
+ deploy.shipcloud = "mtn-minnow1"
172
+ deploy.options = {"mapping"=>["integ.example.com"], "network"=>["guest=1.1.1.10", "crew=1.1.1.91", "cloud=1.1.1.91"]}
173
+ deploy.org = "mtn"
174
+ deploy.ship = "minnow1"
175
+ deploy_name = "foo-dev-minnow1"
176
+ ```
177
+ The are also a number of shortcuts provided for shorter keys:
178
+ ```
179
+ app_id => app.id
180
+ env => deploy.environment.id
181
+ org => deploy.org
182
+ ship => deploy.ship
183
+ shipcloud => deploy.shipcloud
184
+ infra => deploy.shipcloud
185
+ facility => deploy.facility_id
186
+ options => deploy.options
187
+ ```
188
+ Warning: infra will be removed at some point
189
+
190
+ Here is an example Stackato template:
191
+ ```erb
192
+ name: <%= @deploy_name %>
193
+ instances: 1
194
+ mem: 1G
195
+ framework:
196
+ name: standalone
197
+ runtime: java7
198
+ command: "java -Xms768m -Xmx768m -Dlog.logstash.source=\"${name}\" -Dlogback.configurationFile=logback-logstash.xml -jar poseidon.jar <%= @env %>"
199
+ url:
200
+ - <%= @env %>.poseidon.<%= @ship %>.<%= @org %>.mtnsatcloud.com
201
+ - <%= @env %>.poseidon.mtnsatcloud.com
202
+ min_version:
203
+ client: 1.4.3
204
+ services:
205
+ ${name}-db: mysql
206
+ ```
207
+
208
+
209
+ ## Test
210
+
211
+ $ bundle install
212
+ $ bundle exec rspec
213
+
214
+ To continously run specs when files are saved (or you hit return at the prompt):
215
+
216
+ $ bundle exec guard
data/bin/conan ADDED
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'conan/deploy'
4
+ require 'conan/version'
5
+ require 'conan/options'
6
+ require 'optparse'
7
+
8
+ options = {}
9
+
10
+ optparse = OptionParser.new do |o|
11
+ o.banner = "Usage: conan [options] pipeline environment"
12
+ o.separator ""
13
+ o.separator " pipeline - name of the pipeline to use"
14
+ o.separator " environment - name of a the target environment: integ,stage,prod"
15
+ o.separator ""
16
+ o.separator " Options:"
17
+
18
+ o.on( '-d', '--output-dir [DIR]', 'Generate manifest data to this directory' ) do |dir|
19
+ options[:directory] = dir
20
+ end
21
+
22
+ o.on( '-f', '--output-format [FORMAT]', [:properties, :stackato],
23
+ 'The format used to write output. Either "properties" for Jenkins build properties',
24
+ ' or "stackato" (default) to provision binaries and write stackato yml files',
25
+ ' from project templates.' ) do |format|
26
+ if (format)
27
+ options[:format] = format
28
+ else
29
+ puts "Unsupported --format option"
30
+ puts o
31
+ exit
32
+ end
33
+ end
34
+
35
+ o.on('-a','--action [ACTION]', [:provision,:configure,:deploy,:bg_configure,:bg_deploy,:bg_switch,:bg_clean,:all,:bg_all],
36
+ 'The action(s) to perform. Either "provision" (default), "configure","deploy" or "all".',
37
+ ' Support for blue/green deployments use actions: "provision", "bg_configure", "bg_deploy",',
38
+ ' "bg_switch", "bg_clean" or "bg_all".') do |action|
39
+ if (action)
40
+ options[:action] = action
41
+ else
42
+ puts "Unsupported --action option"
43
+ puts o
44
+ exit
45
+ end
46
+ end
47
+
48
+ o.on('-u','--paas-user [USER]', 'The stackato user name for deployments' ) do |user|
49
+ options[:'paas-user'] = user
50
+ end
51
+
52
+ o.on('-p','--paas-password [PASSWORD]', 'The stackato password name for deployments' ) do |pw|
53
+ options[:'paas-password'] = pw
54
+ end
55
+
56
+ o.on('-F','--force-deploy', 'Force deployment to bypass version checks.' ) do
57
+ options[:'force-deploy'] = true
58
+ end
59
+
60
+ o.on('-N', '--new-relic-api-key', 'New Relic API key for deployment alerts') do |api_key|
61
+ options[:'new-relic-api-key'] = api_key
62
+ end
63
+
64
+ o.on("-s", '--deploy-shipcloud [ORG-SHIP]', 'Only include deployments for the given shipcloud (org-ship)') do |shipcloud|
65
+ options[:'deploy-shipcloud'] = shipcloud
66
+ end
67
+
68
+ o.on('-D','--dry-run', 'Deployment dry-run. Prints Stackato commands' ) do
69
+ options[:'dry-run'] = true
70
+ end
71
+
72
+ o.on('-V','--verbose', 'Verbose console output' ) do
73
+ options[:verbose] = true
74
+ end
75
+
76
+ o.on("-v", "--version", "Show the software version") do
77
+ puts Conan::VERSION
78
+ exit
79
+ end
80
+
81
+ o.on_tail( '-h', '--help', 'Display this screen' ) do
82
+ puts o
83
+ exit
84
+ end
85
+ end
86
+ optparse.parse!
87
+
88
+
89
+ pl = if (ARGV.size < 1)
90
+ puts optparse
91
+ puts ''
92
+ raise ArgumentError, "No pipeline name argument was provided, e.g. nexus-apps-deploy"
93
+ else
94
+ ARGV[0].downcase.to_sym
95
+ end
96
+
97
+ env = if (ARGV.size < 2)
98
+ puts optparse
99
+ puts ''
100
+ raise ArgumentError, "No environment name argument was provided, e.g. integ"
101
+ else
102
+ ARGV[1].downcase.to_sym
103
+ end
104
+
105
+ Conan::Deploy.run(Conan::Options.new(options), pl, env)
@@ -0,0 +1,46 @@
1
+ require 'conan/manifest_builder'
2
+ require 'optparse'
3
+
4
+ module Conan
5
+ class Deploy
6
+ def self.run(options, pl, env)
7
+ puts "> Pipeline: #{pl}"
8
+ puts "> Environment: #{env}"
9
+
10
+ manifest = ManifestBuilder.build(options, pl, env) {
11
+ m = File.join(options[:directory], 'manifest.rb')
12
+ puts "> Manifest: #{m}"
13
+ instance_eval(File.read(m), m)
14
+ }
15
+
16
+ case options[:action]
17
+ when :provision
18
+ manifest.provision
19
+ when :configure
20
+ manifest.configure
21
+ when :deploy
22
+ manifest.deploy
23
+ when :bg_configure
24
+ manifest.bg_configure
25
+ when :bg_deploy
26
+ manifest.bg_deploy
27
+ when :bg_switch
28
+ manifest.bg_switch
29
+ when :bg_clean
30
+ manifest.bg_clean
31
+ when :all
32
+ manifest.provision
33
+ manifest.configure
34
+ manifest.deploy
35
+ when :bg_all
36
+ manifest.provision
37
+ manifest.bg_configure
38
+ manifest.bg_deploy
39
+ manifest.bg_switch
40
+ manifest.bg_clean
41
+ else
42
+ raise ArgumentError.new "Invalid action: #{options[:action]}"
43
+ end
44
+ end
45
+ end
46
+ end