dpl-ops_works 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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