travis_dpl_test 2.0.3.beta.4.ror

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 (100) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +172 -0
  3. data/CODE_OF_CONDUCT.md +74 -0
  4. data/CONTRIBUTING.md +392 -0
  5. data/Gemfile +32 -0
  6. data/Gemfile.lock +611 -0
  7. data/LICENSE +19 -0
  8. data/README.md +2744 -0
  9. data/Rakefile +210 -0
  10. data/bin/dpl +11 -0
  11. data/config/transliterate.yml +733 -0
  12. data/dpl.gemspec +23 -0
  13. data/lib/dpl/assets/atlas/install +19 -0
  14. data/lib/dpl/assets/convox/install +11 -0
  15. data/lib/dpl/assets/dpl/README.erb.md +138 -0
  16. data/lib/dpl/assets/dpl/git_ssh +8 -0
  17. data/lib/dpl/assets/git/detect_private_key +8 -0
  18. data/lib/dpl/assets/hephy/filter_log +3 -0
  19. data/lib/dpl/assets/pypi/install +4 -0
  20. data/lib/dpl/assets/scalingo/install +6 -0
  21. data/lib/dpl/cli.rb +100 -0
  22. data/lib/dpl/ctx/bash.rb +549 -0
  23. data/lib/dpl/ctx/test.rb +255 -0
  24. data/lib/dpl/ctx.rb +4 -0
  25. data/lib/dpl/helper/assets.rb +38 -0
  26. data/lib/dpl/helper/cmd.rb +169 -0
  27. data/lib/dpl/helper/config_file.rb +49 -0
  28. data/lib/dpl/helper/cookbook_site_streaming_uploader.rb +249 -0
  29. data/lib/dpl/helper/env.rb +92 -0
  30. data/lib/dpl/helper/github.rb +22 -0
  31. data/lib/dpl/helper/interpolate.rb +160 -0
  32. data/lib/dpl/helper/memoize.rb +23 -0
  33. data/lib/dpl/helper/squiggle.rb +24 -0
  34. data/lib/dpl/helper/transliterate.rb +13 -0
  35. data/lib/dpl/helper/wrap.rb +11 -0
  36. data/lib/dpl/helper/zip.rb +71 -0
  37. data/lib/dpl/provider/dsl.rb +410 -0
  38. data/lib/dpl/provider/examples.rb +132 -0
  39. data/lib/dpl/provider/status.rb +61 -0
  40. data/lib/dpl/provider.rb +651 -0
  41. data/lib/dpl/providers/anynines.rb +71 -0
  42. data/lib/dpl/providers/azure_web_apps.rb +63 -0
  43. data/lib/dpl/providers/bintray.rb +324 -0
  44. data/lib/dpl/providers/bluemixcloudfoundry.rb +98 -0
  45. data/lib/dpl/providers/boxfuse.rb +52 -0
  46. data/lib/dpl/providers/cargo.rb +32 -0
  47. data/lib/dpl/providers/chef_supermarket.rb +132 -0
  48. data/lib/dpl/providers/cloud66.rb +46 -0
  49. data/lib/dpl/providers/cloudfiles.rb +62 -0
  50. data/lib/dpl/providers/cloudformation.rb +281 -0
  51. data/lib/dpl/providers/cloudfoundry.rb +89 -0
  52. data/lib/dpl/providers/codedeploy.rb +190 -0
  53. data/lib/dpl/providers/convox.rb +130 -0
  54. data/lib/dpl/providers/datica.rb +64 -0
  55. data/lib/dpl/providers/ecr.rb +129 -0
  56. data/lib/dpl/providers/elasticbeanstalk.rb +207 -0
  57. data/lib/dpl/providers/engineyard.rb +113 -0
  58. data/lib/dpl/providers/firebase.rb +45 -0
  59. data/lib/dpl/providers/flynn.rb +35 -0
  60. data/lib/dpl/providers/gae.rb +78 -0
  61. data/lib/dpl/providers/gcs.rb +132 -0
  62. data/lib/dpl/providers/git_push.rb +273 -0
  63. data/lib/dpl/providers/gleis.rb +74 -0
  64. data/lib/dpl/providers/hackage.rb +53 -0
  65. data/lib/dpl/providers/hephy.rb +107 -0
  66. data/lib/dpl/providers/heroku/api.rb +123 -0
  67. data/lib/dpl/providers/heroku/git.rb +54 -0
  68. data/lib/dpl/providers/heroku.rb +111 -0
  69. data/lib/dpl/providers/lambda.rb +211 -0
  70. data/lib/dpl/providers/launchpad.rb +80 -0
  71. data/lib/dpl/providers/netlify.rb +38 -0
  72. data/lib/dpl/providers/npm.rb +130 -0
  73. data/lib/dpl/providers/nuget.rb +41 -0
  74. data/lib/dpl/providers/openshift.rb +52 -0
  75. data/lib/dpl/providers/opsworks.rb +146 -0
  76. data/lib/dpl/providers/packagecloud.rb_ +194 -0
  77. data/lib/dpl/providers/pages/api.rb +106 -0
  78. data/lib/dpl/providers/pages/git.rb +262 -0
  79. data/lib/dpl/providers/pages.rb +18 -0
  80. data/lib/dpl/providers/puppetforge.rb +50 -0
  81. data/lib/dpl/providers/pypi.rb +125 -0
  82. data/lib/dpl/providers/releases.rb +234 -0
  83. data/lib/dpl/providers/rubygems.rb +97 -0
  84. data/lib/dpl/providers/s3.rb +251 -0
  85. data/lib/dpl/providers/scalingo.rb +69 -0
  86. data/lib/dpl/providers/script.rb +32 -0
  87. data/lib/dpl/providers/snap.rb +68 -0
  88. data/lib/dpl/providers/surge.rb +59 -0
  89. data/lib/dpl/providers/testfairy.rb +101 -0
  90. data/lib/dpl/providers/transifex.rb +72 -0
  91. data/lib/dpl/providers.rb +48 -0
  92. data/lib/dpl/string_ext.rb +23 -0
  93. data/lib/dpl/support/aws_sdk_patch.rb +26 -0
  94. data/lib/dpl/support/gems.rb +73 -0
  95. data/lib/dpl/support/gstore_patch.rb +8 -0
  96. data/lib/dpl/support/version.rb +84 -0
  97. data/lib/dpl/version.rb +5 -0
  98. data/lib/dpl.rb +23 -0
  99. data/status.json +237 -0
  100. metadata +161 -0
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dpl
4
+ module Providers
5
+ class ChefSupermarket < Provider
6
+ register :'chef-supermarket'
7
+ register :chef_supermarket
8
+
9
+ status :alpha
10
+
11
+ full_name 'Chef Supermarket'
12
+
13
+ description sq(<<-STR)
14
+ tbd
15
+ STR
16
+
17
+ gem 'chef', '~> 18', require: %w[
18
+ chef/cookbook/cookbook_version_loader
19
+ chef/cookbook_uploader
20
+ ]
21
+
22
+ gem 'json'
23
+ gem 'mime-types', '~> 3.4.1'
24
+ gem 'net-telnet', '~> 0.1.0' if ruby_pre?('2.3')
25
+ gem 'rack'
26
+
27
+ env :chef
28
+
29
+ opt '--user_id ID', 'Chef Supermarket user name', required: true
30
+ opt '--name NAME', 'Cookbook name', note: 'defaults to the name given in metadata.json or metadata.rb', alias: :cookbook_name, deprecated: :cookbook_name
31
+ opt '--category CAT', 'Cookbook category in Supermarket', required: true, see: 'https://docs.getchef.com/knife_cookbook_site.html#id12', alias: :cookbook_category, deprecated: :cookbook_category
32
+ opt '--client_key KEY', 'Client API key file name', default: 'client.pem'
33
+ opt '--dir DIR', 'Directory containing the cookbook', default: '.'
34
+
35
+ URL = 'https://supermarket.chef.io/api/v1/cookbooks'
36
+
37
+ msgs validate: 'Validating cookbook',
38
+ upload: 'Uploading cookbook %{name} to %{url}',
39
+ missing_file: 'Missing file: %s',
40
+ unknown_error: 'Unknown error while sharing cookbook: %s',
41
+ version_exists: 'The same version of this cookbook already exists on the Opscode Cookbook Site.'
42
+
43
+ def setup
44
+ Chef::Config[:client_key] = client_key
45
+ chdir dir
46
+ end
47
+
48
+ def validate
49
+ info :validate
50
+ validate_file client_key
51
+ uploader.validate_cookbooks
52
+ end
53
+
54
+ def deploy
55
+ info :upload
56
+ upload
57
+ end
58
+
59
+ private
60
+
61
+ def upload
62
+ res = Chef::Knife::Core::CookbookSiteStreamingUploader.post(URL, user_id, client_key, params)
63
+ handle_error(res.body) if res.code.to_i != 201
64
+ end
65
+
66
+ def params
67
+ { cookbook: json(category: category), tarball: tarball}
68
+ end
69
+
70
+ def tarball
71
+ shell "tar -czf /tmp/#{name}.tgz -C #{build_dir} ."
72
+ shell "tar -tvf /tmp/#{name}.tgz"
73
+ open "/tmp/#{name}.tgz"
74
+ end
75
+
76
+ def name
77
+ @name ||= name_from_json || name_from_rb || error(:missing_file, 'metadata.json or metadata.rb')
78
+ end
79
+
80
+ def name_from_json
81
+ JSON.parse(read('metadata.json'))['name'] if file?('metadata.json')
82
+ end
83
+
84
+ def name_from_rb
85
+ Chef::Cookbook::Metadata.new.from_file('metadata.rb') if file?('metadata.rb')
86
+ end
87
+
88
+ def cookbook
89
+ @cookbook ||= loader.cookbook_version
90
+ end
91
+
92
+ def loader
93
+ Chef::Cookbook::CookbookVersionLoader.new('.').tap(&:load!)
94
+ end
95
+
96
+ def uploader
97
+ Chef::CookbookUploader.new(cookbook)
98
+ end
99
+
100
+ def build_dir
101
+ @build_dir ||= Chef::Knife::Core::CookbookSiteStreamingUploader.create_build_dir(cookbook)
102
+ end
103
+
104
+ def validate_file(path)
105
+ error :missing_file, path unless file?(path)
106
+ end
107
+
108
+ def url
109
+ URL
110
+ end
111
+
112
+ def handle_error(res)
113
+ res = JSON.parse(res)
114
+ unknown_error(res) unless res['error_messages']
115
+ version_exists if res['error_messages'][0].include?('Version already exists')
116
+ error (res['error_messages'][0]).to_s
117
+ end
118
+
119
+ def unknown_error(msg)
120
+ error :unknown_error, msg
121
+ end
122
+
123
+ def version_exists
124
+ error :version_exists
125
+ end
126
+
127
+ def json(obj)
128
+ JSON.dump(obj)
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dpl
4
+ module Providers
5
+ class Cloud66 < Provider
6
+ register :cloud66
7
+
8
+ status :alpha
9
+
10
+ description sq(<<-STR)
11
+ tbd
12
+ STR
13
+
14
+ env :cloud66
15
+
16
+ opt '--redeployment_hook URL', 'The redeployment hook URL', required: true, secret: true
17
+
18
+ msgs failed: 'Redeployment failed (%s)'
19
+
20
+ def deploy
21
+ response = client.request(request)
22
+ error :failed, response.code if response.code != '200'
23
+ end
24
+
25
+ private
26
+
27
+ def client
28
+ Net::HTTP.new(uri.host, uri.port).tap do |client|
29
+ client.use_ssl = use_ssl?
30
+ end
31
+ end
32
+
33
+ def request
34
+ Net::HTTP::Post.new(uri.path)
35
+ end
36
+
37
+ def uri
38
+ @uri ||= URI.parse(redeployment_hook)
39
+ end
40
+
41
+ def use_ssl?
42
+ uri.scheme.downcase == 'https'
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dpl
4
+ module Providers
5
+ class Cloudfiles < Provider
6
+ register :cloudfiles
7
+
8
+ status :alpha
9
+
10
+ full_name 'Cloud Files'
11
+
12
+ description sq(<<-STR)
13
+ tbd
14
+ STR
15
+
16
+ gem 'nokogiri', '~> 1.15'
17
+ gem 'fog-core', '~> 2.3', require: 'fog/core'
18
+ gem 'fog-rackspace', '~> 0.1.6', git: 'https://github.com/travis-oss/fog-rackspace', require: 'fog/rackspace'
19
+
20
+ env :cloudfiles
21
+
22
+ opt '--username USER', 'Rackspace username', required: true
23
+ opt '--api_key KEY', 'Rackspace API key', required: true, secret: true
24
+ opt '--region REGION', 'Cloudfiles region', required: true, enum: %w[ord dfw syd iad hkg]
25
+ opt '--container NAME', 'Name of the container that files will be uploaded to', required: true
26
+ opt '--glob GLOB', 'Paths to upload', default: '**/*'
27
+ opt '--dot_match', 'Upload hidden files starting a dot'
28
+
29
+ msgs missing_container: 'The specified container does not exist.'
30
+
31
+ def deploy
32
+ paths.each do |path|
33
+ container.files.create(key: path, body: File.open(path))
34
+ end
35
+ end
36
+
37
+ def paths
38
+ paths = Dir.glob(*glob)
39
+ paths.reject { |path| File.directory?(path) }
40
+ end
41
+
42
+ def glob
43
+ glob = [super]
44
+ glob << File::FNM_DOTMATCH if dot_match?
45
+ glob
46
+ end
47
+
48
+ def container
49
+ @container ||= api.directories.get(super) || error(:missing_container)
50
+ end
51
+
52
+ def api
53
+ @api ||= Fog::Storage.new(
54
+ provider: 'Rackspace',
55
+ rackspace_username: username,
56
+ rackspace_api_key: api_key,
57
+ rackspace_region: region
58
+ )
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,281 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dpl
4
+ module Providers
5
+ class Cloudformation < Provider
6
+ register :cloudformation
7
+ status :stable
8
+
9
+ full_name 'AWS CloudFormation'
10
+
11
+ description sq(<<-STR)
12
+ tbd
13
+ STR
14
+
15
+ gem 'aws-sdk-cloudformation', '~> 1.0'
16
+
17
+ env :aws, :cloudformation
18
+ config '~/.aws/credentials', prefix: 'aws'
19
+
20
+ opt '--access_key_id ID', 'AWS Access Key ID', required: true, secret: true
21
+ opt '--secret_access_key KEY', 'AWS Secret Key', required: true, secret: true
22
+ opt '--region REGION', 'AWS Region to deploy to', default: 'us-east-1'
23
+ opt '--template STR', 'CloudFormation template file', required: true, note: 'can be either a local path or an S3 URL'
24
+ opt '--stack_name NAME', 'CloudFormation Stack Name.', required: true
25
+ opt '--stack_name_prefix STR', 'CloudFormation Stack Name Prefix.'
26
+ opt '--promote', 'Deploy changes', default: true, note: 'otherwise a change set is created'
27
+ opt '--role_arn ARN', 'AWS Role ARN'
28
+ opt '--sts_assume_role ARN', 'AWS Role ARN for cross account deployments (assumed by travis using given AWS credentials).'
29
+ opt '--capabilities STR', 'CloudFormation allowed capabilities', type: :array, enum: %w[CAPABILITY_IAM CAPABILITY_NAMED_IAM CAPABILITY_AUTO_EXPAND], sep: ',', see: 'https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_CreateStack.html'
30
+ opt '--wait', 'Wait for CloutFormation to finish the stack creation and update', default: true
31
+ opt '--wait_timeout SEC', 'How many seconds to wait for stack creation and update.', type: :integer, default: 3600
32
+ opt '--create_timeout SEC', 'How many seconds to wait before the stack status becomes CREATE_FAILED', type: :integer, default: 3600, note: 'valid only when creating a stack'
33
+ opt '--parameters STR', 'key=value pairs or ENV var names', type: :array, eg: 'one=1 or ENV_VAR_TWO'
34
+ opt '--output_file PATH', 'Path to output file to store CloudFormation outputs to'
35
+
36
+ msgs login: 'Using Access Key: %{access_key_id}',
37
+ create_stack: 'Creating stack ...',
38
+ promote_stack: 'Promoting stack ...',
39
+ create_change_set: 'Creating change set ...',
40
+ stack_up_to_date: 'Stack already up to date.',
41
+ delete_change_set: 'No changes in stack. Removing changeset.',
42
+ done: 'Done.',
43
+ missing_template: 'File does not exist: %{template}',
44
+ invalid_creds: 'Invalid credentials'
45
+
46
+ strs change_set_name: 'travis-ci-build-%{build_number}-%{now}',
47
+ change_set_desc: 'Changeset created by Travis CI job for build #%{build_number} (%{git_sha})'
48
+
49
+ def login
50
+ info :login
51
+ end
52
+
53
+ def deploy
54
+ stack_exists? ? update : create
55
+ store_events if output_file?
56
+ rescue Aws::CloudFormation::Errors::InvalidAccessKeyId
57
+ error :invalid_creds
58
+ end
59
+
60
+ private
61
+
62
+ def update
63
+ promote? ? promote : create_change_set(:update)
64
+ rescue Aws::CloudFormation::Errors::ValidationError => e
65
+ raise e unless e.message.start_with?('No updates are to be performed')
66
+
67
+ info :stack_up_to_date
68
+ end
69
+
70
+ def promote
71
+ info :promote_stack
72
+ client.update_stack(common_params)
73
+ stream_events(stack_name, :stack_update_complete) if wait?
74
+ info :done
75
+ end
76
+
77
+ def create
78
+ promote? ? create_stack : create_change_set(:create)
79
+ end
80
+
81
+ def create_stack
82
+ info :create_stack
83
+ params = { timeout_in_minutes: create_timeout, on_failure: 'ROLLBACK' }
84
+ client.create_stack(common_params.merge(params))
85
+ stream_events(stack_name, :stack_create_complete) if wait?
86
+ info :done
87
+ end
88
+
89
+ def create_change_set(type)
90
+ info :create_change_set
91
+ set = client.create_change_set(common_params.merge(change_set_params(type)))
92
+ wait_for(:change_set_create_complete, change_set_name: set.id) if wait? && !test?
93
+ info :done
94
+ rescue Aws::Waiters::Errors::FailureStateError => e
95
+ raise e unless change_set_contains_changes?(set)
96
+
97
+ info :delete_change_set
98
+ client.delete_change_set(change_set_name: set.id)
99
+ end
100
+
101
+ def change_set_params(type)
102
+ {
103
+ change_set_type: type.to_s.upcase,
104
+ change_set_name: interpolate(str(:change_set_name)),
105
+ description: interpolate(str(:change_set_desc))
106
+ }
107
+ end
108
+
109
+ def change_set_contains_changes?(change_set)
110
+ data = client.describe_change_set(change_set_name: change_set.id)
111
+ data.status_reason.start_with?(%(The submitted information didn't contain changes))
112
+ end
113
+
114
+ def stack_exists?
115
+ stack = last_stack
116
+ stack && stack.stack_status != 'REVIEW_IN_PROGRESS'
117
+ rescue Aws::CloudFormation::Errors::ValidationError => e
118
+ raise e unless e.message.include?('does not exist')
119
+
120
+ false
121
+ end
122
+
123
+ def stream_events(stack_name, condition)
124
+ stream = EventStream.new(client, stack_name, method(:info))
125
+ wait_for(condition, stack_name:) unless test? # hmm.
126
+ ensure
127
+ stream&.stop
128
+ end
129
+
130
+ def wait_for(cond, params)
131
+ started_at = Time.now
132
+ timeout = ->(*) { throw :failure if Time.now - started_at > wait_timeout }
133
+ # params = params.merge(max_attempts: nil, delay: 5, before_wait: timeout)
134
+ client.wait_until(cond, params) { |w| w.before_wait(&timeout) }
135
+ end
136
+
137
+ def store_events
138
+ logs = last_stack.outputs || {}
139
+ logs = logs.map { |log| "#{log[:output_key]}=#{log[:output_value]}" }
140
+ File.write(output_file, logs.join("\n"))
141
+ end
142
+
143
+ def last_stack
144
+ client.describe_stacks(stack_name:)[:stacks].first
145
+ end
146
+
147
+ def common_params
148
+ params = {
149
+ stack_name:,
150
+ role_arn:,
151
+ capabilities:,
152
+ parameters:
153
+ }
154
+ params.merge!(template_param)
155
+ @common_params ||= compact(params)
156
+ end
157
+
158
+ def parameters
159
+ @parameters ||= Array(super).map do |str|
160
+ key, value = str.split('=', 2)
161
+ { parameter_key: key, parameter_value: value || ENV[key] }
162
+ end
163
+ end
164
+
165
+ def create_timeout
166
+ super / 60
167
+ end
168
+
169
+ def stack_name
170
+ @stack_name ||= "#{stack_name_prefix}#{super}"
171
+ end
172
+
173
+ def template_param
174
+ str = template
175
+ return { template_url: str } if url?(str)
176
+ return { template_body: read(str) } if file?(str)
177
+
178
+ error(:missing_template)
179
+ end
180
+
181
+ def client
182
+ @client ||= Aws::CloudFormation::Client.new(client_options)
183
+ end
184
+
185
+ def client_options
186
+ params = { region:, credentials: }
187
+ params = params.merge(credentials: assume_role(params)) if sts_assume_role?
188
+ params
189
+ end
190
+
191
+ def credentials
192
+ Aws::Credentials.new(access_key_id, secret_access_key)
193
+ end
194
+
195
+ def assume_role(params)
196
+ assumed_role = Aws::STS::Client.new(params).assume_role(
197
+ role_arn: sts_assume_role,
198
+ role_session_name: "travis-build-#{build_number}"
199
+ )
200
+ Aws::Credentials.new(
201
+ assumed_role.credentials.access_key_id,
202
+ assumed_role.credentials.secret_access_key,
203
+ assumed_role.credentials.session_token
204
+ )
205
+ end
206
+
207
+ def now
208
+ Time.now.strftime('%Y%m%d%H%M%S')
209
+ end
210
+
211
+ def url?(str)
212
+ str =~ %r{^https?://}
213
+ end
214
+
215
+ class EventStream < Struct.new(:client, :stack_name, :handler)
216
+ attr_reader :thread
217
+
218
+ def initialize(*)
219
+ super
220
+ @event = describe_stack_events.stack_events.first
221
+ @thread = Thread.new(&method(:process))
222
+ end
223
+
224
+ def stop
225
+ mutex.synchronize { @stop = true }
226
+ thread.join
227
+ end
228
+
229
+ private
230
+
231
+ def process
232
+ until mutex.synchronize { @stop }
233
+ @event, events = events_since(@event)
234
+ events.each { |e| handler.call(format_event(e)) }
235
+ sleep 5 unless ENV['ENV'] == 'test'
236
+ end
237
+ end
238
+
239
+ # source: https://github.com/rvedotrc/cfn-events/blob/master/lib/cfn-events/runner.rb
240
+ def events_since(event)
241
+ described_stack = describe_stack_events
242
+ stack_events = described_stack.stack_events
243
+ return [event, []] if stack_events.first.event_id == event.event_id
244
+
245
+ events = []
246
+ described_stack.each_page do |page|
247
+ if (oldest_new = page.stack_events.index { |e| e.event_id == event.event_id })
248
+ events.concat(page.stack_events[0..oldest_new - 1])
249
+ return [events.first, events.reverse]
250
+ end
251
+ events.concat(page.stack_events)
252
+ end
253
+
254
+ warn %(Last-seen stack event is no longer returned by AWS. Please raise this as a provider's bug.)
255
+ [events.first, events.reverse]
256
+ end
257
+
258
+ def describe_stack_events
259
+ client.describe_stack_events(stack_name:)
260
+ end
261
+
262
+ def mutex
263
+ @mutex ||= Mutex.new
264
+ end
265
+
266
+ EVENT_KEYS = %i[timestamp resource_type resource_status logical_resource_id
267
+ physical_resource_id resource_status_reason].freeze
268
+
269
+ def format_event(event)
270
+ parts = EVENT_KEYS.map { |key| event.send(key) }
271
+ parts[0] = format_timestamp(parts[0])
272
+ parts.join(' ')
273
+ end
274
+
275
+ def format_timestamp(timestamp)
276
+ timestamp.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
277
+ end
278
+ end
279
+ end
280
+ end
281
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dpl
4
+ module Providers
5
+ class Cloudfoundry < Provider
6
+ register :cloudfoundry
7
+
8
+ status :stable
9
+
10
+ full_name 'Cloud Foundry'
11
+
12
+ description sq(<<-STR)
13
+ tbd
14
+ STR
15
+
16
+ env :cloudfoundry
17
+
18
+ opt '--username USER', 'Cloud Foundry username', required: true
19
+ opt '--password PASS', 'Cloud Foundry password', required: true, secret: true
20
+ opt '--organization ORG', 'Cloud Foundry organization', required: true
21
+ opt '--space SPACE', 'Cloud Foundry space', required: true
22
+ opt '--api URL', 'Cloud Foundry api URL', default: 'https://api.run.pivotal.io'
23
+ opt '--app_name APP', 'Application name'
24
+ opt '--buildpack PACK', 'Buildpack name or Git URL'
25
+ opt '--manifest FILE', 'Path to the manifest'
26
+ opt '--skip_ssl_validation', 'Skip SSL validation'
27
+ opt '--deployment_strategy STRATEGY', 'Deployment strategy, either rolling or null'
28
+ opt '--v3', 'Use the v3 API version to push the application'
29
+ opt '--logout', default: true, internal: true
30
+
31
+ cmds install: 'test $(uname) = "Linux" && rel="linux64-binary" || rel="macosx64"; wget "https://cli.run.pivotal.io/stable?release=${rel}&version=v7&source=github" -qO cf.tgz && tar -zxvf cf.tgz && rm cf.tgz',
32
+ api: './cf api %{api} %{skip_ssl_validation_opt}',
33
+ login: './cf login -u %{username} -p %{password} -o %{organization} -s %{space}',
34
+ push: './cf %{push_cmd} %{push_args}',
35
+ logout: './cf logout'
36
+
37
+ errs install: 'Failed to install CLI tools',
38
+ api: 'Failed to set api %{api}',
39
+ login: 'Failed to login',
40
+ push: 'Failed to push app',
41
+ logout: 'Failed to logout'
42
+
43
+ msgs manifest_missing: 'Application must have a manifest.yml for unattended deployment'
44
+
45
+ def install
46
+ shell :install
47
+ end
48
+
49
+ def validate
50
+ error :manifest_missing if manifest? && manifest_missing?
51
+ end
52
+
53
+ def login
54
+ shell :api
55
+ shell :login
56
+ end
57
+
58
+ def deploy
59
+ shell :push
60
+ end
61
+
62
+ def finish
63
+ shell :logout if logout?
64
+ end
65
+
66
+ private
67
+
68
+ def push_cmd
69
+ v3? ? 'v3-push' : 'push'
70
+ end
71
+
72
+ def push_args
73
+ args = []
74
+ args << quote(app_name) if app_name?
75
+ args << "-f #{manifest}" if manifest?
76
+ args << "--strategy #{deployment_strategy}" if deployment_strategy?
77
+ args.join(' ')
78
+ end
79
+
80
+ def skip_ssl_validation_opt
81
+ '--skip-ssl-validation' if skip_ssl_validation?
82
+ end
83
+
84
+ def manifest_missing?
85
+ !File.exist?(manifest)
86
+ end
87
+ end
88
+ end
89
+ end