dpl-connect 1.8.43

Sign up to get free protection for your applications and to get access to all the features.
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,48 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+
4
+ module DPL
5
+ class Provider
6
+ class Launchpad < Provider
7
+
8
+ def initialize(context, options)
9
+ super
10
+ @http = Net::HTTP.new('api.launchpad.net', 443)
11
+ @http.use_ssl = true
12
+ end
13
+
14
+ def check_auth
15
+ end
16
+
17
+ def needs_key?
18
+ false
19
+ end
20
+
21
+ def push_app
22
+ response = api_call('/1.0/' + options[:slug] + '/+code-import', {'ws.op' => 'requestImport'})
23
+ error('Deploy failed! Launchpad credentials invalid. ' + response.code.to_s) if response.code == '401'
24
+ error('Error: ' + response.code.to_s + ' ' + response.body) unless response.kind_of? Net::HTTPSuccess
25
+ end
26
+
27
+ private
28
+
29
+ def api_call(path, data)
30
+ req = Net::HTTP::Post.new(path)
31
+ req.set_form_data(data)
32
+ req['Authorization'] = authorization
33
+ return @http.request(req)
34
+ end
35
+
36
+ def authorization
37
+ return 'OAuth oauth_consumer_key="Travis%20Deploy", ' +
38
+ 'oauth_nonce="' + rand(36**32).to_s(36) + '",' +
39
+ 'oauth_signature="%26' + options[:oauth_token_secret] + '",' +
40
+ 'oauth_signature_method="PLAINTEXT",' +
41
+ 'oauth_timestamp="' + Time::now().to_i.to_s + '",' +
42
+ 'oauth_token="' + options[:oauth_token] + '",' +
43
+ 'oauth_version="1.0"'
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,23 @@
1
+ module DPL
2
+ class Provider
3
+ class Modulus < Provider
4
+ npm_g 'modulus'
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
+ raise Error, "must supply a project name" unless option(:project_name)
12
+ end
13
+
14
+ def needs_key?
15
+ false
16
+ end
17
+
18
+ def push_app
19
+ context.shell "env MODULUS_TOKEN=#{option(:api_key)} modulus deploy -p #{option(:project_name)}"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,64 @@
1
+ require 'json'
2
+ require 'uri'
3
+
4
+ module DPL
5
+ class Provider
6
+ class NPM < Provider
7
+ NPMRC_FILE = '~/.npmrc'
8
+ DEFAULT_NPM_REGISTRY = 'registry.npmjs.org'
9
+
10
+ def needs_key?
11
+ false
12
+ end
13
+
14
+ def check_app
15
+ end
16
+
17
+ def setup_auth
18
+ file = File.open(File.expand_path(NPMRC_FILE), 'w')
19
+ file.puts(npmrc_file_content)
20
+ file.flush
21
+ end
22
+
23
+ def check_auth
24
+ setup_auth
25
+ log "Authenticated with email #{option(:email)}"
26
+ end
27
+
28
+ def push_app
29
+ log "NPM API key format changed recently. If your deployment fails, check your API key in ~/.npmrc."
30
+ log "http://docs.travis-ci.com/user/deployment/npm/"
31
+ log "#{NPMRC_FILE} size: #{File.size(File.expand_path(NPMRC_FILE))}"
32
+
33
+ command = "env NPM_API_KEY=#{option(:api_key)} npm publish"
34
+ command << " --tag #{option(:tag)}" if options[:tag]
35
+ context.shell "#{command}"
36
+ FileUtils.rm(File.expand_path(NPMRC_FILE))
37
+ end
38
+
39
+ def package_registry
40
+ if File.exists?('package.json')
41
+ data = JSON.parse(File.read('package.json'))
42
+ if data['publishConfig'] && data['publishConfig']['registry']
43
+ return URI(data['publishConfig']['registry']).host
44
+ end
45
+ end
46
+
47
+ DEFAULT_NPM_REGISTRY
48
+ end
49
+
50
+ def npmrc_file_content
51
+ log "NPM version: #{npm_version}"
52
+ if npm_version =~ /^1/
53
+ "_auth = ${NPM_API_KEY}\nemail = #{option(:email)}"
54
+ else
55
+ "//#{package_registry}/:_authToken=${NPM_API_KEY}"
56
+ end
57
+ end
58
+
59
+ def npm_version
60
+ `npm --version`
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,59 @@
1
+ module DPL
2
+ class Provider
3
+ class Openshift < Provider
4
+ requires 'httpclient', version: '~> 2.4.0'
5
+ requires 'net-ssh', load: 'net/ssh', version: '~> 2.9.2' # Anything higher requires Ruby 2.x
6
+ requires 'net-ssh-gateway', load: 'net/ssh/gateway', version: '~> 1.3.0' # 2.0.0 requires net-ssh 4.0.0
7
+ requires 'rhc'
8
+
9
+ def initialize(context, options)
10
+ super
11
+ @deployment_branch = options[:deployment_branch]
12
+ end
13
+
14
+ def api
15
+ @api ||= ::RHC::Rest::Client.new(:user => option(:user), :password => option(:password), :server => 'openshift.redhat.com')
16
+ end
17
+
18
+ def user
19
+ @user ||= api.user.login
20
+ end
21
+
22
+ def app
23
+ @app ||= api.find_application(option(:domain), option(:app))
24
+ end
25
+
26
+ def check_auth
27
+ log "authenticated as %s" % user
28
+ end
29
+
30
+ def check_app
31
+ log "found app #{app.name}"
32
+ end
33
+
34
+ def setup_key(file, type = nil)
35
+ specified_type, content, comment = File.read(file).split
36
+ api.add_key(option(:key_name), content, type || specified_type)
37
+ end
38
+
39
+ def remove_key
40
+ api.delete_key(option(:key_name))
41
+ end
42
+
43
+ def push_app
44
+ if @deployment_branch
45
+ log "deployment_branch detected: #{@deployment_branch}"
46
+ app.deployment_branch = @deployment_branch
47
+ context.shell "git push #{app.git_url} -f #{app.deployment_branch}"
48
+ else
49
+ context.shell "git push #{app.git_url} -f"
50
+ end
51
+ end
52
+
53
+ def restart
54
+ app.restart
55
+ end
56
+
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,132 @@
1
+ require 'timeout'
2
+
3
+ module DPL
4
+ class Provider
5
+ class OpsWorks < Provider
6
+ requires 'aws-sdk', version: '~> 2.0'
7
+ experimental 'AWS OpsWorks'
8
+
9
+ def opsworks
10
+ @opsworks ||= Aws::OpsWorks::Client.new(opsworks_options)
11
+ end
12
+
13
+ def opsworks_options
14
+ {
15
+ region: region || 'us-east-1',
16
+ credentials: ::Aws::Credentials.new(access_key_id, secret_access_key)
17
+ }
18
+ end
19
+
20
+ def needs_key?
21
+ false
22
+ end
23
+
24
+ def check_app
25
+
26
+ end
27
+
28
+ def region
29
+ options[:region] || context.env['AWS_DEFAULT_REGION']
30
+ end
31
+
32
+ def access_key_id
33
+ options[:access_key_id] || context.env['AWS_ACCESS_KEY_ID'] || raise(Error, "missing access_key_id")
34
+ end
35
+
36
+ def secret_access_key
37
+ options[:secret_access_key] || context.env['AWS_SECRET_ACCESS_KEY'] || raise(Error, "missing secret_access_key")
38
+ end
39
+
40
+ def check_auth
41
+ log "Logging in with Access Key: #{access_key_id[-4..-1].rjust(20, '*')}"
42
+ end
43
+
44
+ def custom_json
45
+ options[:custom_json] || {
46
+ deploy: {
47
+ ops_works_app[:shortname] => {
48
+ migrate: !!options[:migrate],
49
+ scm: {
50
+ revision: current_sha
51
+ }
52
+ }
53
+ }
54
+ }
55
+ end
56
+
57
+ def current_sha
58
+ @current_sha ||= `git rev-parse HEAD`.chomp
59
+ end
60
+
61
+ def ops_works_app
62
+ @ops_works_app ||= fetch_ops_works_app
63
+ end
64
+
65
+ def fetch_ops_works_app
66
+ data = opsworks.describe_apps(app_ids: [option(:app_id)])
67
+ unless data[:apps] && data[:apps].count == 1
68
+ raise Error, "App #{option(:app_id)} not found.", error.backtrace
69
+ end
70
+ data[:apps].first
71
+ end
72
+
73
+ def push_app
74
+ Timeout::timeout(600) do
75
+ create_deployment
76
+ end
77
+ rescue Timeout::Error
78
+ error 'Timeout: Could not finish deployment in 10 minutes.'
79
+ end
80
+
81
+ def create_deployment
82
+ deployment_config = {
83
+ stack_id: ops_works_app[:stack_id],
84
+ app_id: option(:app_id),
85
+ command: {name: 'deploy'},
86
+ comment: travis_deploy_comment,
87
+ custom_json: custom_json.to_json
88
+ }
89
+ if !options[:instance_ids].nil?
90
+ deployment_config[:instance_ids] = Array(option(:instance_ids))
91
+ end
92
+ if !options[:layer_ids].nil?
93
+ deployment_config[:layer_ids] = Array(option(:layer_ids))
94
+ end
95
+ log "creating deployment #{deployment_config.to_json}"
96
+ data = opsworks.create_deployment(deployment_config)
97
+ log "Deployment created: #{data[:deployment_id]}"
98
+ return unless options[:wait_until_deployed]
99
+ print "Deploying "
100
+ deployment = wait_until_deployed(data[:deployment_id])
101
+ print "\n"
102
+ if deployment[:status] == 'successful'
103
+ log "Deployment successful."
104
+ else
105
+ error "Deployment failed."
106
+ end
107
+ end
108
+
109
+ def wait_until_deployed(deployment_id)
110
+ deployment = nil
111
+ loop do
112
+ result = opsworks.describe_deployments(deployment_ids: [deployment_id])
113
+ deployment = result[:deployments].first
114
+ break unless deployment[:status] == "running"
115
+ print "."
116
+ sleep 5
117
+ end
118
+ deployment
119
+ end
120
+
121
+ def travis_deploy_comment
122
+ "Deploy build #{context.env['TRAVIS_BUILD_NUMBER'] || current_sha} via Travis CI"
123
+ end
124
+
125
+ def deploy
126
+ super
127
+ rescue Aws::Errors::ServiceError => error
128
+ raise Error, "Stopping Deploy, OpsWorks service error: #{error.message}", error.backtrace
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,144 @@
1
+ module DPL
2
+ class Provider
3
+ class Packagecloud < Provider
4
+ requires 'json_pure', :version => '< 2.0', :load => 'json/pure'
5
+ requires 'packagecloud-ruby', :version => "1.0.5", :load => 'packagecloud'
6
+
7
+ def check_auth
8
+ setup_auth
9
+ begin
10
+ @client = ::Packagecloud::Client.new(@creds, "travis-ci")
11
+ rescue ::Packagecloud::UnauthenticatedException
12
+ error "Could not authenticate to https://packagecloud.io, please check credentials"
13
+ end
14
+ end
15
+
16
+ def needs_key?
17
+ false
18
+ end
19
+
20
+ def setup_auth
21
+ @username = option(:username)
22
+ @token = option(:token)
23
+ @repo = option(:repository)
24
+ @dist = option(:dist) if options[:dist]
25
+ @creds = ::Packagecloud::Credentials.new(@username, @token)
26
+ log "Logging into https://packagecloud.io with #{@username}:#{@token[-4..-1].rjust(20, '*')}"
27
+ end
28
+
29
+ def get_distro(query)
30
+ distro = nil
31
+ begin
32
+ distro = @client.find_distribution_id(query)
33
+ rescue ArgumentError => exception
34
+ error "Error: #{exception.message}"
35
+ end
36
+ if distro.nil?
37
+ error "Could not find distribution named #{query}"
38
+ end
39
+ distro
40
+ end
41
+
42
+ def is_supported_package?(filename)
43
+ ext = File.extname(filename).gsub!('.','')
44
+ ::Packagecloud::SUPPORTED_EXTENSIONS.include?(ext)
45
+ end
46
+
47
+ def dist_required?(filename)
48
+ ext = File.extname(filename).gsub!('.','')
49
+ if ext.nil?
50
+ error "filename: #{filename} has no extension!"
51
+ end
52
+ ["rpm", "deb", "dsc", "whl", "egg", "egg-info", "gz", "zip", "tar", "bz2", "z"].include?(ext.downcase)
53
+ end
54
+
55
+ def error_if_dist_required(filename)
56
+ if dist_required?(filename) && @dist.nil?
57
+ error "Distribution needed for rpm, deb, python, and dsc packages, example --dist='ubuntu/breezy'"
58
+ end
59
+ end
60
+
61
+ def is_source_package?(filename)
62
+ ext = File.extname(filename).gsub!('.','')
63
+ ext == 'dsc'
64
+ end
65
+
66
+ def get_source_files_for(orig_filename)
67
+ source_files = {}
68
+ glob_args = ["**/*"]
69
+ package = ::Packagecloud::Package.new(:file => orig_filename)
70
+ result = @client.package_contents(@repo, package, get_distro(@dist))
71
+ if result.succeeded
72
+ package_contents_files = result.response["files"].map { |x| x["filename"] }
73
+ Dir.chdir(options.fetch(:local_dir, Dir.pwd)) do
74
+ Dir.glob(*glob_args) do |filename|
75
+ unless File.directory?(filename)
76
+ basename = File.basename(filename)
77
+ if package_contents_files.include?(basename)
78
+ log "Found source fragment: #{basename} for #{orig_filename}"
79
+ source_files = source_files.merge({basename => open(filename)})
80
+ end
81
+ end
82
+ end
83
+ end
84
+ else
85
+ error "Error: #{result.response}"
86
+ end
87
+ source_files
88
+ end
89
+
90
+ def push_app
91
+ forced = options.fetch(:force, nil)
92
+ packages = []
93
+ glob_args = Array(options.fetch(:package_glob, '**/*'))
94
+ Dir.chdir(options.fetch(:local_dir, Dir.pwd)) do
95
+ Dir.glob(*glob_args) do |filename|
96
+ unless File.directory?(filename)
97
+ if is_supported_package?(filename)
98
+ log "Detected supported package: #{filename}"
99
+ error_if_dist_required(filename)
100
+ if is_source_package?(filename)
101
+ log "Processing source package: #{filename}"
102
+ source_files = get_source_files_for(filename)
103
+ packages << ::Packagecloud::Package.new(:file => filename, :source_files => source_files)
104
+ else
105
+ packages << ::Packagecloud::Package.new(:file => filename)
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ packages.each do |package|
113
+ if forced
114
+ log "Deleting package: #{package.filename}"
115
+ distro, distro_release = @dist.split("/")
116
+ result = @client.delete_package(@repo, distro, distro_release, package.filename)
117
+ if result.succeeded
118
+ log "Successfully deleted #{package.filename} on #{@dist}"
119
+ else
120
+ error "Error #{result.response}"
121
+ end
122
+ end
123
+ log "Pushing package: #{package.filename}"
124
+ if dist_required?(package.filename)
125
+ result = @client.put_package(@repo, package, get_distro(@dist))
126
+ else
127
+ result = @client.put_package(@repo, package)
128
+ end
129
+
130
+ if result.succeeded
131
+ log "Successfully pushed #{package.filename} to #{@username}/#{@repo}"
132
+ else
133
+ error "Error #{result.response}"
134
+ end
135
+ end
136
+ if packages.empty?
137
+ error "Error: No supported packages found! Perhaps try skip_cleanup: true"
138
+ end
139
+ end
140
+
141
+ end
142
+
143
+ end
144
+ end