conan_deploy 0.0.9 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/conan/output.rb CHANGED
@@ -10,15 +10,15 @@ class OutThingy
10
10
  end
11
11
 
12
12
  def outputToFile(file, &block)
13
- o = File.join(@output_dir, file)
14
- puts "Write: #{o}"
13
+ o = File.join(@output_dir, file)
14
+ puts "Write: #{o}"
15
15
  FileUtils.mkdir_p File.dirname(o)
16
16
  File.open(o, 'w') { |f| yield f }
17
17
  end
18
18
 
19
19
  def loadAppMetadataFromDeploymentIfExists(app, deploy)
20
20
  loadAppMetadataFromDeployment(app, deploy, true)
21
- end
21
+ end
22
22
  end
23
23
 
24
24
  class StackatoOutThingy < OutThingy
@@ -39,15 +39,15 @@ class StackatoOutThingy < OutThingy
39
39
  FileUtils.mkdir_p apps_dir
40
40
  end
41
41
 
42
- def clean(app, environment)
42
+ def clean(app, environment)
43
43
  # TODO: cleanup
44
44
  end
45
45
 
46
46
  def provision(app)
47
- app.download(@apps_dir)
47
+ app.download(@apps_dir)
48
48
  end
49
49
 
50
- def filePath(app, deploy)
50
+ def filePath(app, deploy)
51
51
  "#{deploy.environment.id}/#{deploy.shipcloud}/#{app.id}"
52
52
  end
53
53
 
@@ -56,9 +56,9 @@ class StackatoOutThingy < OutThingy
56
56
  end
57
57
 
58
58
  # TODO this needs a refactor, it's knoted up with App
59
- def loadAppMetadataFromDeployment(app, deploy, fail_silent=false)
59
+ def loadAppMetadataFromDeployment(app, deploy, fail_silent=false)
60
60
  p = filePath(app, deploy)
61
- path = File.join(@environments_dir, p)
61
+ path = File.join(@environments_dir, p)
62
62
  metadata_file = File.join(path, @@metadata_file_name)
63
63
 
64
64
  if (File.exists? path)
@@ -66,7 +66,7 @@ class StackatoOutThingy < OutThingy
66
66
  else
67
67
  raise "Build meta-data was not found: #{path}" unless fail_silent
68
68
  end
69
- end
69
+ end
70
70
 
71
71
  def writeArtifactMetadata(app, deploy)
72
72
  if (deploy.enabled?)
@@ -76,15 +76,15 @@ class StackatoOutThingy < OutThingy
76
76
  }
77
77
  end
78
78
  end
79
-
79
+
80
80
  def writeConfiguration(app, deploy, bg=false)
81
- if (deploy.enabled?)
81
+ if (deploy.enabled?)
82
82
  target_dir = workingDir(app)
83
83
  templates_dir = File.join(target_dir, "deploy-templates")
84
84
 
85
- daphne_tokens = [ "#{app.id}", "#{deploy.environment.id}" ]
85
+ daphne_tokens = [ "#{app.id}", "#{deploy.environment.id}" ]
86
86
  daphne_tokens = daphne_tokens << "facility-#{deploy.facility_id}" unless deploy.facility_id.nil?
87
-
87
+
88
88
  n_changes = Templates.evaluate templates_dir, target_dir, {
89
89
  :app => app,
90
90
  :deploy => deploy,
@@ -95,10 +95,10 @@ class StackatoOutThingy < OutThingy
95
95
  :oauth_secret => DaphneUtil.generate_secret(*daphne_tokens),
96
96
  :api_key => DaphneUtil.generate_api_key(*daphne_tokens),
97
97
 
98
- # short-cuts
98
+ # short-cuts
99
99
  :app_id => app.id,
100
100
  :deploy_base_name => deploy.name(app),
101
- :deploy_name => bg ? deploy.unique_name(app) : deploy.name(app),
101
+ :deploy_name => bg ? app.unique_name : deploy.name(app),
102
102
  :deploy_urls => bg ? deploy.inactive_urls(app) : deploy.active_urls(app),
103
103
  :env => deploy.environment.id,
104
104
  :org => deploy.org,
@@ -106,7 +106,7 @@ class StackatoOutThingy < OutThingy
106
106
  :infra => deploy.shipcloud, # TODO: remove infra key, this is just to avoid breaking existing templates
107
107
  :shipcloud => deploy.shipcloud,
108
108
  :facility => deploy.facility_id,
109
- :options => deploy.options
109
+ :options => deploy.options
110
110
  }
111
111
  end
112
112
  #TODO: can this be used to provide idempotency for config-only deploymnent?
@@ -116,19 +116,19 @@ end
116
116
 
117
117
  class PropertiesFileOutThingy < OutThingy
118
118
 
119
- def clean(app, environment)
119
+ def clean(app, environment)
120
120
  # cleanup current
121
- FileUtils.rm Dir.glob("#{@output_dir}/#{app.id}-deploy-#{environment.id}-*.properties")
121
+ FileUtils.rm Dir.glob("#{@output_dir}/#{app.id}-deploy-#{environment.id}-*.properties")
122
122
  end
123
123
 
124
- def fileName(app, deploy)
124
+ def fileName(app, deploy)
125
125
  "#{app.id}-deploy-#{deploy.environment.id}-#{deploy.shipcloud}.properties"
126
126
  end
127
127
 
128
128
  def loadAppMetadataFromDeployment(app, deploy, fail_silent=false)
129
129
  path = File.join(@output_dir, fileName(app, deploy))
130
130
  if (File.exists? path)
131
- props = Utils::Properties.load_from_file(path, true)
131
+ props = Utils::Properties.load_from_file(path, true)
132
132
  app.version = props.get(:DEPLOY_VERSION) # TODO: preserve SHA1
133
133
  else
134
134
  raise "File not found: #{path}" unless fail_silent
@@ -138,16 +138,16 @@ class PropertiesFileOutThingy < OutThingy
138
138
  def writeArtifactMetadata(app, deploy)
139
139
  file_name = fileName(app, deploy)
140
140
  out_file = File.join(@output_dir, file_name)
141
- if (!deploy.enabled?)
142
- if (File.exists? out_file)
141
+ if (!deploy.enabled?)
142
+ if (File.exists? out_file)
143
143
  File.delete(out_file)
144
144
  end
145
- out_file = File.join(@output_dir, "DISABLED-#{file_name}")
145
+ out_file = File.join(@output_dir, "DISABLED-#{file_name}")
146
146
  end
147
147
  puts "Write: #{out_file}"
148
148
  File.open(out_file, 'w') { |f|
149
149
  # TODO: would like @time in the manifest as audit field, but not sure it's such a good idea yet
150
- # f << "\# #{file_name}\n\# #{@time}\n"
150
+ # f << "\# #{file_name}\n\# #{@time}\n"
151
151
  f << "\# #{file_name}\n"
152
152
  f << "DEPLOY_ENV=#{deploy.environment.id}\n"
153
153
  f << "DEPLOY_INFRA=#{deploy.shipcloud}\n"
@@ -0,0 +1,130 @@
1
+ class Pipeline
2
+ include ApiHelper
3
+
4
+ attr_accessor :id, :apps
5
+
6
+ def initialize(id, artifact_repo, output, options)
7
+ @id = id
8
+ @artifact_repo = artifact_repo
9
+ @output = output
10
+ @apps = {}
11
+ @options = options
12
+ end
13
+
14
+ def app(app_id, project_name, platform_type, url_segment=nil)
15
+ if (@options[:'deploy-app-name'].nil?) || (@options[:'deploy-app-name'] == app_id.to_s)
16
+ puts "No app specified, or we matched the specified app: #{@options[:'deploy-app-name']}"
17
+ @apps[app_id] = case platform_type
18
+ when :jvm
19
+ JvmApp.new(app_id, project_name, @artifact_repo, @options, url_segment)
20
+ when :rails_zip
21
+ RailsZipApp.new(app_id, project_name, @artifact_repo, @options, url_segment)
22
+ else
23
+ raise "unknown platform type: #{platform_type}"
24
+ end
25
+ else
26
+ puts "App #{app_id} doesn't match specified app #{@options[:'deploy-app-name']}, skipping"
27
+ end
28
+ end
29
+
30
+ def appVersion(app_id)
31
+ @apps[app_id].version
32
+ end
33
+
34
+ def load!(environment, deploy_shipcloud)
35
+ eachAppDeployment(environment) { |app, deploy|
36
+ # load the persisted meta-data
37
+ @output.loadAppMetadataFromDeploymentIfExists(app, deploy)
38
+ }
39
+ @deploy_shipcloud = deploy_shipcloud
40
+ end
41
+
42
+ def update(environment, from_upstream_env)
43
+ @apps.values.each { |app|
44
+ puts ''
45
+ if !(@options[:'deploy-app-version'].nil?)
46
+ puts "Using version from options: #{@options[:'deploy-app-version']}"
47
+ app.findRequestedVersion(@options[:'deploy-app-version'])
48
+ elsif (from_upstream_env)
49
+ # promote versions from an upstream deploy
50
+ # TODO: this needs improving
51
+ puts "Promote #{app.id} from #{from_upstream_env.id} to #{environment.id}"
52
+ upstream_deploy = from_upstream_env.deployments.select { |d| d.app_ids.select {|x| x == app.id }.size > 0 }.first
53
+ @output.loadAppMetadataFromDeployment(app, upstream_deploy)
54
+ else
55
+ puts "Find latest #{app.artifact_id}"
56
+ # lookup most recent from repo
57
+ app.findRequestedVersion('LATEST')
58
+ end
59
+ @output.clean(app, environment)
60
+ # download artifacts
61
+ @output.provision(app)
62
+ }
63
+
64
+ # write out deployment artifact meta-data
65
+ eachAppDeployment(environment) { |app, deploy| @output.writeArtifactMetadata(app, deploy) }
66
+ end
67
+
68
+ def configure(environment, bg=false)
69
+ eachAppDeployment(environment) { |app, deploy| @output.writeConfiguration(app, deploy, bg) }
70
+ end
71
+
72
+ def deploy(environment, paas, force=false)
73
+ eachAppDeployment(environment) { |app, deploy|
74
+ work_dir = @output.workingDir(app)
75
+ if (force)
76
+ paas.deploy(work_dir, app, deploy, true)
77
+ else
78
+ paas.deploy(work_dir, app, deploy) unless app.isDeployedAt(deploy.manifest_url(app))
79
+ end
80
+ }
81
+ end
82
+
83
+ def bg_deploy(environment, paas, force=false)
84
+ apps = []
85
+ eachAppDeployment(environment) { |app, deploy|
86
+ if (force or !app.isDeployedAt(deploy.manifest_url(app)))
87
+ paas.bg_deploy(@output.workingDir(app), app, deploy)
88
+ apps << app
89
+ end
90
+ }
91
+ apps
92
+ end
93
+
94
+ def is_inactive_node_operational?(environment, paas)
95
+ eachAppDeployment(environment) { |app, deploy|
96
+ response = ApiHelper.smoke_test(deploy.inactive_smoke_test_url(app), 60)
97
+
98
+ if(response.code != 200)
99
+ puts "Smoke test failed for inactive (Blue) node. Here is the entire response: #{response.inspect}"
100
+ return false
101
+ else
102
+ return true
103
+ end
104
+ }
105
+ end
106
+
107
+ def bg_switch(environment, paas)
108
+ eachAppDeployment(environment) { |app, deploy| paas.bg_switch(app, deploy) }
109
+ end
110
+
111
+ def bg_clean(environment, paas)
112
+ eachAppDeployment(environment) { |app, deploy| paas.bg_clean(app, deploy) }
113
+ end
114
+
115
+ def eachAppDeployment(environment)
116
+ selected_deployments = environment.deployments.select{ |d| @deploy_shipcloud.nil? || d.shipcloud == @deploy_shipcloud }
117
+ puts "WARNING no deploys selected: #{@deploy_shipcloud}" if selected_deployments.empty?
118
+ selected_deployments.each do |d|
119
+ d.app_ids.each do |a|
120
+ unless @apps[a].nil?
121
+ app = @apps[a]
122
+ app.additional_mappings = d.additional_mappings
123
+ app.unique_name = d.unique_name(app)
124
+ app.smoke_test_path = d.smoke_test_path
125
+ yield app, d
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,10 @@
1
+ require 'conan/application'
2
+ class RailsZipApp < Application
3
+ attr_accessor :sha1, :artifact_repo
4
+
5
+ def initialize(id, project_name, artifact_repo, options, url_segment=nil)
6
+ super(id, project_name, :rails_zip, options, url_segment)
7
+ @sha1 = nil
8
+ @artifact_repo = artifact_repo
9
+ end
10
+ end
@@ -3,13 +3,13 @@ require 'json'
3
3
 
4
4
  class Stackato
5
5
 
6
+ @@paas_token_file = File.join(Dir.tmpdir(), "token_#{Time.now.to_i}")
7
+
6
8
  def initialize(paas_user, paas_password, trace=false, dry_run=false)
7
9
  @paas_user = paas_user
8
10
  @paas_password = paas_password
9
11
  @doit = dry_run ? "echo " : ""
10
12
  @trace = trace ? "--trace" : ""
11
- random_str = (0...8).map { ('a'..'z').to_a[rand(26)] }.join
12
- @paas_token_file = File.join(Dir.tmpdir(), "token_#{random_str}")
13
13
  @paas_manifest = "stackato.yml"
14
14
  end
15
15
 
@@ -17,16 +17,67 @@ class Stackato
17
17
  # login only one time per target, and only one target at a time
18
18
  if (@session != paas_target)
19
19
  @session = paas_target
20
- @paas_cmd = "stackato #{@trace} --target #{paas_target} --token-file #{@paas_token_file}"
20
+ @paas_cmd = "stackato #{@trace} --target #{paas_target} --token-file #{@@paas_token_file}"
21
21
  unless @paas_user.nil?
22
22
  system( "#{@paas_cmd} login --user #{@paas_user} --password #{@paas_password}" ) or raise "Stackato login failed on #{paas_target}"
23
23
  end
24
24
  end
25
25
  end
26
26
 
27
- def deploy(work_dir, app, deployment, force=false)
28
- puts ''
29
- Dir.chdir(work_dir){
27
+ def self.static_login(options)
28
+ org = options[:'deploy-shipcloud'].split('-')[0]
29
+ infra = options[:'deploy-shipcloud'].split('-')[1]
30
+ `stackato --target https://api.paas.#{infra}.#{org}.mtnsatcloud.com --token-file #{@@paas_token_file}`
31
+ `stackato login --user #{options[:'paas-user']} --password #{options[:'paas-password']} --token-file #{@@paas_token_file}`
32
+ end
33
+
34
+ def self.unmap(app, domain)
35
+ puts "[#{app.unique_name}] Unmapping #{domain}"
36
+ `stackato unmap #{app.unique_name} #{domain} --token-file #{@@paas_token_file}`
37
+ end
38
+
39
+ def self.map(app, domain)
40
+ puts "[#{app.unique_name}] Mapping #{domain}"
41
+ `stackato map #{app.unique_name} #{domain} --token-file #{@@paas_token_file}`
42
+ end
43
+
44
+ def self.stop(app)
45
+ puts "[#{app.unique_name}] Stopping"
46
+ `stackato stop #{app.unique_name} --token-file #{@@paas_token_file}`
47
+ end
48
+
49
+ def self.delete(app)
50
+ puts "[#{app.unique_name}] Deleting"
51
+ `stackato delete #{app.unique_name} --token-file #{@@paas_token_file}`
52
+ end
53
+
54
+ def self.bg_switch(app)
55
+ app.active_domains.each{ |domain| Stackato.map(app, domain) }
56
+ app.inactive_domains.each{ |domain| Stackato.unmap(app, domain) }
57
+ app.old_versions.each{ |old_app| old_app.active_domains.each { |domain| Stackato.unmap(old_app, domain) } }
58
+ app.old_versions.each{ |old_app| old_app.inactive_domains.each { |domain| Stackato.map(old_app, domain) } }
59
+ end
60
+
61
+ def self.bg_clean(app)
62
+ app.old_versions.each { |old_app| Stackato.stop(old_app) }
63
+ app.old_versions.each { |old_app| Stackato.delete(old_app) }
64
+ end
65
+
66
+ def self.find_old_versions(newly_deployed_app)
67
+ old_apps = []
68
+ JSON.parse(`stackato apps --json --token-file #{@@paas_token_file}`).map do |app|
69
+ if /#{Regexp.escape(newly_deployed_app.stackato_base_name)}/ =~ app["name"] and app["name"] != newly_deployed_app.unique_name
70
+ old_app = newly_deployed_app.clone
71
+ old_app.unique_name = app["name"]
72
+ old_apps << old_app
73
+ end
74
+ end
75
+ old_apps
76
+ end
77
+
78
+ def deploy(work_dir, app, deployment, force=false)
79
+ puts ''
80
+ Dir.chdir(work_dir){
30
81
  login(deployment.paas_target)
31
82
 
32
83
  paas_app_name = deployment.name(app)
@@ -44,7 +95,7 @@ class Stackato
44
95
  stats_status = `#{@paas_cmd} stats #{paas_app_name} 2>&1 >/dev/null`
45
96
  puts stats_status
46
97
  raise ScriptError, "Stackato authorization failure. Provide user and password" if (stats_status =~ /Not Authorized/)
47
-
98
+
48
99
  # print out the stackato.yml for posterity
49
100
  puts '------------------------------------------------------------------------------'
50
101
 
@@ -82,19 +133,22 @@ class Stackato
82
133
  login(deployment.paas_target)
83
134
 
84
135
  app_info = application_info(app, deployment)
85
- raise "Please remove inactive app '#{app_info.inactive_app_name}' before proceeding." unless app_info.inactive_app_name.nil?
136
+ unless app_info.inactive_app_name.nil?
137
+ puts "inactive app [#{deployment.name(app)}]. Deleting it."
138
+ `stackato delete #{deployment.name(app)}`
139
+ end
86
140
 
87
- puts "Deploying inactive app #{deployment.name(app)}"
141
+ puts "Deploying inactive app #{deployment.name(app)}"
88
142
  c = "#{@doit} #{@paas_cmd} --manifest #{@paas_manifest} --no-prompt push"
89
143
  system(c) or raise "Stackato push failed: #{c}"
90
144
  }
91
- end
145
+ end
92
146
 
93
147
  def bg_switch(app, deployment)
94
148
  login(deployment.paas_target)
95
149
 
96
150
  app_info = application_info(app, deployment)
97
-
151
+
98
152
  if app_info.inactive_app_name.nil?
99
153
  puts "No inactive app to switch to."
100
154
  return
data/lib/conan/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Conan
2
- VERSION = "0.0.9"
3
- end
2
+ VERSION = "0.0.12"
3
+ end
metadata CHANGED
@@ -1,7 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: conan_deploy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.12
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Mike Reardon
@@ -9,11 +10,12 @@ authors:
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2014-05-19 00:00:00.000000000 Z
13
+ date: 2014-06-06 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: daphne_util
16
17
  requirement: !ruby/object:Gem::Requirement
18
+ none: false
17
19
  requirements:
18
20
  - - '='
19
21
  - !ruby/object:Gem::Version
@@ -21,6 +23,7 @@ dependencies:
21
23
  type: :runtime
22
24
  prerelease: false
23
25
  version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
24
27
  requirements:
25
28
  - - '='
26
29
  - !ruby/object:Gem::Version
@@ -32,39 +35,48 @@ executables:
32
35
  extensions: []
33
36
  extra_rdoc_files: []
34
37
  files:
35
- - README.md
36
38
  - bin/conan
39
+ - lib/conan/application.rb
37
40
  - lib/conan/application_helper.rb
38
41
  - lib/conan/deploy.rb
42
+ - lib/conan/deployment.rb
43
+ - lib/conan/environment.rb
44
+ - lib/conan/has_options.rb
45
+ - lib/conan/jvm_app.rb
46
+ - lib/conan/manifest.rb
39
47
  - lib/conan/manifest_builder.rb
40
48
  - lib/conan/newrelic.rb
41
49
  - lib/conan/options.rb
42
50
  - lib/conan/output.rb
51
+ - lib/conan/pipeline.rb
52
+ - lib/conan/rails_zip_app.rb
43
53
  - lib/conan/repository.rb
44
54
  - lib/conan/stackato.rb
45
55
  - lib/conan/templates.rb
46
56
  - lib/conan/version.rb
57
+ - README.md
47
58
  homepage: http://github.com/MTNSatelliteComm/conan/README.md
48
59
  licenses: []
49
- metadata: {}
50
60
  post_install_message:
51
61
  rdoc_options: []
52
62
  require_paths:
53
63
  - lib
54
64
  required_ruby_version: !ruby/object:Gem::Requirement
65
+ none: false
55
66
  requirements:
56
67
  - - ! '>='
57
68
  - !ruby/object:Gem::Version
58
69
  version: '0'
59
70
  required_rubygems_version: !ruby/object:Gem::Requirement
71
+ none: false
60
72
  requirements:
61
73
  - - ! '>='
62
74
  - !ruby/object:Gem::Version
63
75
  version: '0'
64
76
  requirements: []
65
77
  rubyforge_project:
66
- rubygems_version: 2.2.2
78
+ rubygems_version: 1.8.23
67
79
  signing_key:
68
- specification_version: 4
80
+ specification_version: 3
69
81
  summary: Conan da Deployer
70
82
  test_files: []