dpl-connect 1.8.43

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.
Files changed (105) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +8 -0
  4. data/.rspec +2 -0
  5. data/.travis.yml +36 -0
  6. data/Gemfile +100 -0
  7. data/LICENSE +22 -0
  8. data/README.md +934 -0
  9. data/Rakefile +1 -0
  10. data/TESTING.md +29 -0
  11. data/bin/dpl +5 -0
  12. data/dpl.gemspec +32 -0
  13. data/lib/dpl/cli.rb +66 -0
  14. data/lib/dpl/error.rb +3 -0
  15. data/lib/dpl/provider.rb +264 -0
  16. data/lib/dpl/provider/anynines.rb +13 -0
  17. data/lib/dpl/provider/appfog.rb +21 -0
  18. data/lib/dpl/provider/atlas.rb +108 -0
  19. data/lib/dpl/provider/azure_webapps.rb +48 -0
  20. data/lib/dpl/provider/bintray.rb +509 -0
  21. data/lib/dpl/provider/bitballoon.rb +22 -0
  22. data/lib/dpl/provider/bluemix_cloud_foundry.rb +23 -0
  23. data/lib/dpl/provider/boxfuse.rb +57 -0
  24. data/lib/dpl/provider/catalyze.rb +49 -0
  25. data/lib/dpl/provider/chef_supermarket.rb +85 -0
  26. data/lib/dpl/provider/cloud66.rb +38 -0
  27. data/lib/dpl/provider/cloud_files.rb +38 -0
  28. data/lib/dpl/provider/cloud_foundry.rb +43 -0
  29. data/lib/dpl/provider/code_deploy.rb +123 -0
  30. data/lib/dpl/provider/deis.rb +119 -0
  31. data/lib/dpl/provider/divshot.rb +23 -0
  32. data/lib/dpl/provider/elastic_beanstalk.rb +195 -0
  33. data/lib/dpl/provider/engine_yard.rb +90 -0
  34. data/lib/dpl/provider/firebase.rb +27 -0
  35. data/lib/dpl/provider/gae.rb +97 -0
  36. data/lib/dpl/provider/gcs.rb +59 -0
  37. data/lib/dpl/provider/hackage.rb +29 -0
  38. data/lib/dpl/provider/heroku.rb +18 -0
  39. data/lib/dpl/provider/heroku/api.rb +98 -0
  40. data/lib/dpl/provider/heroku/generic.rb +94 -0
  41. data/lib/dpl/provider/heroku/git.rb +28 -0
  42. data/lib/dpl/provider/lambda.rb +236 -0
  43. data/lib/dpl/provider/launchpad.rb +48 -0
  44. data/lib/dpl/provider/modulus.rb +23 -0
  45. data/lib/dpl/provider/npm.rb +64 -0
  46. data/lib/dpl/provider/openshift.rb +59 -0
  47. data/lib/dpl/provider/ops_works.rb +132 -0
  48. data/lib/dpl/provider/packagecloud.rb +144 -0
  49. data/lib/dpl/provider/pages.rb +79 -0
  50. data/lib/dpl/provider/puppet_forge.rb +43 -0
  51. data/lib/dpl/provider/pypi.rb +111 -0
  52. data/lib/dpl/provider/releases.rb +139 -0
  53. data/lib/dpl/provider/rubygems.rb +51 -0
  54. data/lib/dpl/provider/s3.rb +123 -0
  55. data/lib/dpl/provider/scalingo.rb +97 -0
  56. data/lib/dpl/provider/script.rb +29 -0
  57. data/lib/dpl/provider/surge.rb +33 -0
  58. data/lib/dpl/provider/testfairy.rb +190 -0
  59. data/lib/dpl/provider/transifex.rb +45 -0
  60. data/lib/dpl/version.rb +3 -0
  61. data/notes/engine_yard.md +1 -0
  62. data/notes/heroku.md +3 -0
  63. data/spec/cli_spec.rb +36 -0
  64. data/spec/provider/anynines_spec.rb +20 -0
  65. data/spec/provider/appfog_spec.rb +35 -0
  66. data/spec/provider/atlas_spec.rb +99 -0
  67. data/spec/provider/azure_webapps_spec.rb +95 -0
  68. data/spec/provider/bintray_spec.rb +259 -0
  69. data/spec/provider/bitballoon_spec.rb +32 -0
  70. data/spec/provider/bluemixcloudfoundry_spec.rb +23 -0
  71. data/spec/provider/boxfuse_spec.rb +16 -0
  72. data/spec/provider/catalyze_spec.rb +39 -0
  73. data/spec/provider/chef_supermarket_spec.rb +51 -0
  74. data/spec/provider/cloud66_spec.rb +44 -0
  75. data/spec/provider/cloud_files_spec.rb +88 -0
  76. data/spec/provider/cloudfoundry_spec.rb +71 -0
  77. data/spec/provider/code_deploy_spec.rb +360 -0
  78. data/spec/provider/deis_spec.rb +116 -0
  79. data/spec/provider/divshot_spec.rb +28 -0
  80. data/spec/provider/elastic_beanstalk_spec.rb +209 -0
  81. data/spec/provider/firebase_spec.rb +40 -0
  82. data/spec/provider/gae_spec.rb +26 -0
  83. data/spec/provider/gcs_spec.rb +115 -0
  84. data/spec/provider/hackage_spec.rb +47 -0
  85. data/spec/provider/heroku_spec.rb +357 -0
  86. data/spec/provider/lambda_spec.rb +432 -0
  87. data/spec/provider/launchpad_spec.rb +33 -0
  88. data/spec/provider/modulus_spec.rb +29 -0
  89. data/spec/provider/npm_spec.rb +95 -0
  90. data/spec/provider/openshift_spec.rb +91 -0
  91. data/spec/provider/ops_works_spec.rb +127 -0
  92. data/spec/provider/packagecloud_spec.rb +56 -0
  93. data/spec/provider/puppet_forge_spec.rb +60 -0
  94. data/spec/provider/pypi_spec.rb +103 -0
  95. data/spec/provider/releases_spec.rb +303 -0
  96. data/spec/provider/rubygems_spec.rb +106 -0
  97. data/spec/provider/s3_spec.rb +174 -0
  98. data/spec/provider/scalingo_spec.rb +64 -0
  99. data/spec/provider/script_spec.rb +26 -0
  100. data/spec/provider/surge_spec.rb +15 -0
  101. data/spec/provider/testfairy_spec.rb +86 -0
  102. data/spec/provider/transifex_spec.rb +110 -0
  103. data/spec/provider_spec.rb +210 -0
  104. data/spec/spec_helper.rb +20 -0
  105. metadata +279 -0
@@ -0,0 +1,119 @@
1
+ module DPL
2
+ class Provider
3
+ class Deis < Provider
4
+
5
+ def install_deploy_dependencies
6
+ install_url = determine_install_url
7
+ context.shell "curl -sSL #{install_url} | bash -x -s #{option(:cli_version)}"
8
+ end
9
+
10
+ #Default to installing the default v1 client. Otherwise determine if this is a v2 client
11
+ def determine_install_url
12
+ return "https://raw.githubusercontent.com/teamhephy/workflow-cli/master/install-v2.sh"
13
+ end
14
+
15
+ def needs_key?
16
+ true
17
+ end
18
+
19
+ def check_auth
20
+ unless context.shell "./deis login #{option(:controller)}" \
21
+ " --username=#{option(:username)}" \
22
+ " --password=#{option(:password)}"
23
+ error 'Login failed.'
24
+ end
25
+ end
26
+
27
+ def check_app
28
+ unless context.shell "./deis apps:info --app=#{option(:app)}"
29
+ error 'Application could not be verified.'
30
+ end
31
+ end
32
+
33
+ def setup_key(file)
34
+ unless context.shell "./deis keys:add #{file}"
35
+ error 'Adding keys failed.'
36
+ end
37
+ end
38
+
39
+ def setup_git_ssh(path, key_path)
40
+ key_path = File.expand_path(key_path)
41
+ path = File.expand_path(path)
42
+
43
+ File.open(path, 'w') do |file|
44
+ file.write "#!/bin/sh\n"
45
+ file.write "exec ssh #{verbose_flag} -o StrictHostKeychecking=no -o CheckHostIP=no -o UserKnownHostsFile=/dev/null -i #{key_path} \"$@\"\n"
46
+ end
47
+
48
+ chmod(0740, path)
49
+ context.env['GIT_SSH'] = path
50
+
51
+ wait_for_git_access
52
+ end
53
+
54
+ def wait_for_git_access()
55
+ retry_count=0
56
+ max_retries=30
57
+
58
+ #Get the deis git remote host and port
59
+ remote_uri=repository_url.split("ssh://")[1].split("/")[0]
60
+ remote_host, remote_port = remote_uri.split(":")
61
+ puts "Git remote is #{remote_host} at port #{remote_port}"
62
+
63
+ #Try and connect to the github remote via ssh.
64
+ while retry_count < max_retries
65
+ puts "Waiting for ssh key to propagate..."
66
+ if context.shell "#{context.env['GIT_SSH']} #{remote_host} -p #{remote_port} 2>&1 | grep -c 'PTY allocation request failed' > /dev/null"
67
+ puts "SSH connection established."
68
+ break
69
+ end
70
+ retry_count += 1
71
+ sleep(1)
72
+ end
73
+ end
74
+
75
+ def remove_key
76
+ unless context.shell "./deis keys:remove #{option(:key_name)}"
77
+ error 'Removing keys failed.'
78
+ end
79
+ end
80
+
81
+ def repository_url
82
+ "ssh://git@#{builder_hostname}:2222/#{option(:app)}.git"
83
+ end
84
+
85
+ def builder_hostname
86
+ host_tokens = controller_host.split(".")
87
+ host_tokens[0] = [host_tokens[0], "builder"].join("-")
88
+ host_tokens.join(".")
89
+ end
90
+
91
+ def controller_host
92
+ option(:controller).gsub(/https?:\/\//, "").split(":")[0]
93
+ end
94
+
95
+ def push_app
96
+ unless context.shell "bash -c 'git push #{verbose_flag} #{repository_url} HEAD:refs/heads/master -f 2>&1 | tr -dc \"[:alnum:][:space:][:punct:]\" | sed -E \"s/remote: (\\[1G)+//\" | sed \"s/\\[K$//\"; exit ${PIPESTATUS[0]}'"
97
+ error 'Deploying application failed.'
98
+ end
99
+ end
100
+
101
+ def run(command)
102
+ unless context.shell "./deis run -a #{option(:app)} -- #{command}"
103
+ error 'Running command failed.'
104
+ end
105
+ end
106
+
107
+ def cleanup
108
+ return if options[:skip_cleanup]
109
+ context.shell "mv deis ~/deis"
110
+ super
111
+ context.shell "mv ~/deis deis"
112
+ end
113
+
114
+ def verbose_flag
115
+ '-v' if options[:verbose]
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,23 @@
1
+ module DPL
2
+ class Provider
3
+ class Divshot < Provider
4
+ npm_g 'divshot-cli', 'divshot'
5
+
6
+ def check_auth
7
+ raise Error, "must supply an api key" unless option(:api_key)
8
+ end
9
+
10
+ def check_app
11
+ error "missing divshot.json" unless File.exist? "divshot.json"
12
+ end
13
+
14
+ def needs_key?
15
+ false
16
+ end
17
+
18
+ def push_app
19
+ context.shell "divshot push #{options[:environment] || "production"} --token=#{option(:api_key)}"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,195 @@
1
+ require 'time'
2
+
3
+ module DPL
4
+ class Provider
5
+ class ElasticBeanstalk < Provider
6
+ experimental 'AWS Elastic Beanstalk'
7
+
8
+ requires 'aws-sdk', version: '~> 2.0'
9
+ requires 'rubyzip', :load => 'zip'
10
+
11
+ DEFAULT_REGION = 'us-east-1'
12
+
13
+ def needs_key?
14
+ false
15
+ end
16
+
17
+ def access_key_id
18
+ options[:access_key_id] || context.env['AWS_ACCESS_KEY_ID'] || raise(Error, "missing access_key_id")
19
+ end
20
+
21
+ def secret_access_key
22
+ options[:secret_access_key] || context.env['AWS_SECRET_ACCESS_KEY'] || raise(Error, "missing secret_access_key")
23
+ end
24
+
25
+ def check_auth
26
+ options = {
27
+ :region => region,
28
+ :credentials => Aws::Credentials.new(access_key_id, secret_access_key)
29
+ }
30
+ Aws.config.update(options)
31
+ end
32
+
33
+ def check_app
34
+ end
35
+
36
+ def only_create_app_version
37
+ options[:only_create_app_version]
38
+ end
39
+
40
+ def push_app
41
+ @start_time = Time.now
42
+ create_bucket unless bucket_exists?
43
+
44
+ if options[:zip_file]
45
+ zip_file = File.expand_path(options[:zip_file])
46
+ else
47
+ zip_file = create_zip
48
+ end
49
+
50
+ s3_object = upload(archive_name, zip_file)
51
+ sleep 5 #s3 eventual consistency
52
+ version = create_app_version(s3_object)
53
+ if !only_create_app_version
54
+ update_app(version)
55
+ wait_until_deployed if options[:wait_until_deployed]
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def app_name
62
+ option(:app)
63
+ end
64
+
65
+ def env_name
66
+ options[:env] || context.env['ELASTIC_BEANSTALK_ENV'] || raise(Error, "missing env")
67
+ end
68
+
69
+ def version_label
70
+ context.env['ELASTIC_BEANSTALK_LABEL'] || "travis-#{sha}-#{Time.now.to_i}"
71
+ end
72
+
73
+ def version_description
74
+ context.env['ELASTIC_BEANSTALK_DESCRIPTION'] || commit_msg
75
+ end
76
+
77
+ def archive_name
78
+ "#{version_label}.zip"
79
+ end
80
+
81
+ def region
82
+ options[:region] || DEFAULT_REGION
83
+ end
84
+
85
+ def bucket_name
86
+ option(:bucket_name)
87
+ end
88
+
89
+ def bucket_path
90
+ @bucket_path ||= options[:bucket_path] ? option(:bucket_path).gsub(/\/*$/,'/') : nil
91
+ end
92
+
93
+ def s3
94
+ @s3 ||= Aws::S3::Resource.new
95
+ end
96
+
97
+ def eb
98
+ @eb ||= Aws::ElasticBeanstalk::Client.new
99
+ end
100
+
101
+ def bucket_exists?
102
+ s3.bucket(bucket_name).exists?
103
+ end
104
+
105
+ def create_bucket
106
+ s3.bucket(bucket_name).create
107
+ end
108
+
109
+ def files_to_pack
110
+ `git ls-files -z`.split("\x0")
111
+ end
112
+
113
+ def create_zip
114
+ directory = Dir.pwd
115
+ zipfile_name = File.join(directory, archive_name)
116
+
117
+ Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
118
+ files_to_pack.each do |file|
119
+ relative_archive_path = File.join(directory, '/')
120
+ zipfile.add(file.sub(relative_archive_path, ''), file)
121
+ end
122
+ end
123
+ zipfile_name
124
+ end
125
+
126
+ def upload(key, file)
127
+ options = {
128
+ :body => Pathname.new(file).open
129
+ }
130
+ bucket = s3.bucket(bucket_name)
131
+ obj = bucket_path ? bucket.object("#{bucket_path}#{key}") : bucket.object(key)
132
+ obj.put(options)
133
+ obj
134
+ end
135
+
136
+ def create_app_version(s3_object)
137
+ # Elastic Beanstalk doesn't support descriptions longer than 200 characters
138
+ description = version_description[0, 200]
139
+ options = {
140
+ :application_name => app_name,
141
+ :version_label => version_label,
142
+ :description => description,
143
+ :source_bundle => {
144
+ :s3_bucket => bucket_name,
145
+ :s3_key => s3_object.key
146
+ },
147
+ :auto_create_application => false
148
+ }
149
+ eb.create_application_version(options)
150
+ end
151
+
152
+ # Wait until EB environment update finishes
153
+ def wait_until_deployed
154
+ errorEvents = 0 # errors counter, should remain 0 for successful deployment
155
+ events = []
156
+
157
+ loop do
158
+ environment = eb.describe_environments({
159
+ :application_name => app_name,
160
+ :environment_names => [env_name]
161
+ })[:environments].first
162
+
163
+ eb.describe_events({
164
+ :environment_name => env_name,
165
+ :start_time => @start_time.utc.iso8601,
166
+ })[:events].reverse.each do |event|
167
+ message = "#{event[:event_date]} [#{event[:severity]}] #{event[:message]}"
168
+ unless events.include?(message)
169
+ events.push(message)
170
+ if event[:severity] == "ERROR"
171
+ errorEvents += 1
172
+ warn(message)
173
+ else
174
+ log(message)
175
+ end
176
+ end
177
+ end
178
+
179
+ break if environment[:status] == "Ready"
180
+ sleep 5
181
+ end
182
+
183
+ if errorEvents > 0 then error("Deployment failed.") end
184
+ end
185
+
186
+ def update_app(version)
187
+ options = {
188
+ :environment_name => env_name,
189
+ :version_label => version[:application_version][:version_label]
190
+ }
191
+ eb.update_environment(options)
192
+ end
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,90 @@
1
+ require 'time'
2
+
3
+ module DPL
4
+ class Provider
5
+ class EngineYard < Provider
6
+ requires 'engineyard-cloud-client'
7
+
8
+ def token
9
+ options[:api_key] ||= if options[:email] and options[:password]
10
+ EY::CloudClient.authenticate(options[:email], options[:password])
11
+ else
12
+ option(:api_key) # will raise
13
+ end
14
+ end
15
+
16
+ def api
17
+ @api ||= EY::CloudClient.new(:token => token)
18
+ end
19
+
20
+ def check_auth
21
+ log "authenticated as %s" % api.current_user.email
22
+ end
23
+
24
+ def check_app
25
+ remotes = `git remote -v`.scan(/\t[^\s]+\s/).map { |c| c.strip }.uniq
26
+ @current_sha = `git rev-parse HEAD`.chomp
27
+ resolver = api.resolve_app_environments(
28
+ :app_name => options[:app],
29
+ :account_name => options[:account],
30
+ :environment_name => options[:environment],
31
+ :remotes => remotes)
32
+ resolver.one_match { @app_env = resolver.matches.first }
33
+ resolver.no_matches { error resolver.errors.join("\n").inspect }
34
+ resolver.many_matches do |matches|
35
+ message = "Multiple matches possible, please be more specific:\n\n"
36
+ matches.each do |appenv|
37
+ message << "environment: '#{appenv.environment.name}' account: '#{appenv.environment.account.name}'\n"
38
+ end
39
+ error message
40
+ end
41
+ @app_env
42
+ end
43
+
44
+ def needs_key?
45
+ false
46
+ end
47
+
48
+ def cleanup
49
+ end
50
+
51
+ def uncleanup
52
+ end
53
+
54
+ def push_app
55
+ deploy_opts = {:ref => @current_sha}
56
+ if command = options[:migrate]
57
+ if command === true || command === "true"
58
+ error("\"true\" doesn't look like a migration command, try --migrate=\"rake db:migrate\"")
59
+ end
60
+ deploy_opts[:migrate] = true
61
+ deploy_opts[:migration_command] = command
62
+ end
63
+ print "deploying "
64
+ deployment = EY::CloudClient::Deployment.deploy(api, @app_env, deploy_opts)
65
+ result = poll_for_result(deployment)
66
+ unless result.successful
67
+ error "Deployment failed (see logs on Engine Yard)"
68
+ end
69
+ end
70
+
71
+ def poll_for_result(deployment)
72
+ until deployment.finished?
73
+ sleep 5
74
+ #TODO: configurable timeout?
75
+ print "."
76
+ deployment = EY::CloudClient::Deployment.get(api, deployment.app_environment, deployment.id)
77
+ end
78
+ puts "DONE: https://cloud.engineyard.com/apps/#{deployment.app.id}/environments/#{deployment.environment.id}/deployments/#{deployment.id}/pretty"
79
+ deployment
80
+ end
81
+
82
+ def deploy
83
+ super
84
+ rescue EY::CloudClient::Error => e
85
+ error(e.message)
86
+ end
87
+
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,27 @@
1
+ module DPL
2
+ class Provider
3
+ class Firebase < Provider
4
+ npm_g 'firebase-tools@^3.0', 'firebase'
5
+
6
+ def check_auth
7
+ raise Error, "must supply token option or FIREBASE_TOKEN environment variable" if !options[:token] && !context.env['FIREBASE_TOKEN']
8
+ end
9
+
10
+ def check_app
11
+ error "missing firebase.json" unless File.exist? "firebase.json"
12
+ end
13
+
14
+ def needs_key?
15
+ false
16
+ end
17
+
18
+ def push_app
19
+ command = "firebase deploy --non-interactive"
20
+ command << " --project #{options[:project]}" if options[:project]
21
+ command << " --message '#{options[:message]}'" if options[:message]
22
+ command << " --token '#{options[:token]}'" if options[:token]
23
+ context.shell command
24
+ end
25
+ end
26
+ end
27
+ end