beaker-google 1.0.0 → 1.1.0

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: 58d4cd4a18e98fac54af847b0f0b3538359483700f9770cb4a222a4c588c4f6d
4
- data.tar.gz: 41fcc4aa6d3c4836e4a862807b0fe0ba91c0920995b0c96e9ce483f0d6cd792c
3
+ metadata.gz: 75a97e86c7f87f03623670307b3473519a9b0661137c217f6ce255bbb4cf7eb7
4
+ data.tar.gz: b5a2deec42679666ed39aa20e853c04e89d050f0f0dd37cb0511614dbf7b3a52
5
5
  SHA512:
6
- metadata.gz: 9149521d4525a55f1e35fff642109552028be22a6af77f1a7bfe0fd57fe5d196e00cb8969bbc09ad03a6557d0e5f3f661e8c04fd62e76b260204f2d73db5d0b0
7
- data.tar.gz: 75ce8eb08efd1f5f5776f20f79445327d0811bbb8dae79ee005cbcb7dfc17852ea84a4558b1bfd4040f41c563939b3fb0024e3eb2f8b93209930f5c9cdea1dc2
6
+ metadata.gz: 7294d81451483860acd2db28341cd434a3d4f68b5c4be7720b870260155da057626a768209a38fde29165dbf75a7c75b47ac4b8482a48ccd60348da19ec677c7
7
+ data.tar.gz: b5b818fda45a9baa3e83fb74596bb7fa7a11f7ae25dbe52234d3257565a88ba07b9ea956a3d3c4ee1f7fe62c7282e3377ce8f61b9d85326503635417f90240a1
@@ -1,8 +1,17 @@
1
1
  version: 2
2
2
  updates:
3
+ # raise PRs for gem updates
3
4
  - package-ecosystem: bundler
4
5
  directory: "/"
5
6
  schedule:
6
7
  interval: daily
7
8
  time: "13:00"
8
9
  open-pull-requests-limit: 10
10
+
11
+ # Maintain dependencies for GitHub Actions
12
+ - package-ecosystem: github-actions
13
+ directory: "/"
14
+ schedule:
15
+ interval: daily
16
+ time: "13:00"
17
+ open-pull-requests-limit: 10
@@ -11,7 +11,7 @@ jobs:
11
11
  # rubocop:
12
12
  # runs-on: ubuntu-latest
13
13
  # steps:
14
- # - uses: actions/checkout@v2
14
+ # - uses: actions/checkout@v4
15
15
  # - name: Install Ruby 3.1
16
16
  # uses: ruby/setup-ruby@v1
17
17
  # with:
@@ -33,7 +33,7 @@ jobs:
33
33
  COVERAGE: ${{ matrix.coverage }}
34
34
  name: Ruby ${{ matrix.ruby }}
35
35
  steps:
36
- - uses: actions/checkout@v2
36
+ - uses: actions/checkout@v4
37
37
  - name: Install Ruby ${{ matrix.ruby }}
38
38
  uses: ruby/setup-ruby@v1
39
39
  with:
@@ -38,11 +38,11 @@ jobs:
38
38
 
39
39
  steps:
40
40
  - name: Checkout repository
41
- uses: actions/checkout@v2
41
+ uses: actions/checkout@v4
42
42
 
43
43
  # Initializes the CodeQL tools for scanning.
44
44
  - name: Initialize CodeQL
45
- uses: github/codeql-action/init@v1
45
+ uses: github/codeql-action/init@v3
46
46
  with:
47
47
  languages: ${{ matrix.language }}
48
48
  # If you wish to specify custom queries, you can do so here or in a config file.
@@ -53,7 +53,7 @@ jobs:
53
53
  # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
54
54
  # If this step fails, then you should remove it and run the build manually (see below)
55
55
  - name: Autobuild
56
- uses: github/codeql-action/autobuild@v1
56
+ uses: github/codeql-action/autobuild@v3
57
57
 
58
58
  # ℹ️ Command-line programs to run using the OS shell.
59
59
  # 📚 https://git.io/JvXDl
@@ -67,4 +67,4 @@ jobs:
67
67
  # make release
68
68
 
69
69
  - name: Perform CodeQL Analysis
70
- uses: github/codeql-action/analyze@v1
70
+ uses: github/codeql-action/analyze@v3
@@ -10,7 +10,7 @@ jobs:
10
10
  runs-on: ubuntu-latest
11
11
  if: github.repository_owner == 'voxpupuli'
12
12
  steps:
13
- - uses: actions/checkout@v2
13
+ - uses: actions/checkout@v4
14
14
  - name: Install Ruby 3.1
15
15
  uses: ruby/setup-ruby@v1
16
16
  with:
data/CHANGELOG.md CHANGED
@@ -1,12 +1,35 @@
1
1
  # Changelog
2
2
 
3
- ## [1.0.0](https://github.com/voxpupuli/beaker-google/tree/1.0.0) (2022-10-31)
3
+ ## [1.1.0](https://github.com/voxpupuli/beaker-google/tree/1.1.0) (2024-05-21)
4
+
5
+ [Full Changelog](https://github.com/voxpupuli/beaker-google/compare/1.0.0...1.1.0)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - Move timestamp in firewall name to a different value [\#45](https://github.com/voxpupuli/beaker-google/issues/45)
10
+ - Add ability to configure the firewall [\#40](https://github.com/voxpupuli/beaker-google/pull/40) ([jaevans](https://github.com/jaevans))
11
+ - Add ability to set custom hostname [\#39](https://github.com/voxpupuli/beaker-google/pull/39) ([Andy-Adrian](https://github.com/Andy-Adrian))
12
+
13
+ **Closed issues:**
14
+
15
+ - Add ability to set custom hostname [\#38](https://github.com/voxpupuli/beaker-google/issues/38)
16
+ - network ports should be configurable [\#34](https://github.com/voxpupuli/beaker-google/issues/34)
17
+
18
+ **Merged pull requests:**
19
+
20
+ - Fix name conflicts [\#48](https://github.com/voxpupuli/beaker-google/pull/48) ([jaevans](https://github.com/jaevans))
21
+ - Bump actions/checkout from 2 to 4 [\#43](https://github.com/voxpupuli/beaker-google/pull/43) ([dependabot[bot]](https://github.com/apps/dependabot))
22
+ - Bump github/codeql-action from 1 to 2 [\#42](https://github.com/voxpupuli/beaker-google/pull/42) ([dependabot[bot]](https://github.com/apps/dependabot))
23
+ - dependabot: check for github actions and bundler [\#41](https://github.com/voxpupuli/beaker-google/pull/41) ([bastelfreak](https://github.com/bastelfreak))
24
+ - Update fakefs requirement from ~\> 1.8 to ~\> 2.4 [\#37](https://github.com/voxpupuli/beaker-google/pull/37) ([dependabot[bot]](https://github.com/apps/dependabot))
25
+
26
+ ## [1.0.0](https://github.com/voxpupuli/beaker-google/tree/1.0.0) (2022-11-02)
4
27
 
5
28
  [Full Changelog](https://github.com/voxpupuli/beaker-google/compare/0.5.0...1.0.0)
6
29
 
7
30
  **Fixed bugs:**
8
31
 
9
- - exec sysprep commands in child processes [\#31](https://github.com/voxpupuli/beaker-google/pull/31) ([AndyAdrian-OP](https://github.com/AndyAdrian-OP))
32
+ - exec sysprep commands in child processes [\#31](https://github.com/voxpupuli/beaker-google/pull/31) ([Andy-Adrian](https://github.com/Andy-Adrian))
10
33
 
11
34
  ## [0.5.0](https://github.com/voxpupuli/beaker-google/tree/0.5.0) (2022-10-04)
12
35
 
data/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  Beaker library to use the Google hypervisor
12
12
 
13
- # How to use this wizardry
13
+ # How to use this module
14
14
 
15
15
  This is a gem that allows you to use hosts with [Google Compute](https://cloud.google.com/compute) hypervisor with [Beaker](https://github.com/voxpupuli/beaker).
16
16
 
@@ -46,6 +46,7 @@ The behavior of this library can be configured using either the beaker host conf
46
46
  | gce_zone | true | | The zone to place compute instances in. The region is calculated from the zone name. |
47
47
  | gce_network | false | Default | The name of the network to attach to instances. If the project uses the default network, this and `gce_subnetwork` can be left empty. |
48
48
  | gce_subnetwork | false | Default | The name of the subnetwork to attach to the instances network interface. If the Default network is not used, this must be supplied. |
49
+ | gce_ports | false | `[ ]` | A comma separated list of ports to add to the external firewall. Each port is specified in the format `number/protocol` where protocol is one of `tcp`, `udp`, `icmp`, `esp`, `ah`, `ipip`, or `sctp`. **NOTE:** Port `22/tcp` is required for beaker to function and is automatically added to the firewall. |
49
50
  | gce_ssh_private_key | false | $HOME/.ssh/google_compute_engine | The file path of the private key to use to connect to instances. If using the key created by the gcloud tool, this can be left blank. |
50
51
  | gce_ssh_public_key | false | <gce_ssh_private_key>.pub | The file path of the public key to upload to the instance. If left blank, attempt to use the file at `gce_ssh_private_key` with a `.pub` extension. |
51
52
  | gce_machine_type | false | e2-standard-4 | The machine type to use for the instance. If the `BEAKER_gce_machine_type` environment variable is set, it will be used for all hosts. |
@@ -55,14 +56,24 @@ The behavior of this library can be configured using either the beaker host conf
55
56
 
56
57
  All the variables in the list can be set in the Beaker host configuration file, or the ones starting with `gce_` can be overridden by environment variables in the form `BEAKER_gce_...`. i.e. To override the `gce_machine_type` setting in the environment, set `BEAKER_gce_machine_type`.
57
58
 
59
+ ## Networking
60
+
61
+ Each run of beaker creates a pair of firewalls to protect the hosts, and internal host-to-host firewall, and an external firewall between the hosts and the internet.
62
+
63
+ The internal firewall allows all communication between hosts in the node set, while keeping them isolated from any other Beaker jobs that may be running in the same environment. This firewall is attached to all hosts in the test set, and allows all `tcp`, `udp`, and `icmp` traffic.
64
+
65
+ The external firewall allows outside communication from the internet into the hosts in the test. Due to constrains of the Beaker system, the firewall accepts any source IP (`0.0.0.0/0`) and the SSH port (`22/tcp`) is always allowed. Other ports may be added by using the `gce_ports` configuration option or the `BEAKER_gce_ports` environment variable as a comma separated list of `port/proto` values where `port` is the port number or range, and proto is one of `tcp`, `udp`, `icmp`, `esp`, `ah`, `ipip`, or `sctp`. The port number is only used for `tcp`, `udp`, and `sctp` protocols. Any value, such as `-1` can be used for the other protocols.
66
+
67
+ VM Instances created during this process will by default use the automatically-generated instance name as the hostname in the VM OS. Set the `BEAKER_set_gce_hostname` environment variable to `1` to override this behavior and configure the VM OS with the name defined in the nodeset as the hostname.
68
+
58
69
  # Cleanup
59
70
 
60
71
  In cases where the beaker process is killed before finishing, it may leave resources in GCP. These resources will need to be manually deleted.
61
72
 
62
73
  | Resource Type | Name Pattern | Count |
63
74
  | ------------- | ------------------- | ------------------------------------------- |
64
- | Firewall | `beaker-<number>-*` | 1 |
65
- | Instance | `beaker-*` | One or more depending on test configuration |
75
+ | Firewall | `beaker-<number>-*` | 2 |
76
+ | Instance | `beaker-<number>-*` | One or more depending on test configuration |
66
77
 
67
78
  # Contributing
68
79
 
@@ -22,7 +22,7 @@ Gem::Specification.new do |s|
22
22
  # Testing dependencies
23
23
  s.add_development_dependency 'rspec', '~> 3.0'
24
24
  s.add_development_dependency 'rspec-its'
25
- s.add_development_dependency 'fakefs', '~> 1.8'
25
+ s.add_development_dependency 'fakefs', '~> 2.4'
26
26
  s.add_development_dependency 'rake', '~> 13.0'
27
27
  s.add_development_dependency 'simplecov'
28
28
  s.add_development_dependency 'pry', '~> 0.10'
@@ -1,13 +1,10 @@
1
- require 'time'
1
+ require 'securerandom'
2
2
 
3
3
  module Beaker
4
4
  # Beaker support for the Google Compute Engine.
5
5
  class GoogleCompute < Beaker::Hypervisor
6
6
  SLEEPWAIT = 5
7
7
 
8
- # Hours before an instance is considered a zombie
9
- ZOMBIE = 3
10
-
11
8
  # Do some reasonable sleuthing on the SSH public key for GCE
12
9
 
13
10
  ##
@@ -79,27 +76,33 @@ module Beaker
79
76
  @options = options
80
77
  @logger = options[:logger]
81
78
  @hosts = google_hosts
82
- @firewall = ''
79
+ @external_firewall_name = ''
80
+ @internal_firewall_name = ''
83
81
  @gce_helper = GoogleComputeHelper.new(options)
84
82
  end
85
83
 
86
84
  # Create and configure virtual machines in the Google Compute Engine,
87
85
  # including their associated disks and firewall rules
88
86
  def provision
89
- start = Time.now
90
- test_group_identifier = "beaker-#{start.to_i}-"
87
+ test_group_identifier = "beaker-#{SecureRandom.hex(4)}"
91
88
 
92
89
  # set firewall to open pe ports
93
90
  network = @gce_helper.get_network
94
91
 
95
- @firewall = test_group_identifier + generate_host_name
92
+ @external_firewall_name = test_group_identifier + '-external'
96
93
 
97
- @gce_helper.create_firewall(@firewall, network)
94
+ # Always allow ssh from anywhere as it's needed for Beaker to run
95
+ @gce_helper.create_firewall(@external_firewall_name, network, allow: @options[:gce_ports] + ['22/tcp'], source_ranges: ['0.0.0.0/0'], target_tags: [test_group_identifier])
98
96
 
99
- @logger.debug("Created Google Compute firewall #{@firewall}")
97
+ @logger.debug("Created External Google Compute firewall #{@external_firewall_name}")
100
98
 
101
- @hosts.each do |host|
99
+ # Create a firewall that opens everything between all the hosts in this test group
100
+ @internal_firewall_name = test_group_identifier + '-internal'
101
+ internal_ports = ['1-65535/tcp', '1-65535/udp', '-1/icmp']
102
+ @gce_helper.create_firewall(@internal_firewall_name, network, allow: internal_ports, source_tags: [test_group_identifier], target_tags: [test_group_identifier])
103
+ @logger.debug("Created test group Google Compute firewall #{@internal_firewall_name}")
102
104
 
105
+ @hosts.each do |host|
103
106
  machine_type_name = ENV.fetch('BEAKER_gce_machine_type', host['gce_machine_type'])
104
107
  raise "Must provide a machine type name in 'gce_machine_type'." if machine_type_name.nil?
105
108
  # Get the GCE machine type object for this host
@@ -142,7 +145,7 @@ module Beaker
142
145
  raise('You must specify either :image or :family')
143
146
  end
144
147
 
145
- unique_host_id = test_group_identifier + generate_host_name
148
+ unique_host_id = test_group_identifier + '-' + generate_host_name
146
149
 
147
150
  boot_size = host['volume_size'] || img.disk_size_gb
148
151
 
@@ -155,13 +158,16 @@ module Beaker
155
158
  host['vmhostname'] = unique_host_id
156
159
 
157
160
  # add a new instance of the image
158
- operation = @gce_helper.create_instance(host['vmhostname'], img, machine_type, boot_size)
161
+ operation = @gce_helper.create_instance(host['vmhostname'], img, machine_type, boot_size, host.name)
159
162
  unless operation.error.nil?
160
163
  raise "Unable to create Google Compute Instance #{host.name}: [#{operation.error.errors[0].code}] #{operation.error.errors[0].message}"
161
164
  end
162
165
  @logger.debug("Created Google Compute instance for #{host.name}: #{host['vmhostname']}")
163
166
  instance = @gce_helper.get_instance(host['vmhostname'])
164
167
 
168
+ @gce_helper.add_instance_tag(host['vmhostname'], test_group_identifier)
169
+ @logger.debug("Added network tag #{test_group_identifier} to instance")
170
+
165
171
  # Make sure we have a non root/Adminsitor user to log in as
166
172
  if host['user'] == "root" || host['user'] == "Administrator" || host['user'].empty?
167
173
  initial_user = 'google_compute'
@@ -184,7 +190,7 @@ module Beaker
184
190
  value: 'FALSE'
185
191
  },
186
192
  ]
187
-
193
+
188
194
  # Check for google's default windows images and turn on ssh if found
189
195
  if image_project == "windows-cloud" || image_project == "windows-sql-cloud"
190
196
  # Turn on SSH on GCP's default windows images
@@ -210,9 +216,6 @@ module Beaker
210
216
 
211
217
  host['ip'] = instance.network_interfaces[0].access_configs[0].nat_ip
212
218
 
213
- # Add the new host to the firewall
214
- @gce_helper.add_firewall_tag(@firewall, host['vmhostname'])
215
-
216
219
  if host['disable_root_ssh'] == true
217
220
  @logger.info('Not enabling root ssh as disable_root_ssh is true')
218
221
  else
@@ -235,7 +238,8 @@ module Beaker
235
238
  # Shutdown and destroy virtual machines in the Google Compute Engine,
236
239
  # including their associated disks and firewall rules
237
240
  def cleanup
238
- @gce_helper.delete_firewall(@firewall)
241
+ @gce_helper.delete_firewall(@external_firewall_name)
242
+ @gce_helper.delete_firewall(@internal_firewall_name)
239
243
 
240
244
  @hosts.each do |host|
241
245
  # TODO: Delete any other disks attached during the instance creation
@@ -24,6 +24,8 @@ class Beaker::GoogleComputeHelper
24
24
  DEFAULT_MACHINE_TYPE = 'e2-standard-4'
25
25
  DEFAULT_NETWORK_NAME = 'default'
26
26
 
27
+ VALID_PROTOS = ['tcp', 'udp', 'icmp', 'esp', 'ah', 'ipip', 'sctp']
28
+
27
29
  GCP_AUTH_SCOPE = [
28
30
  Google::Apis::ComputeV1::AUTH_COMPUTE,
29
31
  Google::Apis::OsloginV1::AUTH_CLOUD_PLATFORM_READ_ONLY,
@@ -48,8 +50,18 @@ class Beaker::GoogleComputeHelper
48
50
  @options[:gce_network] = ENV.fetch('BEAKER_gce_network', DEFAULT_NETWORK_NAME)
49
51
  @options[:gce_subnetwork] = ENV.fetch('BEAKER_gce_subnetwork', nil)
50
52
 
53
+ @configure_ports = ENV.fetch('BEAKER_gce_ports', "").strip
54
+ # Split the ports based on commas, removing any empty values
55
+ @options[:gce_ports] = @configure_ports.split(/\s*?,\s*/).reject { |s| s.empty? }
56
+
51
57
  raise 'You must specify a gce_project for Google Compute Engine instances!' unless @options[:gce_project]
52
58
 
59
+ @options[:gce_ports].each do |port|
60
+ parts = port.split('/', 2)
61
+ raise "Invalid format for port #{port}. Should be 'port/proto'" unless parts.length == 2
62
+ proto = parts[1]
63
+ raise "Invalid value '#{proto}' for protocol in '#{port}'. Must be one of '#{VALID_PROTOS.join("', '")}'" unless VALID_PROTOS.include? proto
64
+ end
53
65
  authorizer = authenticate
54
66
  @compute = ::Google::Apis::ComputeV1::ComputeService.new
55
67
  @compute.authorization = authorizer
@@ -288,39 +300,131 @@ class Beaker::GoogleComputeHelper
288
300
  # @param [::Google::Apis::ComputeV1::Network] network The Google Compute networkin which to create
289
301
  # the firewall
290
302
  #
303
+ # @param [Array<String>] allow List of ports to allow through the firewall. One of 'allow' or 'deny' must be specified, but not both.
304
+ #
305
+ # @param [Array<String>] deny List of ports to deny through the firewall. One of 'allow' or 'deny' must be specified, but not both.
306
+ #
307
+ # @param [Array<String>] source_ranges List of ranges in CIDR format to accept through the firewall. If neither 'source_ranges'
308
+ # or 'source_tags' is specified, GCP adds a default 'source_range' of '0.0.0.0/0' (allow all)
309
+ #
310
+ # @param [Array<String>] source_tags List of network tags to accept through the firewall. If neither 'source_ranges'
311
+ # or 'source_tags' is specified, GCP adds a default 'source_range' of '0.0.0.0/0' (allow all)
312
+ #
313
+ # @param [Array<String>] target_ranges List of ranges in CIDR format to apply this firewall. If neither 'target_ranges'
314
+ # or 'target_tags' is specified, the firewall applies to all hosts in the VPC
315
+ #
316
+ # @param [Array<String>] target_tags List of network tags to apply this firewall. If neither 'target_ranges'
317
+ # or 'target_tags' is specified, the firewall applies to all hosts in the VPC
318
+ #
291
319
  # @return [Google::Apis::ComputeV1::Operation]
292
320
  #
293
321
  # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
294
322
  # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
295
323
  # @raise [Google::Apis::AuthorizationError] Authorization is required
296
- def create_firewall(name, network)
324
+ def create_firewall(name, network, allow: [], deny: [], source_ranges: [], source_tags: [], target_ranges: [], target_tags: [])
325
+ allowed = []
326
+ allow.each do |port|
327
+ parts = port.split('/', 2)
328
+ if parts[1] == 'tcp' || parts[1] == 'udp' || parts[1] == 'sctp' then
329
+ allowed << ::Google::Apis::ComputeV1::Firewall::Allowed.new(ip_protocol: parts[1], ports: [parts[0]])
330
+ else
331
+ allowed << ::Google::Apis::ComputeV1::Firewall::Allowed.new(ip_protocol: parts[1])
332
+ end
333
+ end
334
+ denied = []
335
+ deny.each do |port|
336
+ parts = port.split('/', 2)
337
+ if parts[1] == 'tcp' || parts[1] == 'udp' || parts[1] == 'sctp' then
338
+ denied << ::Google::Apis::ComputeV1::Firewall::Denied.new(ip_protocol: parts[1], ports: [parts[0]])
339
+ else
340
+ denied << ::Google::Apis::ComputeV1::Firewall::Denied.new(ip_protocol: parts[1])
341
+ end
342
+ end
343
+
297
344
  firewall_object = ::Google::Apis::ComputeV1::Firewall.new(
298
345
  name: name,
299
- allowed: [
300
- ::Google::Apis::ComputeV1::Firewall::Allowed.new(ip_protocol: 'tcp',
301
- ports: ['443', '8140', '61613', '8080', '8081', '22']),
302
- ],
346
+ direction: 'INGRESS',
303
347
  network: network.self_link,
304
- # TODO: Is there a better way to do this?
305
- sourceRanges: ['0.0.0.0/0'], # Allow from anywhere
348
+ allowed: allowed,
349
+ denied: denied,
350
+ source_ranges: source_ranges,
351
+ source_tags: source_tags,
352
+ target_ranges: target_ranges,
353
+ target_tags: target_tags,
306
354
  )
307
355
  operation = @compute.insert_firewall(@options[:gce_project], firewall_object)
308
356
  @compute.wait_global_operation(@options[:gce_project], operation.name)
309
357
  end
310
358
 
359
+ ##
360
+ # Get the named firewall
361
+ #
362
+ # @param [String] name The name of the firewall
363
+ #
364
+ # @return [Google::Apis::ComputeV1::Firewall]
365
+ #
366
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
367
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
368
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
369
+ def get_firewall(name)
370
+ firewall = @compute.get_firewall(@options[:gce_project], name)
371
+ end
372
+
373
+ ##
374
+ # Add a source range to the firewall.
375
+ #
376
+ # @param [String] name The name of the firewall
377
+ #
378
+ # @param [String] range The IP range in CIDR format to add to the firewall
379
+ #
380
+ # @return [Google::Apis::ComputeV1::Operation]
381
+ #
382
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
383
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
384
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
385
+ def add_firewall_source_range(name, range)
386
+ firewall = get_firewall(name)
387
+ firewall.source_ranges = [] if firewall.source_ranges.nil?
388
+ firewall.source_ranges << range
389
+ operation = @compute.patch_firewall(@options[:gce_project], name, firewall)
390
+ @compute.wait_global_operation(@options[:gce_project], operation.name)
391
+ end
392
+
393
+ ##
394
+ # Add an allowed port to the firewall
395
+ #
396
+ # @param [String] name The name of the firewall
397
+ #
398
+ # @param [String] port The port number to open on the firewall
399
+ #
400
+ # @param [String] proto The protocol of the port. This should be 'tcp' or 'udp'
401
+ #
402
+ # @return [Google::Apis::ComputeV1::Operation]
403
+ #
404
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
405
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
406
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
407
+ def add_firewall_port(name, port, proto)
408
+ firewall = get_firewall(name)
409
+ firewall.allowed = [] if firewall.allowed.nil?
410
+ firewall.allowed << ::Google::Apis::ComputeV1::Firewall::Allowed.new(ip_protocol: proto, ports: [port])
411
+ operation = @compute.patch_firewall(@options[:gce_project], name, firewall)
412
+ @compute.wait_global_operation(@options[:gce_project], operation.name)
413
+ end
414
+
311
415
  ##
312
416
  # Add a taget_tag to an existing firewall
313
417
  #
314
418
  # @param [String] the name of the firewall to update
315
419
  #
316
- # @ param [String] tag The tag to add to the firewall
420
+ # @param [String] tag The target tag to add to the firewall
317
421
  #
318
422
  # @return [Google::Apis::ComputeV1::Operation]
319
423
  #
320
424
  # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
321
425
  # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
322
426
  # @raise [Google::Apis::AuthorizationError] Authorization is required
323
- def add_firewall_tag(name, tag)
427
+ def add_firewall_target_tag(name, tag)
324
428
  firewall = @compute.get_firewall(@options[:gce_project], name)
325
429
  firewall.target_tags = [] if firewall.target_tags.nil?
326
430
  firewall.target_tags << tag
@@ -328,6 +432,26 @@ class Beaker::GoogleComputeHelper
328
432
  @compute.wait_global_operation(@options[:gce_project], operation.name)
329
433
  end
330
434
 
435
+ ##
436
+ # Add a source_tag to an existing firewall
437
+ #
438
+ # @param [String] the name of the firewall to update
439
+ #
440
+ # @param [String] tag The source tag to add to the firewall
441
+ #
442
+ # @return [Google::Apis::ComputeV1::Operation]
443
+ #
444
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
445
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
446
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
447
+ def add_firewall_source_tag(name, tag)
448
+ firewall = @compute.get_firewall(@options[:gce_project], name)
449
+ firewall.source_tags = [] if firewall.source_tags.nil?
450
+ firewall.source_tags << tag
451
+ operation = @compute.patch_firewall(@options[:gce_project], name, firewall)
452
+ @compute.wait_global_operation(@options[:gce_project], operation.name)
453
+ end
454
+
331
455
  ##
332
456
  # Create a Google Compute disk
333
457
  #
@@ -363,12 +487,14 @@ class Beaker::GoogleComputeHelper
363
487
  # @param [Integer] disk_size The size of the boot disk for the new instance. Must be equal to or
364
488
  # greater than the image disk's size
365
489
  #
490
+ # @param [String] hostname The custom hostname to set in the OS of the instance
491
+ #
366
492
  # @return [Google::Apis::ComputeV1::Operation]
367
493
  #
368
494
  # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
369
495
  # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
370
496
  # @raise [Google::Apis::AuthorizationError] Authorization is required
371
- def create_instance(name, img, machine_type, disk_size)
497
+ def create_instance(name, img, machine_type, disk_size, hostname)
372
498
  initialize_params = ::Google::Apis::ComputeV1::AttachedDiskInitializeParams.new(
373
499
  disk_size_gb: disk_size,
374
500
  source_image: img.self_link,
@@ -393,13 +519,24 @@ class Beaker::GoogleComputeHelper
393
519
  ),
394
520
  ],
395
521
  )
396
- new_instance = ::Google::Apis::ComputeV1::Instance.new(
397
- machine_type: machine_type.self_link,
398
- name: name,
399
- disks: [disk_params],
400
- network_interfaces: [network_interface],
401
- tags: tags,
402
- )
522
+
523
+ instance_opts = {
524
+ :machine_type => machine_type.self_link,
525
+ :name => name,
526
+ :disks => [disk_params],
527
+ :network_interfaces => [network_interface],
528
+ :tags => tags,
529
+ }
530
+
531
+ # use custom hostname if specified
532
+ if hostname && ENV.fetch('BEAKER_set_gce_hostname', false)
533
+ # The google api requires an FQDN for the custom hostname
534
+ hostname.include?('.') ? valid_hostname = hostname : valid_hostname = hostname + '.beaker.test'
535
+ instance_opts[:hostname] = valid_hostname
536
+ end
537
+
538
+ new_instance = ::Google::Apis::ComputeV1::Instance.new(instance_opts)
539
+
403
540
  operation = @compute.insert_instance(@options[:gce_project], @options[:gce_zone], new_instance)
404
541
  @compute.wait_zone_operation(@options[:gce_project], @options[:gce_zone], operation.name)
405
542
  end
@@ -418,6 +555,26 @@ class Beaker::GoogleComputeHelper
418
555
  @compute.get_instance(@options[:gce_project], @options[:gce_zone], name)
419
556
  end
420
557
 
558
+ ##
559
+ # Add a tag to a Google Compute Instance
560
+ #
561
+ # @param [String] name The name of the instance
562
+ #
563
+ # @param [String] tag The tag to add to the instance
564
+ #
565
+ # @return [Google::Apis::ComputeV1::Operation]
566
+ #
567
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
568
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
569
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
570
+ def add_instance_tag(name, tag)
571
+ instance = get_instance(name)
572
+ tags = instance.tags
573
+ tags.items << tag
574
+ operation = @compute.set_instance_tags(@options[:gce_project], @options[:gce_zone], name, tags)
575
+ @compute.wait_zone_operation(@options[:gce_project], @options[:gce_zone], operation.name)
576
+ end
577
+
421
578
  ##
422
579
  # Set key/value metadata pairs to a Google Compute instance
423
580
  #
@@ -1,3 +1,3 @@
1
1
  module BeakerGoogle
2
- VERSION = '1.0.0'
2
+ VERSION = '1.1.0'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beaker-google
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-11-02 00:00:00.000000000 Z
12
+ date: 2024-05-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -45,14 +45,14 @@ dependencies:
45
45
  requirements:
46
46
  - - "~>"
47
47
  - !ruby/object:Gem::Version
48
- version: '1.8'
48
+ version: '2.4'
49
49
  type: :development
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
53
  - - "~>"
54
54
  - !ruby/object:Gem::Version
55
- version: '1.8'
55
+ version: '2.4'
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: rake
58
58
  requirement: !ruby/object:Gem::Requirement
@@ -225,7 +225,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
225
225
  - !ruby/object:Gem::Version
226
226
  version: '0'
227
227
  requirements: []
228
- rubygems_version: 3.3.7
228
+ rubygems_version: 3.3.27
229
229
  signing_key:
230
230
  specification_version: 4
231
231
  summary: Beaker DSL Extension Helpers!