dpl-ops_works 1.9.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 700293690bf0aee31bbb320afa956a9fa2afdf63
4
+ data.tar.gz: 70fd5dad880da64b0c18d68524d6a104b5aafb09
5
+ SHA512:
6
+ metadata.gz: 4c482f9186d74c7f01c94986c99ab469f9ae019542f2160b430436dfcce8b1f4031492e51d4438536b8a565a9d17aea292ce3b1772b3e8b2d4e2a661b034c45a
7
+ data.tar.gz: 67f6083c8f061e91d582e56bb0e3e037c4f9b80d0cbaa18b3da302d5644fad7fd884a18a0ded5a3c9d7dd59191ddf7cadc014bc3139a436b42b44844a305a64d
@@ -0,0 +1,3 @@
1
+ require './gemspec_helper'
2
+
3
+ gemspec_for 'ops_works', [['aws-sdk', '~> 2.0']]
@@ -0,0 +1,132 @@
1
+ require 'timeout'
2
+ require 'aws-sdk'
3
+
4
+ module DPL
5
+ class Provider
6
+ class OpsWorks < Provider
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
+ }.to_json
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
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,127 @@
1
+ require 'spec_helper'
2
+ require 'aws-sdk'
3
+ require 'dpl/provider'
4
+ require 'dpl/provider/ops_works'
5
+
6
+ describe DPL::Provider::OpsWorks do
7
+
8
+ subject :provider do
9
+ described_class.new(DummyContext.new, :access_key_id => 'qwertyuiopasdfghjklz', :secret_access_key => 'qwertyuiopasdfghjklzqwertyuiopasdfghjklz')
10
+ end
11
+
12
+ describe '#opsworks_options' do
13
+ context 'without region' do
14
+ example do
15
+ options = provider.opsworks_options
16
+ expect(options[:region]).to eq('us-east-1')
17
+ end
18
+ end
19
+
20
+ context 'with region' do
21
+ example do
22
+ region = 'us-west-1'
23
+ provider.options.update(:region => region)
24
+ options = provider.opsworks_options
25
+ expect(options[:region]).to eq(region)
26
+ end
27
+ end
28
+ end
29
+
30
+ describe "#check_auth" do
31
+ example do
32
+ expect(provider).to receive(:log).with('Logging in with Access Key: ****************jklz')
33
+ provider.check_auth
34
+ end
35
+ end
36
+
37
+ describe "#needs_key?" do
38
+ example do
39
+ expect(provider.needs_key?).to eq(false)
40
+ end
41
+ end
42
+
43
+ describe DPL::Provider::OpsWorks do
44
+ access_key_id = 'someaccesskey'
45
+ secret_access_key = 'somesecretaccesskey'
46
+ region = 'us-east-1'
47
+
48
+ client_options = {
49
+ stub_responses: true,
50
+ region: region,
51
+ credentials: Aws::Credentials.new(access_key_id, secret_access_key)
52
+ }
53
+
54
+ subject :provider do
55
+ described_class.new(DummyContext.new, {
56
+ access_key_id: access_key_id,
57
+ secret_access_key: secret_access_key
58
+ })
59
+ end
60
+
61
+ before :each do
62
+ expect(provider).to receive(:opsworks_options).and_return(client_options)
63
+ end
64
+
65
+ describe '#opsworks' do
66
+ example do
67
+ expect(Aws::OpsWorks::Client).to receive(:new).with(client_options).once
68
+ provider.opsworks
69
+ end
70
+ end
71
+
72
+ describe "#push_app" do
73
+ let(:client) { provider.opsworks }
74
+ let(:ops_works_app) { {shortname: 'app', stack_id: 'stack-id'} }
75
+ before do
76
+ expect(provider).to receive(:current_sha).and_return('sha')
77
+ expect(provider.context.env).to receive(:[]).with('TRAVIS_BUILD_NUMBER').and_return('123')
78
+ end
79
+
80
+ let(:custom_json) { "{\"deploy\":{\"app\":{\"migrate\":false,\"scm\":{\"revision\":\"sha\"}}}}" }
81
+ example 'without :migrate option' do
82
+ provider.options.update(app_id: 'app-id')
83
+ expect(client).to receive(:describe_apps).with(app_ids: ['app-id']).and_return({apps: [ops_works_app]})
84
+ expect(client).to receive(:create_deployment).with(
85
+ stack_id: 'stack-id', app_id: 'app-id', command: {name: 'deploy'}, comment: 'Deploy build 123 via Travis CI', custom_json: custom_json
86
+ ).and_return({})
87
+ provider.push_app
88
+ end
89
+
90
+ let(:custom_json_with_migrate) { "{\"deploy\":{\"app\":{\"migrate\":true,\"scm\":{\"revision\":\"sha\"}}}}" }
91
+ example 'with :migrate option' do
92
+ provider.options.update(app_id: 'app-id', migrate: true)
93
+ expect(client).to receive(:describe_apps).with(app_ids: ['app-id']).and_return({apps: [ops_works_app]})
94
+ expect(client).to receive(:create_deployment).with(
95
+ stack_id: 'stack-id', app_id: 'app-id', command: {name: 'deploy'}, comment: 'Deploy build 123 via Travis CI', custom_json: custom_json_with_migrate
96
+ ).and_return({})
97
+ provider.push_app
98
+ end
99
+
100
+ example 'with :wait_until_deployed' do
101
+ provider.options.update(app_id: 'app-id', wait_until_deployed: true)
102
+ expect(client).to receive(:describe_apps).with(app_ids: ['app-id']).and_return({apps: [ops_works_app]})
103
+ expect(client).to receive(:create_deployment).and_return({deployment_id: 'deployment_id'})
104
+ expect(client).to receive(:describe_deployments).with({deployment_ids: ['deployment_id']}).and_return({deployments: [status: 'running']}, {deployments: [status: 'successful']})
105
+ provider.push_app
106
+ end
107
+
108
+ example 'with :instance-ids' do
109
+ provider.options.update(app_id: 'app-id', instance_ids: ['instance-id'])
110
+ expect(client).to receive(:describe_apps).with(app_ids: ['app-id']).and_return({apps: [ops_works_app]})
111
+ expect(client).to receive(:create_deployment).with(
112
+ stack_id: 'stack-id', app_id: 'app-id', instance_ids:['instance-id'], command: {name: 'deploy'}, comment: 'Deploy build 123 via Travis CI', custom_json: custom_json
113
+ ).and_return({})
114
+ provider.push_app
115
+ end
116
+
117
+ example 'with :layer-ids' do
118
+ provider.options.update(app_id: 'app-id', layer_ids: ['layer-id'])
119
+ expect(client).to receive(:describe_apps).with(app_ids: ['app-id']).and_return({apps: [ops_works_app]})
120
+ expect(client).to receive(:create_deployment).with(
121
+ stack_id: 'stack-id', app_id: 'app-id', layer_ids:['layer-id'], command: {name: 'deploy'}, comment: 'Deploy build 123 via Travis CI', custom_json: custom_json
122
+ ).and_return({})
123
+ provider.push_app
124
+ end
125
+ end
126
+ end
127
+ end
metadata ADDED
@@ -0,0 +1,173 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dpl-ops_works
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.9.0
5
+ platform: ruby
6
+ authors:
7
+ - Konstantin Haase
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-03-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dpl
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.9.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.9.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: aws-sdk
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-its
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: json_pure
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: tins
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: coveralls
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: highline
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: deploy tool abstraction for clients
140
+ email: konstantin.mailinglists@googlemail.com
141
+ executables: []
142
+ extensions: []
143
+ extra_rdoc_files: []
144
+ files:
145
+ - dpl-ops_works.gemspec
146
+ - lib/dpl/provider/ops_works.rb
147
+ - spec/provider/ops_works_spec.rb
148
+ homepage: https://github.com/travis-ci/dpl
149
+ licenses:
150
+ - MIT
151
+ metadata: {}
152
+ post_install_message:
153
+ rdoc_options: []
154
+ require_paths:
155
+ - lib
156
+ required_ruby_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '2.2'
161
+ required_rubygems_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ requirements: []
167
+ rubyforge_project:
168
+ rubygems_version: 2.6.13
169
+ signing_key:
170
+ specification_version: 4
171
+ summary: deploy tool
172
+ test_files:
173
+ - spec/provider/ops_works_spec.rb