vagrant-google 2.5.0 → 2.6.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.
- checksums.yaml +5 -5
- data/.rubocop.yml +12 -4
- data/.ruby-version +2 -2
- data/CHANGELOG.md +28 -0
- data/Gemfile +2 -4
- data/README.md +42 -26
- data/lib/vagrant-google/action.rb +10 -0
- data/lib/vagrant-google/action/run_instance.rb +128 -79
- data/lib/vagrant-google/action/setup_winrm_password.rb +72 -0
- data/lib/vagrant-google/action/start_instance.rb +4 -4
- data/lib/vagrant-google/config.rb +80 -35
- data/lib/vagrant-google/version.rb +1 -1
- data/locales/en.yml +7 -4
- data/tasks/changelog.rake +40 -0
- data/test/acceptance/skeletons/image_family/Vagrantfile +2 -0
- data/test/unit/common/config_test.rb +107 -42
- data/vagrant-google.gemspec +4 -3
- metadata +27 -13
- data/.rubocop_todo.yml +0 -305
@@ -0,0 +1,72 @@
|
|
1
|
+
# Copyright 2015 Google Inc. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
#
|
15
|
+
# Changes:
|
16
|
+
# April 2019: Modified example found here:
|
17
|
+
# https://github.com/GoogleCloudPlatform/compute-image-windows/blob/master/examples/windows_auth_python_sample.py
|
18
|
+
# to enable WinRM with vagrant.
|
19
|
+
|
20
|
+
module VagrantPlugins
|
21
|
+
module Google
|
22
|
+
module Action
|
23
|
+
# Sets up a temporary WinRM password using Google's method for
|
24
|
+
# establishing a new password over encrypted channels.
|
25
|
+
class SetupWinrmPassword
|
26
|
+
def initialize(app, env)
|
27
|
+
@app = app
|
28
|
+
@logger = Log4r::Logger.new("vagrant_google::action::setup_winrm_password")
|
29
|
+
end
|
30
|
+
|
31
|
+
def setup_password(env, instance, zone, user)
|
32
|
+
# Setup
|
33
|
+
compute = env[:google_compute]
|
34
|
+
server = compute.servers.get(instance, zone)
|
35
|
+
password = server.reset_windows_password(user)
|
36
|
+
|
37
|
+
env[:ui].info("Temp Password: #{password}")
|
38
|
+
|
39
|
+
password
|
40
|
+
end
|
41
|
+
|
42
|
+
def call(env)
|
43
|
+
# Get the configs
|
44
|
+
zone = env[:machine].provider_config.zone
|
45
|
+
zone_config = env[:machine].provider_config.get_zone_config(zone)
|
46
|
+
|
47
|
+
instance = zone_config.name
|
48
|
+
user = env[:machine].config.winrm.username
|
49
|
+
pass = env[:machine].config.winrm.password
|
50
|
+
|
51
|
+
# Get Temporary Password, set WinRM password
|
52
|
+
temp_pass = setup_password(env, instance, zone, user)
|
53
|
+
env[:machine].config.winrm.password = temp_pass
|
54
|
+
|
55
|
+
# Wait for WinRM To be Ready
|
56
|
+
env[:ui].info("Waiting for WinRM To be ready")
|
57
|
+
env[:machine].communicate.wait_for_ready(60)
|
58
|
+
|
59
|
+
# Use WinRM to Change Password to one in Vagrantfile
|
60
|
+
env[:ui].info("Changing password from temporary to winrm password")
|
61
|
+
winrmcomm = VagrantPlugins::CommunicatorWinRM::Communicator.new(env[:machine])
|
62
|
+
cmd = "net user #{user} #{pass}"
|
63
|
+
opts = { elevated: true }
|
64
|
+
winrmcomm.test(cmd, opts)
|
65
|
+
|
66
|
+
# Update WinRM password to reflect updated one
|
67
|
+
env[:machine].config.winrm.password = pass
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -65,9 +65,9 @@ module VagrantPlugins
|
|
65
65
|
@logger.info("Time to instance ready: #{env[:metrics]["instance_ready_time"]}")
|
66
66
|
|
67
67
|
unless env[:interrupted]
|
68
|
-
env[:metrics]["
|
69
|
-
# Wait for
|
70
|
-
env[:ui].info(I18n.t("vagrant_google.
|
68
|
+
env[:metrics]["instance_comm_time"] = Util::Timer.time do
|
69
|
+
# Wait for Comms to be ready.
|
70
|
+
env[:ui].info(I18n.t("vagrant_google.waiting_for_comm"))
|
71
71
|
while true
|
72
72
|
# If we're interrupted then just back out
|
73
73
|
break if env[:interrupted]
|
@@ -76,7 +76,7 @@ module VagrantPlugins
|
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
79
|
-
@logger.info("Time for
|
79
|
+
@logger.info("Time for Comms ready: #{env[:metrics]["instance_comm_time"]}")
|
80
80
|
|
81
81
|
# Ready and booted!
|
82
82
|
env[:ui].info(I18n.t("vagrant_google.ready"))
|
@@ -178,38 +178,68 @@ module VagrantPlugins
|
|
178
178
|
# @return [Array<Hash>]
|
179
179
|
attr_accessor :additional_disks
|
180
180
|
|
181
|
+
# (Optional - Override default WinRM setup before for Public Windows images)
|
182
|
+
#
|
183
|
+
# @return [Boolean]
|
184
|
+
attr_accessor :setup_winrm_password
|
185
|
+
|
186
|
+
# Accelerators
|
187
|
+
#
|
188
|
+
# @return [Array<Hash>]
|
189
|
+
attr_accessor :accelerators
|
190
|
+
|
191
|
+
# whether the instance has Secure Boot enabled
|
192
|
+
#
|
193
|
+
# @return Boolean
|
194
|
+
attr_accessor :enable_secure_boot
|
195
|
+
|
196
|
+
# whether the instance has the vTPM enabled
|
197
|
+
#
|
198
|
+
# @return Boolean
|
199
|
+
attr_accessor :enable_vtpm
|
200
|
+
|
201
|
+
# whether the instance has integrity monitoring enabled
|
202
|
+
#
|
203
|
+
# @return Boolean
|
204
|
+
attr_accessor :enable_integrity_monitoring
|
205
|
+
|
181
206
|
def initialize(zone_specific=false)
|
182
|
-
@google_json_key_location
|
183
|
-
@google_project_id
|
184
|
-
@image
|
185
|
-
@image_family
|
186
|
-
@image_project_id
|
187
|
-
@instance_group
|
188
|
-
@machine_type
|
189
|
-
@disk_size
|
190
|
-
@disk_name
|
191
|
-
@disk_type
|
192
|
-
@metadata
|
193
|
-
@name
|
194
|
-
@network
|
195
|
-
@network_project_id
|
196
|
-
@subnetwork
|
197
|
-
@tags
|
198
|
-
@labels
|
199
|
-
@can_ip_forward
|
200
|
-
@external_ip
|
201
|
-
@network_ip
|
202
|
-
@use_private_ip
|
203
|
-
@autodelete_disk
|
204
|
-
@preemptible
|
205
|
-
@auto_restart
|
206
|
-
@on_host_maintenance
|
207
|
-
@instance_ready_timeout
|
208
|
-
@zone
|
209
|
-
@scopes
|
210
|
-
@service_accounts
|
211
|
-
@service_account
|
212
|
-
@additional_disks
|
207
|
+
@google_json_key_location = UNSET_VALUE
|
208
|
+
@google_project_id = UNSET_VALUE
|
209
|
+
@image = UNSET_VALUE
|
210
|
+
@image_family = UNSET_VALUE
|
211
|
+
@image_project_id = UNSET_VALUE
|
212
|
+
@instance_group = UNSET_VALUE
|
213
|
+
@machine_type = UNSET_VALUE
|
214
|
+
@disk_size = UNSET_VALUE
|
215
|
+
@disk_name = UNSET_VALUE
|
216
|
+
@disk_type = UNSET_VALUE
|
217
|
+
@metadata = {}
|
218
|
+
@name = UNSET_VALUE
|
219
|
+
@network = UNSET_VALUE
|
220
|
+
@network_project_id = UNSET_VALUE
|
221
|
+
@subnetwork = UNSET_VALUE
|
222
|
+
@tags = []
|
223
|
+
@labels = {}
|
224
|
+
@can_ip_forward = UNSET_VALUE
|
225
|
+
@external_ip = UNSET_VALUE
|
226
|
+
@network_ip = UNSET_VALUE
|
227
|
+
@use_private_ip = UNSET_VALUE
|
228
|
+
@autodelete_disk = UNSET_VALUE
|
229
|
+
@preemptible = UNSET_VALUE
|
230
|
+
@auto_restart = UNSET_VALUE
|
231
|
+
@on_host_maintenance = UNSET_VALUE
|
232
|
+
@instance_ready_timeout = UNSET_VALUE
|
233
|
+
@zone = UNSET_VALUE
|
234
|
+
@scopes = UNSET_VALUE
|
235
|
+
@service_accounts = UNSET_VALUE
|
236
|
+
@service_account = UNSET_VALUE
|
237
|
+
@additional_disks = []
|
238
|
+
@setup_winrm_password = UNSET_VALUE
|
239
|
+
@accelerators = []
|
240
|
+
@enable_secure_boot = UNSET_VALUE
|
241
|
+
@enable_vtpm = UNSET_VALUE
|
242
|
+
@enable_integrity_monitoring = UNSET_VALUE
|
213
243
|
|
214
244
|
# Internal state (prefix with __ so they aren't automatically
|
215
245
|
# merged)
|
@@ -275,12 +305,10 @@ module VagrantPlugins
|
|
275
305
|
result.instance_variable_set(:@__zone_config, new_zone_config)
|
276
306
|
|
277
307
|
# Merge in the metadata
|
278
|
-
result.metadata.merge
|
279
|
-
result.metadata.merge!(other.metadata)
|
308
|
+
result.metadata = self.metadata.merge(other.metadata)
|
280
309
|
|
281
310
|
# Merge in the labels
|
282
|
-
result.labels.merge
|
283
|
-
result.labels.merge!(other.labels)
|
311
|
+
result.labels = self.labels.merge(other.labels)
|
284
312
|
|
285
313
|
# Merge in the tags
|
286
314
|
result.tags |= self.tags
|
@@ -382,11 +410,23 @@ module VagrantPlugins
|
|
382
410
|
# Default IAM service account
|
383
411
|
@service_account = nil if @service_account == UNSET_VALUE
|
384
412
|
|
413
|
+
# Default Setup WinRM Password
|
414
|
+
@setup_winrm_password = nil if @setup_winrm_password == UNSET_VALUE
|
415
|
+
|
385
416
|
# Config option service_accounts is deprecated
|
386
417
|
if @service_accounts
|
387
418
|
@scopes = @service_accounts
|
388
419
|
end
|
389
420
|
|
421
|
+
# enable_secure_boot defaults to nil
|
422
|
+
@enable_secure_boot = false if @enable_secure_boot == UNSET_VALUE
|
423
|
+
|
424
|
+
# enable_vtpm defaults to nil
|
425
|
+
@enable_vtpm = false if @enable_vtpm == UNSET_VALUE
|
426
|
+
|
427
|
+
# enable_integrity_monitoring defaults to nil
|
428
|
+
@enable_integrity_monitoring = false if @enable_integrity_monitoring == UNSET_VALUE
|
429
|
+
|
390
430
|
# Compile our zone specific configurations only within
|
391
431
|
# NON-zone-SPECIFIC configurations.
|
392
432
|
unless @__zone_specific
|
@@ -444,6 +484,11 @@ module VagrantPlugins
|
|
444
484
|
|
445
485
|
errors << I18n.t("vagrant_google.config.image_required") if config.image.nil? && config.image_family.nil?
|
446
486
|
errors << I18n.t("vagrant_google.config.name_required") if @name.nil?
|
487
|
+
|
488
|
+
if !config.accelerators.empty?
|
489
|
+
errors << I18n.t("vagrant_google.config.on_host_maintenance_invalid_with_accelerators") unless \
|
490
|
+
config.on_host_maintenance == "TERMINATE"
|
491
|
+
end
|
447
492
|
end
|
448
493
|
|
449
494
|
if @service_accounts
|
data/locales/en.yml
CHANGED
@@ -14,8 +14,8 @@ en:
|
|
14
14
|
Instance is not created. Please run `vagrant up` first.
|
15
15
|
ready: |-
|
16
16
|
Machine is booted and ready for use!
|
17
|
-
|
18
|
-
Machine is ready for
|
17
|
+
ready_comm: |-
|
18
|
+
Machine is ready for Communicator access!
|
19
19
|
rsync_not_found_warning: |-
|
20
20
|
Warning! Folder sync disabled because the rsync binary is missing.
|
21
21
|
Make sure rsync is installed and the binary can be found in the PATH.
|
@@ -31,8 +31,8 @@ en:
|
|
31
31
|
Waiting for GCP operation '%{name}' to finish...
|
32
32
|
waiting_for_ready: |-
|
33
33
|
Waiting for instance to become "ready"...
|
34
|
-
|
35
|
-
Waiting for
|
34
|
+
waiting_for_comm: |-
|
35
|
+
Waiting for Communicator to become available...
|
36
36
|
warn_networks: |-
|
37
37
|
Warning! The Google provider doesn't support any of the Vagrant
|
38
38
|
high-level network configurations (`config.vm.network`). They
|
@@ -71,6 +71,9 @@ en:
|
|
71
71
|
"image" must be unset when setting "image_family"
|
72
72
|
service_accounts_deprecaated: |-
|
73
73
|
"service_accounts is deprecated. Please use scopes instead"
|
74
|
+
on_host_maintenance_invalid_with_accelerators: |-
|
75
|
+
"on_host_maintenance" option must be set to "TERMINATE" for instances
|
76
|
+
with accelerators
|
74
77
|
#-------------------------------------------------------------------------------
|
75
78
|
# Translations for exception classes
|
76
79
|
#-------------------------------------------------------------------------------
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
|
3
|
+
# Helper method to insert text after a line that matches the regex
|
4
|
+
def insert_after_line(file, insert, regex = /^## Next/)
|
5
|
+
tempfile = File.open("#{file}.tmp", "w")
|
6
|
+
f = File.new(file)
|
7
|
+
f.each do |line|
|
8
|
+
tempfile << line
|
9
|
+
next unless line =~ regex
|
10
|
+
|
11
|
+
tempfile << "\n"
|
12
|
+
tempfile << insert
|
13
|
+
tempfile << "\n"
|
14
|
+
end
|
15
|
+
f.close
|
16
|
+
tempfile.close
|
17
|
+
|
18
|
+
FileUtils.mv("#{file}.tmp", file)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Extracts all changes that have been made after the latest pushed tag
|
22
|
+
def changes_since_last_tag
|
23
|
+
`git --no-pager log $(git describe --tags --abbrev=0)..HEAD --grep="Merge" --pretty=format:"%t - %s%n%b%n"`
|
24
|
+
end
|
25
|
+
|
26
|
+
# Extracts all github users contributed since last tag
|
27
|
+
def users_since_last_tag
|
28
|
+
`git --no-pager log $(git describe --tags --abbrev=0)..HEAD --grep="Merge" --pretty=format:"%s" | cut -d' ' -f 6 | cut -d/ -f1 | sort | uniq`
|
29
|
+
end
|
30
|
+
|
31
|
+
namespace :changelog do
|
32
|
+
task :generate do
|
33
|
+
insert_after_line("CHANGELOG.md", changes_since_last_tag, /^## Next/)
|
34
|
+
printf("Users contributed since last release:\n")
|
35
|
+
contributors = users_since_last_tag.split("\n").map { |name| "@" + name }
|
36
|
+
printf("Huge thanks to all our contributors 🎆\n")
|
37
|
+
printf("Special thanks to: " + contributors.join(" ") + "\n")
|
38
|
+
printf("\nI'll merge this and release the gem once all tests pass.\n")
|
39
|
+
end
|
40
|
+
end
|
@@ -7,6 +7,8 @@ Vagrant.configure("2") do |config|
|
|
7
7
|
|
8
8
|
google.zone_config "australia-southeast1-b" do |zone|
|
9
9
|
zone.name = "vagrant-acceptance-preemptible-#{('a'..'z').to_a.sample(8).join}"
|
10
|
+
# Some images no longer fit into default 10GB disk size
|
11
|
+
zone.disk_size = 30
|
10
12
|
zone.disk_type = "pd-ssd"
|
11
13
|
zone.image_family = "centos-7"
|
12
14
|
end
|
@@ -30,26 +30,30 @@ describe VagrantPlugins::Google::Config do
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
its("name")
|
34
|
-
its("image")
|
35
|
-
its("image_family")
|
36
|
-
its("image_project_id")
|
37
|
-
its("instance_group")
|
38
|
-
its("zone")
|
39
|
-
its("network")
|
40
|
-
its("machine_type")
|
41
|
-
its("disk_size")
|
42
|
-
its("disk_name")
|
43
|
-
its("disk_type")
|
44
|
-
its("instance_ready_timeout")
|
45
|
-
its("metadata")
|
46
|
-
its("tags")
|
47
|
-
its("labels")
|
48
|
-
its("scopes")
|
49
|
-
its("additional_disks")
|
50
|
-
its("preemptible")
|
51
|
-
its("auto_restart")
|
52
|
-
its("on_host_maintenance")
|
33
|
+
its("name") { should match "i-[0-9]{10}-[0-9a-f]{4}" }
|
34
|
+
its("image") { should be_nil }
|
35
|
+
its("image_family") { should be_nil }
|
36
|
+
its("image_project_id") { should be_nil }
|
37
|
+
its("instance_group") { should be_nil }
|
38
|
+
its("zone") { should == "us-central1-f" }
|
39
|
+
its("network") { should == "default" }
|
40
|
+
its("machine_type") { should == "n1-standard-1" }
|
41
|
+
its("disk_size") { should == 10 }
|
42
|
+
its("disk_name") { should be_nil }
|
43
|
+
its("disk_type") { should == "pd-standard" }
|
44
|
+
its("instance_ready_timeout") { should == 20 }
|
45
|
+
its("metadata") { should == {} }
|
46
|
+
its("tags") { should == [] }
|
47
|
+
its("labels") { should == {} }
|
48
|
+
its("scopes") { should == nil }
|
49
|
+
its("additional_disks") { should == [] }
|
50
|
+
its("preemptible") { should be_falsey }
|
51
|
+
its("auto_restart") { should }
|
52
|
+
its("on_host_maintenance") { should == "MIGRATE" }
|
53
|
+
its("accelerators") { should == [] }
|
54
|
+
its("enable_secure_boot") { should be_falsey }
|
55
|
+
its("enable_vtpm") { should be_falsey }
|
56
|
+
its("enable_integrity_monitoring") { should be_falsey }
|
53
57
|
end
|
54
58
|
|
55
59
|
describe "overriding defaults" do
|
@@ -57,8 +61,28 @@ describe VagrantPlugins::Google::Config do
|
|
57
61
|
# simple boilerplate test, so I cut corners here. It just sets
|
58
62
|
# each of these attributes to "foo" in isolation, and reads the value
|
59
63
|
# and asserts the proper result comes back out.
|
60
|
-
[
|
61
|
-
|
64
|
+
[
|
65
|
+
:name,
|
66
|
+
:image,
|
67
|
+
:image_family,
|
68
|
+
:image_project_id,
|
69
|
+
:zone,
|
70
|
+
:instance_ready_timeout,
|
71
|
+
:machine_type,
|
72
|
+
:disk_size,
|
73
|
+
:disk_name,
|
74
|
+
:disk_type,
|
75
|
+
:network,
|
76
|
+
:network_project_id,
|
77
|
+
:metadata,
|
78
|
+
:labels,
|
79
|
+
:can_ip_forward,
|
80
|
+
:external_ip,
|
81
|
+
:autodelete_disk,
|
82
|
+
:enable_secure_boot,
|
83
|
+
:enable_vtpm,
|
84
|
+
:enable_integrity_monitoring,
|
85
|
+
].each do |attribute|
|
62
86
|
|
63
87
|
it "should not default #{attribute} if overridden" do
|
64
88
|
instance.send("#{attribute}=".to_sym, "foo")
|
@@ -89,6 +113,14 @@ describe VagrantPlugins::Google::Config do
|
|
89
113
|
errors = instance.validate("foo")["Google Provider"]
|
90
114
|
expect(errors).to include(/on_host_maintenance_invalid_on_preemptible/)
|
91
115
|
end
|
116
|
+
|
117
|
+
it "should raise error with accelerators and on_host_maintenance is not TERMINATE" do
|
118
|
+
instance.accelerators = [{ :type => "nvidia-tesla-k80" }]
|
119
|
+
instance.on_host_maintenance = "MIGRATE"
|
120
|
+
instance.finalize!
|
121
|
+
errors = instance.validate("foo")["Google Provider"]
|
122
|
+
expect(errors).to include(/on_host_maintenance_invalid_with_accelerators/)
|
123
|
+
end
|
92
124
|
end
|
93
125
|
|
94
126
|
describe "getting credentials from environment" do
|
@@ -128,6 +160,7 @@ describe VagrantPlugins::Google::Config do
|
|
128
160
|
let(:config_network) { "foo" }
|
129
161
|
let(:can_ip_forward) { true }
|
130
162
|
let(:external_ip) { "foo" }
|
163
|
+
let(:accelerators) { [{ :type => "foo" }] }
|
131
164
|
|
132
165
|
def set_test_values(instance)
|
133
166
|
instance.name = config_name
|
@@ -140,6 +173,7 @@ describe VagrantPlugins::Google::Config do
|
|
140
173
|
instance.zone = config_zone
|
141
174
|
instance.can_ip_forward = can_ip_forward
|
142
175
|
instance.external_ip = external_ip
|
176
|
+
instance.accelerators = accelerators
|
143
177
|
end
|
144
178
|
|
145
179
|
it "should raise an exception if not finalized" do
|
@@ -169,6 +203,7 @@ describe VagrantPlugins::Google::Config do
|
|
169
203
|
its("zone") { should == config_zone }
|
170
204
|
its("can_ip_forward") { should == can_ip_forward }
|
171
205
|
its("external_ip") { should == external_ip }
|
206
|
+
its("accelerators") { should == accelerators }
|
172
207
|
end
|
173
208
|
|
174
209
|
context "with a specific config set" do
|
@@ -197,6 +232,7 @@ describe VagrantPlugins::Google::Config do
|
|
197
232
|
its("zone") { should == zone_name }
|
198
233
|
its("can_ip_forward") { should == can_ip_forward }
|
199
234
|
its("external_ip") { should == external_ip }
|
235
|
+
its("accelerators") { should == accelerators }
|
200
236
|
end
|
201
237
|
|
202
238
|
describe "inheritance of parent config" do
|
@@ -231,47 +267,76 @@ describe VagrantPlugins::Google::Config do
|
|
231
267
|
end
|
232
268
|
|
233
269
|
describe "merging" do
|
234
|
-
let(:
|
235
|
-
let(:
|
270
|
+
let(:current) { described_class.new }
|
271
|
+
let(:other) { described_class.new }
|
272
|
+
|
273
|
+
subject { current.merge(other) }
|
236
274
|
|
237
275
|
it "should merge the metadata" do
|
238
|
-
|
239
|
-
|
276
|
+
current.metadata["one"] = "foo"
|
277
|
+
other.metadata["two"] = "bar"
|
240
278
|
|
241
|
-
|
242
|
-
expect(third.metadata).to eq({
|
279
|
+
expect(subject.metadata).to eq({
|
243
280
|
"one" => "foo",
|
244
281
|
"two" => "bar"
|
245
282
|
})
|
246
283
|
end
|
247
284
|
|
285
|
+
it "should merge the metadata and overwrite older values" do
|
286
|
+
current.metadata = {
|
287
|
+
"one" => "foo",
|
288
|
+
"name" => "current",
|
289
|
+
}
|
290
|
+
|
291
|
+
other.metadata = {
|
292
|
+
"two" => "bar",
|
293
|
+
"name" => "other",
|
294
|
+
}
|
295
|
+
|
296
|
+
expect(subject.metadata).to eq({
|
297
|
+
"one" => "foo",
|
298
|
+
"two" => "bar",
|
299
|
+
"name" => "other",
|
300
|
+
})
|
301
|
+
end
|
302
|
+
|
248
303
|
it "should merge the labels" do
|
249
|
-
|
250
|
-
|
304
|
+
current.labels["one"] = "one"
|
305
|
+
other.labels["two"] = "two"
|
251
306
|
|
252
|
-
|
253
|
-
expect(third.labels).to eq({
|
307
|
+
expect(subject.labels).to eq({
|
254
308
|
"one" => "one",
|
255
309
|
"two" => "two"
|
256
310
|
})
|
257
311
|
end
|
312
|
+
|
313
|
+
it "should merge the labels and overwrite older values" do
|
314
|
+
current.labels["one"] = "one"
|
315
|
+
current.labels["name"] = "current"
|
316
|
+
other.labels["two"] = "two"
|
317
|
+
other.labels["name"] = "other"
|
318
|
+
|
319
|
+
expect(subject.labels).to eq({
|
320
|
+
"one" => "one",
|
321
|
+
"two" => "two",
|
322
|
+
"name" => "other",
|
323
|
+
})
|
324
|
+
end
|
258
325
|
|
259
326
|
it "should merge the tags" do
|
260
|
-
|
261
|
-
|
327
|
+
current.tags = ["foo", "bar"]
|
328
|
+
other.tags = ["biz"]
|
262
329
|
|
263
|
-
|
264
|
-
expect(
|
265
|
-
expect(
|
266
|
-
expect(third.tags).to include("biz")
|
330
|
+
expect(subject.tags).to include("foo")
|
331
|
+
expect(subject.tags).to include("bar")
|
332
|
+
expect(subject.tags).to include("biz")
|
267
333
|
end
|
268
334
|
|
269
335
|
it "should merge the additional_disks" do
|
270
|
-
|
271
|
-
|
336
|
+
current.additional_disks = [{:one => "one"}]
|
337
|
+
other.additional_disks = [{:two => "two"}]
|
272
338
|
|
273
|
-
|
274
|
-
expect(third.additional_disks).to contain_exactly(
|
339
|
+
expect(subject.additional_disks).to contain_exactly(
|
275
340
|
{:one => "one"}, {:two => "two"}
|
276
341
|
)
|
277
342
|
end
|