train 1.4.4 → 1.4.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3bd7445d39832ea8fdd1ccba4a089153a6352229246b6c7ed8251eb44afd099f
4
- data.tar.gz: e813525dbb9a25e7cf7138d30c704503acd06d96e895c238b0d4453b6fc6323f
3
+ metadata.gz: cecb9bec9682f0acc90154bcdc16a17fbe7c146b30b3be37bbadd774176d7065
4
+ data.tar.gz: fa01c4fde81ed2a58584576a07cb68ad52b3e73926521e6329486352c4dfa14c
5
5
  SHA512:
6
- metadata.gz: d38b05424dbd5431aa31f5a921d724f1e07247d5601a85a61b503a0c73a2194f3694aaddffe39fac89e375825a8f44ed839bd76c0a3e7353f90a593026c97398
7
- data.tar.gz: 814a6345a5f4d3eecc7e9d26d4050831598be0205f2c1a82dbec11678f9776a517bbf7657b3e1182cd72c4bf0192661390afaec1a356831edb1287a256f86f50
6
+ metadata.gz: 49af5ddd1e984052b4b4e3ba9d1f121ece725a29ecbcd672589a21187c19fb5f3d51859806560cfe2835f4f6499574fc5ed21fb5ae4356131297c05663bf0c63
7
+ data.tar.gz: f8e5cf2d0459c8e1b75ee95d91cba4084313f556a8900a0c7b6dbd9536f9602c0fb613f591787cdf02a63a8b8187cf4d8953cbc735a6defde018a01eb8d79e92
@@ -1,22 +1,33 @@
1
- <!-- latest_release 1.4.4 -->
2
- ## [v1.4.4](https://github.com/chef/train/tree/v1.4.4) (2018-05-02)
1
+ <!-- latest_release 1.4.9 -->
2
+ ## [v1.4.9](https://github.com/chef/train/tree/v1.4.9) (2018-05-16)
3
3
 
4
4
  #### Merged Pull Requests
5
- - Split train into a core gem. [#293](https://github.com/chef/train/pull/293) ([miah](https://github.com/miah))
6
- - Enable expeditor release tasks [#294](https://github.com/chef/train/pull/294) ([jquick](https://github.com/jquick))
5
+ - Unpin google-protobuf now that we are building it as a gem [#300](https://github.com/chef/train/pull/300) ([scotthain](https://github.com/scotthain))
7
6
  <!-- latest_release -->
8
7
 
9
- <!-- release_rollup since=1.4.2 -->
10
- ### Changes since 1.4.2 release
8
+ <!-- release_rollup since=1.4.4 -->
9
+ ### Changes since 1.4.4 release
10
+
11
+ #### Bug Fixes
12
+ - Allow nil password and www_form_encoded_password to work together. [#297](https://github.com/chef/train/pull/297) ([marcparadise](https://github.com/marcparadise)) <!-- 1.4.6 -->
11
13
 
12
14
  #### Merged Pull Requests
13
- - Split train into a core gem. [#293](https://github.com/chef/train/pull/293) ([miah](https://github.com/miah)) <!-- 1.4.4 -->
14
- - Enable expeditor release tasks [#294](https://github.com/chef/train/pull/294) ([jquick](https://github.com/jquick)) <!-- 1.4.3 -->
15
+ - Unpin google-protobuf now that we are building it as a gem [#300](https://github.com/chef/train/pull/300) ([scotthain](https://github.com/scotthain)) <!-- 1.4.9 -->
16
+ - Change Cisco IOS transport log level to INFO [#298](https://github.com/chef/train/pull/298) ([jerryaldrichiii](https://github.com/jerryaldrichiii)) <!-- 1.4.8 -->
17
+ - Initial import of transport for GCP. [#283](https://github.com/chef/train/pull/283) ([skpaterson](https://github.com/skpaterson)) <!-- 1.4.7 -->
18
+ - Support encoded passwords in target url [#296](https://github.com/chef/train/pull/296) ([marcparadise](https://github.com/marcparadise)) <!-- 1.4.5 -->
15
19
  <!-- release_rollup -->
16
20
 
17
21
  <!-- latest_stable_release -->
22
+ ## [v1.4.4](https://github.com/chef/train/tree/v1.4.4) (2018-05-02)
23
+
24
+ #### Merged Pull Requests
25
+ - Enable expeditor release tasks [#294](https://github.com/chef/train/pull/294) ([jquick](https://github.com/jquick))
26
+ - Split train into a core gem. [#293](https://github.com/chef/train/pull/293) ([miah](https://github.com/miah))
18
27
  <!-- latest_stable_release -->
19
28
 
29
+
30
+
20
31
  # Change Log
21
32
 
22
33
  ## [1.4.2](https://github.com/chef/train/tree/1.4.2) (2018-04-26)
data/Gemfile CHANGED
@@ -23,7 +23,7 @@ group :test do
23
23
  end
24
24
 
25
25
  group :integration do
26
- gem 'berkshelf', '~> 4.3'
26
+ gem 'berkshelf', '~> 5.2'
27
27
  gem 'test-kitchen', '~> 1.11'
28
28
  gem 'kitchen-vagrant'
29
29
  end
@@ -66,8 +66,13 @@ module Train
66
66
  conf[:host] ||= uri.hostname
67
67
  conf[:port] ||= uri.port
68
68
  conf[:user] ||= uri.user
69
- conf[:password] ||= uri.password
70
69
  conf[:path] ||= uri.path
70
+ conf[:password] ||=
71
+ if conf[:www_form_encoded_password] && !uri.password.nil?
72
+ URI.decode_www_form_component(uri.password)
73
+ else
74
+ uri.password
75
+ end
71
76
  end
72
77
 
73
78
  # ensure path is nil, if its empty; e.g. required to reset defaults for winrm
@@ -10,6 +10,7 @@ module Train::Platforms::Detect::Specifications
10
10
  plat.family('cloud').in_family('api')
11
11
  plat.name('aws').in_family('cloud')
12
12
  plat.name('azure').in_family('cloud')
13
+ plat.name('gcp').in_family('cloud')
13
14
  end
14
15
  end
15
16
  end
@@ -7,6 +7,8 @@ class Train::Transports::SSH
7
7
  def initialize(options)
8
8
  super(options)
9
9
 
10
+ logger.level = Logger::INFO
11
+
10
12
  # Extract options to avoid passing them in to `Net::SSH.start` later
11
13
  @host = options.delete(:host)
12
14
  @user = options.delete(:user)
@@ -0,0 +1,92 @@
1
+ # encoding: utf-8
2
+
3
+ require 'train/plugins'
4
+ require 'google/apis'
5
+ require 'google/apis/cloudresourcemanager_v1'
6
+ require 'google/apis/compute_v1'
7
+ require 'google/apis/storage_v1'
8
+ require 'google/apis/iam_v1'
9
+ require 'googleauth'
10
+
11
+ module Train::Transports
12
+ class Gcp < Train.plugin(1)
13
+ name 'gcp'
14
+
15
+ # GCP will look automatically for the below env var for service accounts etc. :
16
+ option :google_application_credentials, required: false, default: ENV['GOOGLE_APPLICATION_CREDENTIALS']
17
+ # see https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application
18
+ # In the absence of this, the client is expected to have already set up local credentials via:
19
+ # $ gcloud auth application-default login
20
+ # $ gcloud config set project <project-name>
21
+ # GCP projects can have default regions / zones set, see:
22
+ # https://cloud.google.com/compute/docs/regions-zones/changing-default-zone-region
23
+ # can also specify project via env var:
24
+ option :google_cloud_project, required: false, default: ENV['GOOGLE_CLOUD_PROJECT']
25
+
26
+ def connection(_ = nil)
27
+ @connection ||= Connection.new(@options)
28
+ end
29
+
30
+ class Connection < BaseConnection
31
+ def initialize(options)
32
+ super(options)
33
+
34
+ # additional GCP platform metadata
35
+ release = Gem.loaded_specs['google_cloud']
36
+ @platform_details = { release: "google-cloud-v#{release}" }
37
+
38
+ # Initialize the client object cache
39
+ @cache_enabled[:api_call] = true
40
+ @cache[:api_call] = {}
41
+
42
+ connect
43
+ end
44
+
45
+ def platform
46
+ direct_platform('gcp', @platform_details)
47
+ end
48
+
49
+ # Instantiate some named classes for ease of use
50
+ def gcp_compute_client
51
+ gcp_client(Google::Apis::ComputeV1::ComputeService)
52
+ end
53
+
54
+ def gcp_iam_client
55
+ gcp_client(Google::Apis::IamV1::IamService)
56
+ end
57
+
58
+ def gcp_project_client
59
+ gcp_client(Google::Apis::CloudresourcemanagerV1::CloudResourceManagerService)
60
+ end
61
+
62
+ def gcp_storage_client
63
+ gcp_client(Google::Apis::StorageV1::StorageService)
64
+ end
65
+
66
+ # Let's allow for other clients too
67
+ def gcp_client(klass)
68
+ return klass.new unless cache_enabled?(:api_call)
69
+ @cache[:api_call][klass.to_s.to_sym] ||= klass.new
70
+ end
71
+
72
+ def connect
73
+ ENV['GOOGLE_APPLICATION_CREDENTIALS'] = @options[:google_application_credentials] if @options[:google_application_credentials]
74
+ ENV['GOOGLE_CLOUD_PROJECT'] = @options[:google_cloud_project] if @options[:google_cloud_project]
75
+ # GCP initialization
76
+ scopes = ['https://www.googleapis.com/auth/cloud-platform',
77
+ 'https://www.googleapis.com/auth/compute']
78
+ authorization = Google::Auth.get_application_default(scopes)
79
+ Google::Apis::RequestOptions.default.authorization = authorization
80
+ end
81
+
82
+ def uri
83
+ "gcp://#{unique_identifier}"
84
+ end
85
+
86
+ def unique_identifier
87
+ # use auth client_id - same to retrieve for any of the clients but use IAM
88
+ gcp_iam_client.request_options.authorization.client_id
89
+ end
90
+ end
91
+ end
92
+ end
@@ -3,5 +3,5 @@
3
3
  # Author:: Dominik Richter (<dominik.richter@gmail.com>)
4
4
 
5
5
  module Train
6
- VERSION = '1.4.4'.freeze
6
+ VERSION = '1.4.9'.freeze
7
7
  end
@@ -177,6 +177,32 @@ describe Train do
177
177
  res[:target].must_equal org[:target]
178
178
  end
179
179
 
180
+ it 'supports www-form encoded passwords when the option is set' do
181
+ raw_password = '+!@#$%^&*()_-\';:"\\|/?.>,<][}{=`~'
182
+ encoded_password = URI.encode_www_form_component(raw_password)
183
+ org = { target: "mock://username:#{encoded_password}@1.2.3.4:100",
184
+ www_form_encoded_password: true}
185
+ res = Train.target_config(org)
186
+ res[:backend].must_equal 'mock'
187
+ res[:host].must_equal '1.2.3.4'
188
+ res[:user].must_equal 'username'
189
+ res[:password].must_equal raw_password
190
+ res[:port].must_equal 100
191
+ res[:target].must_equal org[:target]
192
+ end
193
+
194
+ it 'ignores www-form-encoded password value when there is no password' do
195
+ org = { target: "mock://username@1.2.3.4:100",
196
+ www_form_encoded_password: true}
197
+ res = Train.target_config(org)
198
+ res[:backend].must_equal 'mock'
199
+ res[:host].must_equal '1.2.3.4'
200
+ res[:user].must_equal 'username'
201
+ res[:password].must_be_nil
202
+ res[:port].must_equal 100
203
+ res[:target].must_equal org[:target]
204
+ end
205
+
180
206
  it 'it raises UserError on invalid URIs' do
181
207
  org = { target: 'mock world' }
182
208
  proc { Train.target_config(org) }.must_raise Train::UserError
@@ -0,0 +1,191 @@
1
+ # encoding: utf-8
2
+
3
+ require 'helper'
4
+
5
+ describe 'gcp transport' do
6
+
7
+ let(:credentials_file) do
8
+ require 'tempfile'
9
+ file = Tempfile.new('application_default_credentials.json')
10
+ info = <<-INFO
11
+ {
12
+ "client_id": "asdfasf-asdfasdf.apps.googleusercontent.com",
13
+ "client_secret": "d-asdfasdf",
14
+ "refresh_token": "1/adsfasdf-lCkju3-yQmjr20xVZonrfkE48L",
15
+ "type": "authorized_user"
16
+ }
17
+ INFO
18
+ file.write(info)
19
+ file.close
20
+ file
21
+ end
22
+
23
+ let(:credentials_file_override) do
24
+ require 'tempfile'
25
+ file = Tempfile.new('application_default_credentials.json')
26
+ info = <<-INFO
27
+ {
28
+ "client_id": "asdfasf-asdfasdf.apps.googleusercontent.com",
29
+ "client_secret": "d-asdfasdf",
30
+ "refresh_token": "1/adsfasdf-lCkju3-yQmjr20xVZonrfkE48L",
31
+ "type": "authorized_user"
32
+ }
33
+ INFO
34
+ file.write(info)
35
+ file.close
36
+ file
37
+ end
38
+
39
+ def transport(options = nil)
40
+ ENV['GOOGLE_APPLICATION_CREDENTIALS'] = credentials_file.path
41
+ ENV['GOOGLE_CLOUD_PROJECT'] = 'test_project'
42
+ # need to require this at here as it captures the envs on load
43
+ require 'train/transports/gcp'
44
+ Train::Transports::Gcp.new(options)
45
+ end
46
+
47
+ let(:connection) { transport.connection }
48
+ let(:options) { connection.instance_variable_get(:@options) }
49
+ let(:cache) { connection.instance_variable_get(:@cache) }
50
+
51
+ describe 'options' do
52
+ it 'defaults to env options' do
53
+ options[:google_application_credentials] = credentials_file.path
54
+ options[:google_cloud_project].must_equal 'test_project'
55
+ end
56
+ end
57
+
58
+ it 'allows for options override' do
59
+ transport = transport(google_application_credentials: credentials_file_override.path, google_cloud_project: "override_project")
60
+ options = transport.connection.instance_variable_get(:@options)
61
+ options[:google_application_credentials].must_equal credentials_file_override.path
62
+ options[:google_cloud_project].must_equal "override_project"
63
+ end
64
+
65
+ describe 'platform' do
66
+ it 'returns platform' do
67
+ platform = connection.platform
68
+ platform.name.must_equal 'gcp'
69
+ platform.family_hierarchy.must_equal ['cloud', 'api']
70
+ end
71
+ end
72
+
73
+ describe 'gcp_client' do
74
+ it 'test gcp_client with caching' do
75
+ client = connection.gcp_client(Object)
76
+ client.is_a?(Object).must_equal true
77
+ cache[:api_call].count.must_equal 1
78
+ end
79
+
80
+ it 'test gcp_client without caching' do
81
+ connection.disable_cache(:api_call)
82
+ client = connection.gcp_client(Object)
83
+ client.is_a?(Object).must_equal true
84
+ cache[:api_call].count.must_equal 0
85
+ end
86
+ end
87
+
88
+
89
+ describe 'gcp_compute_client' do
90
+ it 'test gcp_compute_client with caching' do
91
+ client = connection.gcp_compute_client
92
+ client.is_a?(Google::Apis::ComputeV1::ComputeService).must_equal true
93
+ cache[:api_call].count.must_equal 1
94
+ end
95
+
96
+ it 'test gcp_client without caching' do
97
+ connection.disable_cache(:api_call)
98
+ client = connection.gcp_compute_client
99
+ client.is_a?(Google::Apis::ComputeV1::ComputeService).must_equal true
100
+ cache[:api_call].count.must_equal 0
101
+ end
102
+ end
103
+
104
+ describe 'gcp_iam_client' do
105
+ it 'test gcp_iam_client with caching' do
106
+ client = connection.gcp_iam_client
107
+ client.is_a?(Google::Apis::IamV1::IamService).must_equal true
108
+ cache[:api_call].count.must_equal 1
109
+ end
110
+
111
+ it 'test gcp_iam_client without caching' do
112
+ connection.disable_cache(:api_call)
113
+ client = connection.gcp_iam_client
114
+ client.is_a?(Google::Apis::IamV1::IamService).must_equal true
115
+ cache[:api_call].count.must_equal 0
116
+ end
117
+ end
118
+
119
+ describe 'gcp_project_client' do
120
+ it 'test gcp_project_client with caching' do
121
+ client = connection.gcp_project_client
122
+ client.is_a?(Google::Apis::CloudresourcemanagerV1::CloudResourceManagerService).must_equal true
123
+ cache[:api_call].count.must_equal 1
124
+ end
125
+
126
+ it 'test gcp_project_client without caching' do
127
+ connection.disable_cache(:api_call)
128
+ client = connection.gcp_project_client
129
+ client.is_a?(Google::Apis::CloudresourcemanagerV1::CloudResourceManagerService).must_equal true
130
+ cache[:api_call].count.must_equal 0
131
+ end
132
+ end
133
+
134
+ describe 'gcp_storage_client' do
135
+ it 'test gcp_storage_client with caching' do
136
+ client = connection.gcp_storage_client
137
+ client.is_a?(Google::Apis::StorageV1::StorageService).must_equal true
138
+ cache[:api_call].count.must_equal 1
139
+ end
140
+
141
+ it 'test gcp_storage_client without caching' do
142
+ connection.disable_cache(:api_call)
143
+ client = connection.gcp_storage_client
144
+ client.is_a?(Google::Apis::StorageV1::StorageService).must_equal true
145
+ cache[:api_call].count.must_equal 0
146
+ end
147
+ end
148
+
149
+ # test options override of env vars in connect
150
+ describe 'connect' do
151
+ let(:creds) do
152
+ require 'tempfile'
153
+ file = Tempfile.new('creds')
154
+ info = <<-INFO
155
+ {
156
+ "client_id": "asdfasf-asdfasdf.apps.googleusercontent.com",
157
+ "client_secret": "d-asdfasdf",
158
+ "refresh_token": "1/adsfasdf-lCkju3-yQmjr20xVZonrfkE48L",
159
+ "type": "authorized_user"
160
+ }
161
+ INFO
162
+ file.write(info)
163
+ file.close
164
+ file
165
+ end
166
+ it 'validate gcp connection with credentials' do
167
+ options[:google_application_credentials] = creds.path
168
+ connection.connect
169
+ ENV['GOOGLE_APPLICATION_CREDENTIALS'].must_equal creds.path
170
+ end
171
+ it 'validate gcp connection with project' do
172
+ options[:google_cloud_project] = 'project'
173
+ connection.connect
174
+ ENV['GOOGLE_CLOUD_PROJECT'].must_equal 'project'
175
+ end
176
+ end
177
+
178
+ describe 'unique_identifier' do
179
+ it 'test connection unique identifier' do
180
+ client = connection
181
+ client.unique_identifier.must_equal 'asdfasf-asdfasdf.apps.googleusercontent.com'
182
+ end
183
+ end
184
+
185
+ describe 'uri' do
186
+ it 'test uri' do
187
+ client = connection
188
+ client.uri.must_equal 'gcp://asdfasf-asdfasdf.apps.googleusercontent.com'
189
+ end
190
+ end
191
+ end
@@ -35,6 +35,9 @@ Gem::Specification.new do |spec|
35
35
  spec.add_dependency 'docker-api', '~> 1.26'
36
36
  spec.add_dependency 'aws-sdk', '~> 2'
37
37
  spec.add_dependency 'azure_mgmt_resources', '~> 0.15'
38
+ spec.add_dependency 'google-api-client', '~> 0.19.8'
39
+ spec.add_dependency 'googleauth', '~> 0.6.2'
40
+ spec.add_dependency 'google-cloud', '~> 0.51.1'
38
41
  spec.add_dependency 'inifile'
39
42
 
40
43
  spec.add_development_dependency 'mocha', '~> 1.1'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: train
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.4
4
+ version: 1.4.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dominik Richter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-02 00:00:00.000000000 Z
11
+ date: 2018-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -148,6 +148,48 @@ dependencies:
148
148
  - - "~>"
149
149
  - !ruby/object:Gem::Version
150
150
  version: '0.15'
151
+ - !ruby/object:Gem::Dependency
152
+ name: google-api-client
153
+ requirement: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - "~>"
156
+ - !ruby/object:Gem::Version
157
+ version: 0.19.8
158
+ type: :runtime
159
+ prerelease: false
160
+ version_requirements: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - "~>"
163
+ - !ruby/object:Gem::Version
164
+ version: 0.19.8
165
+ - !ruby/object:Gem::Dependency
166
+ name: googleauth
167
+ requirement: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - "~>"
170
+ - !ruby/object:Gem::Version
171
+ version: 0.6.2
172
+ type: :runtime
173
+ prerelease: false
174
+ version_requirements: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - "~>"
177
+ - !ruby/object:Gem::Version
178
+ version: 0.6.2
179
+ - !ruby/object:Gem::Dependency
180
+ name: google-cloud
181
+ requirement: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - "~>"
184
+ - !ruby/object:Gem::Version
185
+ version: 0.51.1
186
+ type: :runtime
187
+ prerelease: false
188
+ version_requirements: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - "~>"
191
+ - !ruby/object:Gem::Version
192
+ version: 0.51.1
151
193
  - !ruby/object:Gem::Dependency
152
194
  name: inifile
153
195
  requirement: !ruby/object:Gem::Requirement
@@ -224,6 +266,7 @@ files:
224
266
  - lib/train/transports/azure.rb
225
267
  - lib/train/transports/cisco_ios_connection.rb
226
268
  - lib/train/transports/docker.rb
269
+ - lib/train/transports/gcp.rb
227
270
  - lib/train/transports/local.rb
228
271
  - lib/train/transports/mock.rb
229
272
  - lib/train/transports/ssh.rb
@@ -290,6 +333,7 @@ files:
290
333
  - test/unit/transports/aws_test.rb
291
334
  - test/unit/transports/azure_test.rb
292
335
  - test/unit/transports/cisco_ios_connection.rb
336
+ - test/unit/transports/gcp_test.rb
293
337
  - test/unit/transports/local_test.rb
294
338
  - test/unit/transports/mock_test.rb
295
339
  - test/unit/transports/ssh_test.rb
@@ -381,6 +425,7 @@ test_files:
381
425
  - test/unit/transports/aws_test.rb
382
426
  - test/unit/transports/azure_test.rb
383
427
  - test/unit/transports/cisco_ios_connection.rb
428
+ - test/unit/transports/gcp_test.rb
384
429
  - test/unit/transports/local_test.rb
385
430
  - test/unit/transports/mock_test.rb
386
431
  - test/unit/transports/ssh_test.rb