dpl 1.10.17.travis.6637.6 → 2.0.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (140) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +74 -0
  3. data/CONTRIBUTING.md +392 -0
  4. data/Gemfile +17 -3
  5. data/Gemfile.lock +373 -0
  6. data/LICENSE +16 -19
  7. data/NOTES.md +275 -0
  8. data/README.md +1977 -707
  9. data/Rakefile +2 -2
  10. data/bin/dpl +7 -3
  11. data/lib/dpl.rb +20 -0
  12. data/lib/dpl/assets/atlas/install +19 -0
  13. data/lib/dpl/assets/dpl/README.erb.md +133 -0
  14. data/lib/dpl/assets/dpl/git_ssh +2 -0
  15. data/lib/dpl/assets/git/detect_private_key +8 -0
  16. data/lib/dpl/assets/hephy/filter_log +3 -0
  17. data/lib/dpl/assets/pypi/install +4 -0
  18. data/lib/dpl/assets/scalingo/install +6 -0
  19. data/lib/dpl/cli.rb +36 -48
  20. data/lib/dpl/ctx.rb +2 -0
  21. data/lib/dpl/ctx/bash.rb +543 -0
  22. data/lib/dpl/ctx/test.rb +242 -0
  23. data/lib/dpl/helper/assets.rb +36 -0
  24. data/lib/dpl/helper/cmd.rb +167 -0
  25. data/lib/dpl/helper/config_file.rb +47 -0
  26. data/lib/dpl/helper/env.rb +39 -0
  27. data/lib/dpl/helper/interpolate.rb +126 -0
  28. data/lib/dpl/helper/memoize.rb +20 -0
  29. data/lib/dpl/helper/squiggle.rb +22 -0
  30. data/lib/dpl/helper/zip.rb +69 -0
  31. data/lib/dpl/provider.rb +562 -234
  32. data/lib/dpl/provider/dsl.rb +369 -0
  33. data/lib/dpl/provider/examples.rb +128 -0
  34. data/lib/dpl/provider/status.rb +59 -0
  35. data/lib/dpl/providers.rb +40 -0
  36. data/lib/dpl/providers/anynines.rb +65 -0
  37. data/lib/dpl/providers/atlas.rb +49 -0
  38. data/lib/dpl/providers/azure_web_apps.rb +59 -0
  39. data/lib/dpl/providers/bintray.rb +313 -0
  40. data/lib/dpl/providers/bluemixcloudfoundry.rb +92 -0
  41. data/lib/dpl/providers/boxfuse.rb +48 -0
  42. data/lib/dpl/providers/cargo.rb +19 -0
  43. data/lib/dpl/providers/chef_supermarket.rb +128 -0
  44. data/lib/dpl/providers/cloud66.rb +40 -0
  45. data/lib/dpl/providers/cloudfiles.rb +56 -0
  46. data/lib/dpl/providers/cloudfoundry.rb +81 -0
  47. data/lib/dpl/providers/codedeploy.rb +179 -0
  48. data/lib/dpl/providers/datica.rb +60 -0
  49. data/lib/dpl/providers/elasticbeanstalk.rb +195 -0
  50. data/lib/dpl/providers/engineyard.rb +107 -0
  51. data/lib/dpl/providers/firebase.rb +41 -0
  52. data/lib/dpl/providers/gae.rb +74 -0
  53. data/lib/dpl/providers/gcs.rb +105 -0
  54. data/lib/dpl/providers/hackage.rb +47 -0
  55. data/lib/dpl/providers/hephy.rb +101 -0
  56. data/lib/dpl/providers/heroku.rb +111 -0
  57. data/lib/dpl/providers/heroku/api.rb +119 -0
  58. data/lib/dpl/providers/heroku/git.rb +50 -0
  59. data/lib/dpl/providers/lambda.rb +202 -0
  60. data/lib/dpl/providers/launchpad.rb +74 -0
  61. data/lib/dpl/providers/netlify.rb +30 -0
  62. data/lib/dpl/providers/npm.rb +88 -0
  63. data/lib/dpl/providers/openshift.rb +46 -0
  64. data/lib/dpl/providers/opsworks.rb +142 -0
  65. data/lib/dpl/providers/packagecloud.rb +190 -0
  66. data/lib/dpl/providers/pages.rb +17 -0
  67. data/lib/dpl/providers/pages/api.rb +102 -0
  68. data/lib/dpl/providers/pages/git.rb +251 -0
  69. data/lib/dpl/providers/puppetforge.rb +44 -0
  70. data/lib/dpl/providers/pypi.rb +120 -0
  71. data/lib/dpl/providers/releases.rb +214 -0
  72. data/lib/dpl/providers/rubygems.rb +89 -0
  73. data/lib/dpl/providers/s3.rb +243 -0
  74. data/lib/dpl/providers/scalingo.rb +63 -0
  75. data/lib/dpl/providers/script.rb +28 -0
  76. data/lib/dpl/providers/snap.rb +59 -0
  77. data/lib/dpl/providers/surge.rb +55 -0
  78. data/lib/dpl/providers/testfairy.rb +93 -0
  79. data/lib/dpl/providers/transifex.rb +66 -0
  80. data/lib/dpl/support/aws_sdk_patch.rb +23 -0
  81. data/lib/dpl/support/gems.rb +69 -0
  82. data/lib/dpl/support/gstore_patch.rb +6 -0
  83. data/lib/dpl/support/version.rb +83 -0
  84. data/lib/dpl/version.rb +2 -2
  85. metadata +98 -169
  86. data/.coveralls.yml +0 -1
  87. data/.github/CONTRIBUTING.md +0 -173
  88. data/.github/stale.yml +0 -53
  89. data/.gitignore +0 -13
  90. data/.rspec +0 -2
  91. data/.travis.yml +0 -56
  92. data/dpl-anynines.gemspec +0 -3
  93. data/dpl-atlas.gemspec +0 -3
  94. data/dpl-azure_webapps.gemspec +0 -3
  95. data/dpl-bintray.gemspec +0 -3
  96. data/dpl-bitballoon.gemspec +0 -3
  97. data/dpl-bluemix_cloud_foundry.gemspec +0 -3
  98. data/dpl-boxfuse.gemspec +0 -3
  99. data/dpl-cargo.gemspec +0 -3
  100. data/dpl-catalyze.gemspec +0 -3
  101. data/dpl-chef_supermarket.gemspec +0 -20
  102. data/dpl-cloud66.gemspec +0 -3
  103. data/dpl-cloud_files.gemspec +0 -3
  104. data/dpl-cloud_foundry.gemspec +0 -3
  105. data/dpl-code_deploy.gemspec +0 -3
  106. data/dpl-deis.gemspec +0 -3
  107. data/dpl-elastic_beanstalk.gemspec +0 -3
  108. data/dpl-engine_yard.gemspec +0 -3
  109. data/dpl-firebase.gemspec +0 -3
  110. data/dpl-gae.gemspec +0 -3
  111. data/dpl-gcs.gemspec +0 -3
  112. data/dpl-hackage.gemspec +0 -3
  113. data/dpl-hephy.gemspec +0 -3
  114. data/dpl-heroku.gemspec +0 -3
  115. data/dpl-lambda.gemspec +0 -3
  116. data/dpl-launchpad.gemspec +0 -3
  117. data/dpl-npm.gemspec +0 -3
  118. data/dpl-openshift.gemspec +0 -3
  119. data/dpl-ops_works.gemspec +0 -3
  120. data/dpl-packagecloud.gemspec +0 -3
  121. data/dpl-pages.gemspec +0 -3
  122. data/dpl-puppet_forge.gemspec +0 -3
  123. data/dpl-pypi.gemspec +0 -3
  124. data/dpl-releases.gemspec +0 -8
  125. data/dpl-rubygems.gemspec +0 -3
  126. data/dpl-s3.gemspec +0 -3
  127. data/dpl-scalingo.gemspec +0 -3
  128. data/dpl-script.gemspec +0 -3
  129. data/dpl-snap.gemspec +0 -3
  130. data/dpl-surge.gemspec +0 -3
  131. data/dpl-testfairy.gemspec +0 -3
  132. data/dpl-transifex.gemspec +0 -3
  133. data/dpl.gemspec +0 -3
  134. data/gemspec_helper.rb +0 -51
  135. data/lib/dpl/error.rb +0 -3
  136. data/notes/engine_yard.md +0 -1
  137. data/notes/heroku.md +0 -3
  138. data/spec/cli_spec.rb +0 -36
  139. data/spec/provider_spec.rb +0 -191
  140. data/spec/spec_helper.rb +0 -20
@@ -0,0 +1,242 @@
1
+ require 'cl'
2
+ require 'stringio'
3
+ require 'dpl/helper/squiggle'
4
+
5
+ module Dpl
6
+ module Ctx
7
+ class Test < Cl::Ctx
8
+ include Squiggle
9
+
10
+ attr_reader :cmds, :stdout, :stderr, :last_out, :last_err
11
+
12
+ def initialize
13
+ @cmds = []
14
+ @stderr = StringIO.new
15
+ @stdout = {}
16
+ super('dpl')
17
+ end
18
+
19
+ def fold(name)
20
+ cmds << "[fold] #{name}"
21
+ yield.tap { cmds << "[unfold] #{name}" }
22
+ end
23
+
24
+ def validate_runtimes(runtimes)
25
+ runtimes.each do |name, requirements|
26
+ cmds << "[validate:runtime] #{name} (#{requirements.join(', ')})"
27
+ end
28
+ end
29
+
30
+ def apts_get(apts)
31
+ apts.each { |apt| apt_get(*apt) }
32
+ end
33
+
34
+ def apt_get(name, cmd = name)
35
+ cmds << "[apt:get] #{name} (#{cmd})"
36
+ end
37
+
38
+ def gems_require(gems)
39
+ gems.each { |gem| gem_require(gem) }
40
+ end
41
+
42
+ def gem_require(name, version = nil, opts = {})
43
+ cmds << "[gem:require] #{name} (#{version}, #{opts})"
44
+ end
45
+
46
+ def npm_install(name, cmd = name)
47
+ cmds << "[npm:install] #{name} (#{cmd})"
48
+ end
49
+
50
+ def pip_install(name, cmd = name, version = nil)
51
+ cmds << "[pip:install] #{name} (#{cmd}, #{version})"
52
+ end
53
+
54
+ def ssh_keygen(name, file)
55
+ File.open(file, 'w+') { |f| f.write('private-key') }
56
+ File.open("#{file}.pub", 'w+') { |f| f.write('ssh-rsa public-key') }
57
+ end
58
+
59
+ def shell(cmd, opts = {})
60
+ info cmd.msg if cmd.msg?
61
+ info cmd.echo if cmd.echo?
62
+ cmds << cmd.cmd
63
+ return true unless cmd.capture?
64
+ stdout[cmd.key] || 'captured_stdout'
65
+ end
66
+
67
+ def success?
68
+ true
69
+ end
70
+
71
+ def info(msg)
72
+ cmds << "[info] #{msg}"
73
+ end
74
+
75
+ def print(chars)
76
+ cmds << "[print] #{chars}"
77
+ end
78
+
79
+ def warn(msg)
80
+ cmds << "[warn] #{msg}"
81
+ end
82
+
83
+ def error(message)
84
+ raise Error, message
85
+ end
86
+
87
+ def deprecate_opt(key, msg)
88
+ msg = "please use #{msg}" if msg.is_a?(Symbol)
89
+ warn("deprecated option #{key} (#{msg})")
90
+ end
91
+
92
+ def repo_name
93
+ 'dpl'
94
+ end
95
+
96
+ def repo_slug
97
+ 'travis-ci/dpl'
98
+ end
99
+
100
+ def build_dir
101
+ '.'
102
+ end
103
+
104
+ def build_number
105
+ 1
106
+ end
107
+
108
+ def git_commit_msg
109
+ 'commit msg'
110
+ end
111
+
112
+ def git_author_name
113
+ 'author name'
114
+ end
115
+
116
+ def git_author_email
117
+ 'author email'
118
+ end
119
+
120
+ def git_dirty?
121
+ true
122
+ end
123
+
124
+ def git_log(args)
125
+ 'commits'
126
+ end
127
+
128
+ def git_ls_files
129
+ %w(one two)
130
+ end
131
+
132
+ def git_ls_remote?(url, ref)
133
+ true
134
+ end
135
+
136
+ def git_remote_urls
137
+ ['git://origin.git']
138
+ end
139
+
140
+ def git_rev_parse(ref)
141
+ "ref: #{ref}"
142
+ end
143
+
144
+ def git_tag
145
+ 'tag'
146
+ end
147
+
148
+ def git_sha
149
+ 'sha'
150
+ end
151
+
152
+ def machine_name
153
+ 'machine_name'
154
+ end
155
+
156
+ def node_version
157
+ '11.0.0'
158
+ end
159
+
160
+ def npm_version
161
+ '1'
162
+ end
163
+
164
+ def which(cmd)
165
+ false
166
+ end
167
+
168
+ def tmp_dir
169
+ FileUtils.mkdir_p('tmp')
170
+ 'tmp'
171
+ end
172
+
173
+ def sleep(*)
174
+ end
175
+
176
+ def encoding(path)
177
+ 'text'
178
+ end
179
+
180
+ def logger(level = :info)
181
+ logger = Logger.new(stderr)
182
+ logger.level = Logger.const_get(level.to_s.upcase)
183
+ logger
184
+ end
185
+
186
+ def test?
187
+ true
188
+ end
189
+
190
+ def file_size(path)
191
+ File.size(path.sub("#{File.expand_path('~')}", './home'))
192
+ end
193
+
194
+ def move_files(paths)
195
+ paths.each do |path|
196
+ mv(path, "/tmp/#{File.basename(path)}")
197
+ end
198
+ end
199
+
200
+ def unmove_files(paths)
201
+ paths.each do |path|
202
+ mv("/tmp/#{File.basename(path)}", path)
203
+ end
204
+ end
205
+
206
+ def mv(src, dest)
207
+ cmds << [:mv, src, dest].join(' ')
208
+ end
209
+
210
+ def rm_rf(path)
211
+ cmds << [:rm_rf, path].join(' ')
212
+ end
213
+
214
+ def chmod(perm, path)
215
+ cmds << [:chmod, perm, path].join(' ')
216
+ end
217
+
218
+ def write_file(path, content, chmod = nil)
219
+ path = File.expand_path(path)
220
+ path = path.sub("#{File.expand_path('~')}", './home')
221
+ FileUtils.mkdir_p(File.dirname(path))
222
+ File.open(path, 'w+') { |f| f.write(content) }
223
+ end
224
+
225
+ def write_netrc(machine, login, password)
226
+ write_file('~/.netrc', sq(<<-rc))
227
+ machine #{machine}
228
+ login #{login}
229
+ password #{password}
230
+ rc
231
+ end
232
+
233
+ def tty?
234
+ false
235
+ end
236
+
237
+ def except(hash, *keys)
238
+ hash.reject { |key, _| keys.include?(key) }
239
+ end
240
+ end
241
+ end
242
+ end
@@ -0,0 +1,36 @@
1
+ require 'fileutils'
2
+
3
+ module Dpl
4
+ module Assets
5
+ class Asset < Struct.new(:provider, :namespace, :name)
6
+ include FileUtils
7
+
8
+ DIR = File.expand_path('../../assets', __FILE__)
9
+
10
+ def copy(target)
11
+ cp path, File.expand_path(target)
12
+ end
13
+
14
+ def read
15
+ exists? ? provider.interpolate(File.read(path)) : unknown
16
+ end
17
+
18
+ def exists?
19
+ File.exists?(path)
20
+ end
21
+
22
+ def unknown
23
+ raise "Could not find asset #{path}"
24
+ end
25
+
26
+ def path
27
+ "#{DIR}/#{namespace}/#{name}"
28
+ end
29
+ end
30
+
31
+ def asset(*args)
32
+ name, namespace = args.reverse
33
+ Asset.new(self, namespace || registry_key, name)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,167 @@
1
+ module Dpl
2
+ # Represents a shell command
3
+ class Cmd < Struct.new(:provider, :key, :opts)
4
+ # Returns the shell command string
5
+ #
6
+ # If a Symbol was passed as a command then the command will be looked
7
+ # up from the provider class' `cmds` declaration.
8
+ #
9
+ # The command will be interpolated, and can include secrets. See
10
+ # `Dpl::Interpolate` for details on interpolating variables.
11
+ #
12
+ # If the option `silence` was passed then stdout and stderr will be
13
+ # redirected to `/dev/null`.
14
+ #
15
+ # If the option `python` was passed then the virtualenv with the given
16
+ # Python version will be activated before executing the command.
17
+ def cmd(secure = true)
18
+ cmd = lookup(:cmd, key) || missing(:cmd, key)
19
+ cmd = interpolate(cmd, opts, secure: secure).strip
20
+ cmd = silence(cmd) if silence?
21
+ cmd = python(cmd) if python?
22
+ cmd
23
+ end
24
+
25
+ # Returns a log message version of the command string
26
+ #
27
+ # This is the same as #cmd, except that included secrets will be
28
+ # obfuscated, and a prompt (dollar and space) will be prepended. See
29
+ # `Dpl::Interpolate` for details on interpolating variables.
30
+ def echo
31
+ "$ #{cmd(false)}"
32
+ end
33
+
34
+ # Returns the log message for announcing a command
35
+ #
36
+ # If the option `msg` was given as a String then it will be used. If the
37
+ # option `msg` was given as a Symbol then it will be looked up from the
38
+ # provider class' `msgs` declaration.
39
+ #
40
+ # The message string will be interpolated, but included secrets will be
41
+ # obfuscated. See `Dpl::Interpolate` for details on interpolating
42
+ # variables.
43
+ def msg
44
+ msg = lookup(:msg, opts[:msg], key.is_a?(Symbol) ? key : nil)
45
+ msg || missing(:msg, opts[:msg], key)
46
+ msg = interpolate(msg, opts, secure: false).strip
47
+ msg
48
+ end
49
+
50
+ def msg?
51
+ !!lookup(:msg, opts[:msg], key.is_a?(Symbol) ? key : nil)
52
+ end
53
+
54
+ # Returns the log message for a failed command
55
+ #
56
+ # The message string will be interpolated, but included secrets will be
57
+ # obfuscated. See `Dpl::Interpolate` for details on interpolating
58
+ # variables.
59
+ #
60
+ # If the option `assert` was given as a String then it will be used. If the
61
+ # option `assert` was given as a Symbol then it will be looked up from the
62
+ # provider class' `errs` declaration. If the command was given as a Symbol,
63
+ # and it can be found in `errs` then this String will be used.
64
+ def error
65
+ keys = [opts[:assert], key]
66
+ err = lookup(:err, *keys)
67
+ err ? interpolate(err, opts).strip : 'Failed'
68
+ end
69
+
70
+ # Whether or not to assert that the command has exited with 0
71
+ #
72
+ # Returns `true` if the option `assert` was given as `true` or not given at
73
+ # all. Returns `false` if the option `assert` was given as `false`.
74
+ def assert?
75
+ !opts[:assert].is_a?(FalseClass)
76
+ end
77
+
78
+ # Whether or not to announce the command with an info level log message
79
+ #
80
+ # Returns `true` if the option `assert` was given as `true` or not given at
81
+ # all. Returns `false` if the option `assert` was given as `false`.
82
+ def echo?
83
+ !opts[:echo].is_a?(FalseClass)
84
+ end
85
+
86
+ # Whether or not to capture the commands stdout and stderr
87
+ #
88
+ # Returns `true` if the option `capture` was given as `true`. Returns
89
+ # `false` if the option `capture` was given as `false` or not given.
90
+ def capture?
91
+ !!opts[:capture]
92
+ end
93
+
94
+ # Whether or not to output a log message before the command is run
95
+ #
96
+ # Returns `true` if the option `info` was given. Returns `false` if the
97
+ # option `info` was given as `false` or not given.
98
+ def info?
99
+ !!opts[:info]
100
+ end
101
+
102
+ # Returns the log message to output after the command has succeeded
103
+ def info
104
+ opts[:info]
105
+ end
106
+
107
+ # Whether or not to output a log message after the command has succeeded
108
+ #
109
+ # Returns `true` if the option `success` was given. Returns `false` if the
110
+ # option `success` was given as `false` or not given.
111
+ def success?
112
+ !!opts[:success]
113
+ end
114
+
115
+ # Returns the log message to output after the command has succeeded
116
+ def success
117
+ opts[:success]
118
+ end
119
+
120
+ # Whether or not to activate a Python virtualenv before executing the
121
+ # command
122
+ #
123
+ # Returns `true` if the option `python` was given. Returns `false` if the
124
+ # option `python` was given as `false` or not given.
125
+ def python?
126
+ !!opts[:python]
127
+ end
128
+
129
+ # Returns how often to retry the command
130
+ def retry
131
+ opts[:retry]
132
+ end
133
+
134
+ # Whether or not to redirect the command's stdout and stderr to `/dev/null`
135
+ #
136
+ # Returns `true` if the option `silence` was given. Returns `false` if the
137
+ # option `silence` was given as `false` or not given.
138
+ def silence?
139
+ !!opts[:silence]
140
+ end
141
+
142
+ private
143
+
144
+ def lookup(type, *keys)
145
+ str = provider.send(type, *keys) if provider
146
+ str || keys.detect { |key| key.is_a?(String) }
147
+ end
148
+
149
+ def missing(type, *keys)
150
+ raise("Could not find #{type}: #{keys.compact.map(&:inspect).join(', ')}")
151
+ end
152
+
153
+ def interpolate(str, args, opts = {})
154
+ provider ? provider.interpolate(str, args, opts) : str
155
+ end
156
+
157
+ def silence(str)
158
+ "#{str} > /dev/null 2>&1"
159
+ end
160
+
161
+ # Activates the Python virtualenv for the given Python version.
162
+ def python(cmd)
163
+ # "bash -c 'source $HOME/virtualenv/python#{opts[:python]}/bin/activate; #{cmd.gsub(/'/, "'\\\\''")}'"
164
+ "source $HOME/virtualenv/python#{opts[:python]}/bin/activate && #{cmd}"
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,47 @@
1
+ module Dpl
2
+ module ConfigFile
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ # should this sit in Cl?
8
+ module ClassMethods
9
+ attr_reader :config_files
10
+
11
+ def config(*paths)
12
+ if paths.any?
13
+ @config_files = paths
14
+ elsif config_files
15
+ paths = config_files.dup
16
+ opts = paths.last.is_a?(Hash) ? paths.pop : {}
17
+ conf = ConfigFiles.new(paths, opts).config
18
+ known = self.opts.map(&:name).map(&:to_sym)
19
+ conf.select { |key, _| known.include?(key) }
20
+ else
21
+ {}
22
+ end
23
+ end
24
+ end
25
+
26
+ class ConfigFiles < Struct.new(:paths, :opts)
27
+ def config
28
+ paths.map { |path| parse(path) }.inject(&:merge) || {}
29
+ end
30
+
31
+ def parse(path)
32
+ str = File.exists?(path) ? File.read(path) : ''
33
+ opts = str.lines.select { |line| line.include?('=') }.map(&:strip)
34
+ opts = opts.map { |pair| pair.split('=', 2) }.to_h
35
+ opts.map { |key, value| [strip_prefix(key).to_sym, value] }.to_h
36
+ end
37
+
38
+ def strip_prefix(str)
39
+ opts[:prefix] ? str.sub(/^#{opts[:prefix]}[\-_]?/, '') : str
40
+ end
41
+ end
42
+
43
+ def opts
44
+ @opts ||= self.class.config.merge(super)
45
+ end
46
+ end
47
+ end