conan_deploy_stackato3 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/README.md +223 -0
- data/bin/conan-stackato3 +131 -0
- data/lib/conan/application.rb +113 -0
- data/lib/conan/application_helper.rb +120 -0
- data/lib/conan/deploy.rb +41 -0
- data/lib/conan/deployment.rb +91 -0
- data/lib/conan/environment.rb +24 -0
- data/lib/conan/has_options.rb +15 -0
- data/lib/conan/jvm_app.rb +16 -0
- data/lib/conan/manifest.rb +100 -0
- data/lib/conan/manifest_builder.rb +14 -0
- data/lib/conan/newrelic.rb +16 -0
- data/lib/conan/options.rb +31 -0
- data/lib/conan/output.rb +180 -0
- data/lib/conan/pipeline.rb +102 -0
- data/lib/conan/rails_zip_app.rb +10 -0
- data/lib/conan/repository.rb +95 -0
- data/lib/conan/stackato.rb +105 -0
- data/lib/conan/templates.rb +38 -0
- data/lib/conan/version.rb +3 -0
- metadata +78 -0
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'rest_client'
|
2
|
+
require 'digest'
|
3
|
+
|
4
|
+
class DefaultArtifactRepository
|
5
|
+
@@artifact_repository_url = 'http://nexus.mtnsatcloud.com/nexus'
|
6
|
+
@@artifact_repository_local_api_url = "#{@@artifact_repository_url}/service/local/artifact/maven"
|
7
|
+
|
8
|
+
def resolveArtifact(group_id, artifact_id, extension, version='LATEST')
|
9
|
+
# we only care about the releases repo, no snapshots please
|
10
|
+
RestClient.get("#{@@artifact_repository_local_api_url}/resolve?r=releases&g=#{group_id}&a=#{artifact_id}&v=#{version}&e=#{extension}")
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
def downloadArtifact(output_dir, group_id, artifact_id, extension, version, sha1_hash)
|
15
|
+
if (extension == 'jar')
|
16
|
+
# put jars in a parent directory
|
17
|
+
output_dir = File.join(output_dir, "#{artifact_id}")
|
18
|
+
end
|
19
|
+
url="#{@@artifact_repository_local_api_url}/content?r=releases&g=#{group_id}&a=#{artifact_id}&v=#{version}&e=#{extension}"
|
20
|
+
target_file = File.join(output_dir, "#{artifact_id}.#{extension}")
|
21
|
+
HttpUtil.download(url, target_file, "#{artifact_id}-#{version}.#{extension}", sha1_hash)
|
22
|
+
|
23
|
+
# extract tar balls
|
24
|
+
if (extension == 'tar.gz')
|
25
|
+
dir = "#{output_dir}/#{artifact_id}"
|
26
|
+
FileUtils.rm_rf dir
|
27
|
+
FileUtils.mkdir_p dir
|
28
|
+
`tar -xf #{target_file} -C #{dir}`
|
29
|
+
# TODO fail if tar doesn't work
|
30
|
+
|
31
|
+
# extract deploy artifacts
|
32
|
+
elsif (extension == 'jar')
|
33
|
+
# templates
|
34
|
+
dir = "#{output_dir}/deploy-templates"
|
35
|
+
FileUtils.rm_rf dir
|
36
|
+
FileUtils.mkdir_p dir
|
37
|
+
c = "unzip -j #{target_file} 'META-INF/deploy/templates/*.erb' -d '#{dir}'"
|
38
|
+
system(c) or raise "unzip failed: #{c}"
|
39
|
+
|
40
|
+
# new relic extensions
|
41
|
+
dir = "#{output_dir}/extensions"
|
42
|
+
FileUtils.rm_rf dir
|
43
|
+
FileUtils.mkdir_p dir
|
44
|
+
c = "unzip -j #{target_file} 'META-INF/deploy/extensions/*.yml' -d '#{dir}'"
|
45
|
+
system(c) # extensions are optional, it's ok if this one fails
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def downloadNewRelicAgent(output_dir, nr_version, sha1_hash)
|
50
|
+
url = "#{@@artifact_repository_url}/content/groups/public/com/newrelic/agent/java/newrelic-agent/#{nr_version}/newrelic-agent-#{nr_version}.jar"
|
51
|
+
target_file = File.join(output_dir, "newrelic.jar")
|
52
|
+
HttpUtil.download(url, target_file, "newrelic-agent-#{nr_version}.jar", sha1_hash)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
module HttpUtil
|
57
|
+
def self.download(url, target_file, download_file_name, sha1_hash)
|
58
|
+
not_shasum = ->(file) {
|
59
|
+
ret = true
|
60
|
+
if (File.exists?(file))
|
61
|
+
# verify the file
|
62
|
+
found_hash = Digest::SHA1.file(file).hexdigest
|
63
|
+
puts "Found: #{found_hash}, Want: #{sha1_hash}"
|
64
|
+
if (found_hash != sha1_hash)
|
65
|
+
puts "#{file} is not the file we're looking for. It has a SHA1 hash of #{found_hash}, but #{sha1_hash} is expected"
|
66
|
+
ret = true
|
67
|
+
else
|
68
|
+
puts "#{file} matches checksum"
|
69
|
+
ret = false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
ret
|
73
|
+
}
|
74
|
+
|
75
|
+
if (not_shasum.call(target_file))
|
76
|
+
tmp = File.join(Dir.tmpdir(), "nexus-app-manifest")
|
77
|
+
FileUtils.mkdir_p tmp
|
78
|
+
download_file = File.join(tmp, download_file_name)
|
79
|
+
if (not_shasum.call(download_file))
|
80
|
+
# download it
|
81
|
+
puts "Fetching artifact #{download_file_name}"
|
82
|
+
puts " #{url}"
|
83
|
+
puts "..."
|
84
|
+
wget_cmd = "wget -nv \"#{url}\" --content-disposition --no-use-server-timestamps --output-document \"#{download_file}\""
|
85
|
+
puts wget_cmd
|
86
|
+
system( wget_cmd )
|
87
|
+
raise "Failed to download #{download_file_name}" if not_shasum.call(download_file)
|
88
|
+
end
|
89
|
+
# move download to target file
|
90
|
+
puts "cp #{download_file} to #{target_file}"
|
91
|
+
FileUtils.mkdir_p File.dirname(target_file)
|
92
|
+
FileUtils.copy(download_file, target_file)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'rest_client'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
class Stackato
|
5
|
+
|
6
|
+
class Commands
|
7
|
+
@@executable = "stackato-3.1.1"
|
8
|
+
@@token_file = File.join(Dir.tmpdir(), "token_#{Time.now.to_i}")
|
9
|
+
|
10
|
+
def initialize(target, dry_run=false)
|
11
|
+
@target = target
|
12
|
+
@dry_run = dry_run
|
13
|
+
end
|
14
|
+
|
15
|
+
def shell_cmd(stackato_cmd, args)
|
16
|
+
base_args = "--target #{@target} --token-file #{@@token_file}"
|
17
|
+
|
18
|
+
cmd = "#{@@executable} #{stackato_cmd} #{base_args} #{args}"
|
19
|
+
|
20
|
+
if @dry_run
|
21
|
+
puts "Dry-run, skipping execution of command: #{cmd}"
|
22
|
+
else
|
23
|
+
system(cmd)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def login(username, password, space)
|
28
|
+
shell_cmd("login", "--space #{space} --password '#{password}' #{username}")
|
29
|
+
end
|
30
|
+
|
31
|
+
def push(manifest)
|
32
|
+
shell_cmd("push", "--manifest #{manifest} --no-prompt --reset")
|
33
|
+
end
|
34
|
+
|
35
|
+
def delete(app_name)
|
36
|
+
shell_cmd("delete", "--no-prompt #{app_name}")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize(paas_user, paas_password, paas_space, dry_run=false)
|
41
|
+
@paas_user = paas_user
|
42
|
+
@paas_password = paas_password
|
43
|
+
@paas_space = paas_space
|
44
|
+
@dry_run = dry_run
|
45
|
+
@paas_manifest = "stackato.yml"
|
46
|
+
end
|
47
|
+
|
48
|
+
def login(paas_target)
|
49
|
+
# login only one time per target, and only one target at a time
|
50
|
+
if (@session != paas_target)
|
51
|
+
@session = paas_target
|
52
|
+
@commands = Commands.new(paas_target, @dry_run)
|
53
|
+
unless @paas_user.nil?
|
54
|
+
@commands.login(@paas_user, @paas_password, @paas_space)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def deploy(work_dir, app, deployment, force=false)
|
60
|
+
puts ''
|
61
|
+
Dir.chdir(work_dir){
|
62
|
+
login(deployment.paas_target)
|
63
|
+
|
64
|
+
paas_app_name = deployment.name(app)
|
65
|
+
yield paas_app_name if block_given?
|
66
|
+
|
67
|
+
# print out the stackato.yml for posterity
|
68
|
+
puts '------------------------------------------------------------------------------'
|
69
|
+
|
70
|
+
File.open(@paas_manifest, "r") do |f|
|
71
|
+
while (line = f.gets)
|
72
|
+
puts "#{line}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
puts '------------------------------------------------------------------------------'
|
76
|
+
puts ''
|
77
|
+
|
78
|
+
if (force)
|
79
|
+
puts "Deleting #{paas_app_name} if it exists. May be force be with you!"
|
80
|
+
@commands.delete(paas_app_name)
|
81
|
+
end
|
82
|
+
|
83
|
+
puts "Pushing #{paas_app_name}"
|
84
|
+
@commands.push(@paas_manifest)
|
85
|
+
}
|
86
|
+
end
|
87
|
+
|
88
|
+
def bg_deploy(work_dir, app, deployment)
|
89
|
+
puts ''
|
90
|
+
Dir.chdir(work_dir){
|
91
|
+
raise RuntimeError.new "Blue/green deployment is not implemented for the stackato v3 client yet"
|
92
|
+
|
93
|
+
# login(deployment.paas_target)
|
94
|
+
|
95
|
+
# push app
|
96
|
+
|
97
|
+
#if app.is_inactive_node_operational?
|
98
|
+
# switch (remap nodes)
|
99
|
+
# clean (delete inactive nodes)
|
100
|
+
#else
|
101
|
+
# raise RuntimeError.new "#{app}'s inactive node is not operational. Skipping switch and clean."
|
102
|
+
#end
|
103
|
+
}
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'erubis'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
module Templates
|
5
|
+
|
6
|
+
# Returns the number of files changed/created
|
7
|
+
def self.evaluate(templates_dir, output_dir, context)
|
8
|
+
no_changes = 0
|
9
|
+
FileUtils.mkdir_p File.dirname(output_dir)
|
10
|
+
Dir.glob(File.join(templates_dir, '*.erb')) do |template|
|
11
|
+
target_file = File.join(output_dir, File.basename(template)[0..-5])
|
12
|
+
eruby = Erubis::Eruby.new(File.read(template))
|
13
|
+
if (File.exist? target_file)
|
14
|
+
Tempfile.open(File.basename template) { |t|
|
15
|
+
t.write(eruby.evaluate(context))
|
16
|
+
t.rewind
|
17
|
+
if (FileUtils.identical? t.path, target_file)
|
18
|
+
puts "-- No change from: #{File.basename template} => #{target_file}"
|
19
|
+
else
|
20
|
+
puts ">> Replace file from template: #{File.basename template} => #{target_file}"
|
21
|
+
puts "------------------------------"
|
22
|
+
puts `diff -y -W 120 #{t.path} #{target_file}`
|
23
|
+
puts "------------------------------"
|
24
|
+
FileUtils.cp t.path, target_file
|
25
|
+
no_changes += 1
|
26
|
+
end
|
27
|
+
}
|
28
|
+
else
|
29
|
+
File.open(target_file, 'w') { |f|
|
30
|
+
puts "++ New file from template: #{File.basename template} => #{target_file}"
|
31
|
+
f.write(eruby.evaluate(context))
|
32
|
+
no_changes += 1
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
no_changes
|
37
|
+
end
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: conan_deploy_stackato3
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mike Reardon
|
8
|
+
- Michael Crane
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-09-04 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: daphne_util
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - '='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 0.2.0
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - '='
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 0.2.0
|
28
|
+
description: Provision, configure, deploy and never hear da lamantation of da users
|
29
|
+
email: michael.reardon@mtnsat.com
|
30
|
+
executables:
|
31
|
+
- conan-stackato3
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- README.md
|
36
|
+
- bin/conan-stackato3
|
37
|
+
- lib/conan/application.rb
|
38
|
+
- lib/conan/application_helper.rb
|
39
|
+
- lib/conan/deploy.rb
|
40
|
+
- lib/conan/deployment.rb
|
41
|
+
- lib/conan/environment.rb
|
42
|
+
- lib/conan/has_options.rb
|
43
|
+
- lib/conan/jvm_app.rb
|
44
|
+
- lib/conan/manifest.rb
|
45
|
+
- lib/conan/manifest_builder.rb
|
46
|
+
- lib/conan/newrelic.rb
|
47
|
+
- lib/conan/options.rb
|
48
|
+
- lib/conan/output.rb
|
49
|
+
- lib/conan/pipeline.rb
|
50
|
+
- lib/conan/rails_zip_app.rb
|
51
|
+
- lib/conan/repository.rb
|
52
|
+
- lib/conan/stackato.rb
|
53
|
+
- lib/conan/templates.rb
|
54
|
+
- lib/conan/version.rb
|
55
|
+
homepage: http://github.com/MTNSatelliteComm/conan/README.md
|
56
|
+
licenses: []
|
57
|
+
metadata: {}
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ! '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
requirements: []
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 2.2.2
|
75
|
+
signing_key:
|
76
|
+
specification_version: 4
|
77
|
+
summary: Conan da Deployer
|
78
|
+
test_files: []
|