fog-google 1.19.0 → 1.24.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/integration-compute-core.yml +54 -0
  3. data/.github/workflows/integration-compute-instance_groups.yml +55 -0
  4. data/.github/workflows/integration-compute-loadbalancing.yml +54 -0
  5. data/.github/workflows/integration-compute-networking.yml +53 -0
  6. data/.github/workflows/integration-monitoring.yml +54 -0
  7. data/.github/workflows/integration-pubsub.yml +54 -0
  8. data/.github/workflows/integration-sql.yml +54 -0
  9. data/.github/workflows/integration-storage.yml +55 -0
  10. data/.github/workflows/stale.yml +2 -2
  11. data/.github/workflows/unit.yml +7 -2
  12. data/.ruby-version +1 -0
  13. data/CHANGELOG.md +112 -0
  14. data/README.md +3 -3
  15. data/examples/create_instance.rb +1 -1
  16. data/examples/create_instance_and_attach_disk_later.rb +86 -0
  17. data/examples/create_instance_with_attached_disk.rb +1 -1
  18. data/examples/get_list_images.rb +1 -1
  19. data/examples/load-balance.rb +1 -1
  20. data/examples/metadata.rb +1 -1
  21. data/examples/network.rb +1 -1
  22. data/fog-google.gemspec +12 -10
  23. data/lib/fog/compute/google/models/addresses.rb +17 -8
  24. data/lib/fog/compute/google/models/disk_types.rb +17 -7
  25. data/lib/fog/compute/google/models/disks.rb +23 -8
  26. data/lib/fog/compute/google/models/firewalls.rb +11 -2
  27. data/lib/fog/compute/google/models/forwarding_rules.rb +16 -10
  28. data/lib/fog/compute/google/models/global_addresses.rb +11 -2
  29. data/lib/fog/compute/google/models/global_forwarding_rules.rb +11 -2
  30. data/lib/fog/compute/google/models/http_health_checks.rb +12 -3
  31. data/lib/fog/compute/google/models/images.rb +15 -8
  32. data/lib/fog/compute/google/models/instance_group_managers.rb +17 -9
  33. data/lib/fog/compute/google/models/instance_groups.rb +16 -8
  34. data/lib/fog/compute/google/models/instance_templates.rb +12 -3
  35. data/lib/fog/compute/google/models/machine_types.rb +17 -8
  36. data/lib/fog/compute/google/models/networks.rb +12 -3
  37. data/lib/fog/compute/google/models/operations.rb +22 -8
  38. data/lib/fog/compute/google/models/regions.rb +12 -3
  39. data/lib/fog/compute/google/models/routes.rb +12 -3
  40. data/lib/fog/compute/google/models/server.rb +4 -4
  41. data/lib/fog/compute/google/models/servers.rb +23 -9
  42. data/lib/fog/compute/google/models/ssl_certificates.rb +12 -3
  43. data/lib/fog/compute/google/models/subnetworks.rb +16 -8
  44. data/lib/fog/compute/google/models/target_http_proxies.rb +12 -3
  45. data/lib/fog/compute/google/models/target_https_proxies.rb +12 -3
  46. data/lib/fog/compute/google/models/target_instances.rb +16 -8
  47. data/lib/fog/compute/google/models/target_pools.rb +16 -8
  48. data/lib/fog/compute/google/models/url_maps.rb +12 -3
  49. data/lib/fog/compute/google/models/zones.rb +12 -3
  50. data/lib/fog/compute/google/requests/insert_server.rb +1 -1
  51. data/lib/fog/compute/google/requests/stop_server.rb +2 -2
  52. data/lib/fog/google/shared.rb +9 -8
  53. data/lib/fog/google/version.rb +1 -1
  54. data/lib/fog/storage/google_json/models/file.rb +7 -2
  55. data/lib/fog/storage/google_json/real.rb +16 -7
  56. data/lib/fog/storage/google_json/utils.rb +3 -4
  57. data/lib/fog/storage/google_json.rb +1 -1
  58. data/test/helpers/integration_test_helper.rb +3 -3
  59. data/test/integration/compute/core_compute/test_servers.rb +86 -0
  60. data/test/integration/monitoring/test_timeseries.rb +29 -14
  61. data/test/integration/storage/test_objects.rb +1 -0
  62. data/test/unit/compute/test_common_collections.rb +1 -1
  63. data/test/unit/compute/test_common_models.rb +1 -1
  64. data/test/unit/compute/test_disk.rb +26 -0
  65. data/test/unit/compute/test_server.rb +1 -1
  66. data/test/unit/dns/test_common_collections.rb +1 -1
  67. data/test/unit/monitoring/test_comon_collections.rb +1 -1
  68. data/test/unit/pubsub/test_common_collections.rb +1 -1
  69. data/test/unit/sql/test_common_collections.rb +1 -1
  70. data/test/unit/storage/test_common_json_collections.rb +1 -1
  71. data/test/unit/storage/test_common_xml_collections.rb +1 -1
  72. data/test/unit/storage/test_json_requests.rb +9 -1
  73. data/test/unit/storage/test_xml_requests.rb +1 -1
  74. metadata +63 -26
  75. data/.github/workflows/integration.yml +0 -225
@@ -4,9 +4,18 @@ module Fog
4
4
  class Regions < Fog::Collection
5
5
  model Fog::Compute::Google::Region
6
6
 
7
- def all
8
- data = service.list_regions.to_h
9
- load(data[:items] || [])
7
+ def all(opts = {})
8
+ items = []
9
+ next_page_token = nil
10
+ loop do
11
+ data = service.list_regions(**opts)
12
+ next_items = data.to_h[:items] || []
13
+ items.concat(next_items)
14
+ next_page_token = data.next_page_token
15
+ break if next_page_token.nil? || next_page_token.empty?
16
+ opts[:page_token] = next_page_token
17
+ end
18
+ load(items)
10
19
  end
11
20
 
12
21
  def get(identity)
@@ -4,9 +4,18 @@ module Fog
4
4
  class Routes < Fog::Collection
5
5
  model Fog::Compute::Google::Route
6
6
 
7
- def all
8
- data = service.list_routes.to_h
9
- load(data[:items] || [])
7
+ def all(opts = {})
8
+ items = []
9
+ next_page_token = nil
10
+ loop do
11
+ data = service.list_routes(**opts)
12
+ next_items = data.to_h[:items] || []
13
+ items.concat(next_items)
14
+ next_page_token = data.next_page_token
15
+ break if next_page_token.nil? || next_page_token.empty?
16
+ opts[:page_token] = next_page_token
17
+ end
18
+ load(items)
10
19
  end
11
20
 
12
21
  def get(identity)
@@ -27,7 +27,7 @@ module Fog
27
27
  # [
28
28
  # {
29
29
  # :initialize_params => {
30
- # :source_image => "projects/debian-cloud/global/images/family/debian-9"
30
+ # :source_image => "projects/debian-cloud/global/images/family/debian-11"
31
31
  # }
32
32
  # }
33
33
  # ]
@@ -279,7 +279,7 @@ module Fog
279
279
  if disk.is_a? Disk
280
280
  disk_obj = disk.get_attached_disk
281
281
  elsif disk.is_a? String
282
- disk_obj = service.disks.attached_disk_obj(disk, attached_disk_options)
282
+ disk_obj = service.disks.attached_disk_obj(disk, **attached_disk_options)
283
283
  end
284
284
 
285
285
  data = service.attach_disk(identity, zone_name, disk_obj)
@@ -339,10 +339,10 @@ module Fog
339
339
  operation
340
340
  end
341
341
 
342
- def stop(async = true)
342
+ def stop(async = true, discard_local_ssd=false)
343
343
  requires :identity, :zone
344
344
 
345
- data = service.stop_server(identity, zone_name)
345
+ data = service.stop_server(identity, zone_name, discard_local_ssd)
346
346
  operation = Fog::Compute::Google::Operations
347
347
  .new(:service => service)
348
348
  .get(data.name, data.zone)
@@ -13,17 +13,31 @@ module Fog
13
13
  :page_token => page_token
14
14
  }
15
15
 
16
- if zone
17
- data = service.list_servers(zone, **opts).to_h[:items] || []
18
- else
19
- data = []
20
- service.list_aggregated_servers(**opts).items.each_value do |scoped_lst|
21
- if scoped_lst && scoped_lst.instances
22
- data.concat(scoped_lst.instances.map(&:to_h))
16
+ items = []
17
+ next_page_token = nil
18
+
19
+ loop do
20
+ if zone
21
+ data = service.list_servers(zone, **opts)
22
+ next_items = data.to_h[:items] || []
23
+ items.concat(next_items)
24
+ next_page_token = data.next_page_token
25
+ else
26
+ data = service.list_aggregated_servers(**opts)
27
+ data.items.each_value do |scoped_lst|
28
+ if scoped_lst && scoped_lst.instances
29
+ items.concat(scoped_lst.instances.map(&:to_h))
30
+ end
23
31
  end
32
+ next_page_token = data.next_page_token
24
33
  end
34
+
35
+ break if next_page_token.nil? || next_page_token.empty?
36
+
37
+ opts[:page_token] = next_page_token
25
38
  end
26
- load(data)
39
+
40
+ load(items)
27
41
  end
28
42
 
29
43
  # TODO: This method needs to take self_links as well as names
@@ -50,7 +64,7 @@ module Fog
50
64
 
51
65
  if disks.nil? || disks.empty?
52
66
  # create the persistent boot disk
53
- source_img = service.images.get_from_family("debian-9")
67
+ source_img = service.images.get_from_family("debian-11")
54
68
  disk_defaults = {
55
69
  :name => name,
56
70
  :size_gb => 10,
@@ -14,9 +14,18 @@ module Fog
14
14
  nil
15
15
  end
16
16
 
17
- def all(_filters = {})
18
- data = service.list_ssl_certificates.to_h[:items] || []
19
- load(data)
17
+ def all(opts = {})
18
+ items = []
19
+ next_page_token = nil
20
+ loop do
21
+ data = service.list_ssl_certificates(**opts)
22
+ next_items = data.to_h[:items] || []
23
+ items.concat(next_items)
24
+ next_page_token = data.next_page_token
25
+ break if next_page_token.nil? || next_page_token.empty?
26
+ opts[:page_token] = next_page_token
27
+ end
28
+ load(items)
20
29
  end
21
30
  end
22
31
  end
@@ -11,16 +11,24 @@ module Fog
11
11
  :order_by => order_by,
12
12
  :page_token => page_token
13
13
  }
14
-
15
- if region
16
- data = service.list_subnetworks(region, **filters).to_h[:items] || []
17
- else
18
- data = []
19
- service.list_aggregated_subnetworks(**filters).to_h[:items].each_value do |region_obj|
20
- data.concat(region_obj[:subnetworks]) if region_obj[:subnetworks]
14
+ items = []
15
+ next_page_token = nil
16
+ loop do
17
+ if region
18
+ data = service.list_subnetworks(region, **filters)
19
+ next_items = data.items || []
20
+ items.concat(next_items)
21
+ next_page_token = data.next_page_token
22
+ else
23
+ data = service.list_aggregated_subnetworks(**filters)
24
+ data.items.each_value do |region_obj|
25
+ items.concat(region_obj.subnetworks) if region_obj && region_obj.subnetworks
26
+ end
21
27
  end
28
+ break if next_page_token.nil? || next_page_token.empty?
29
+ filters[:page_token] = next_page_token
22
30
  end
23
- load(data)
31
+ load(items.map(&:to_h))
24
32
  end
25
33
 
26
34
  def get(identity, region = nil)
@@ -4,9 +4,18 @@ module Fog
4
4
  class TargetHttpProxies < Fog::Collection
5
5
  model Fog::Compute::Google::TargetHttpProxy
6
6
 
7
- def all(_filters = {})
8
- data = service.list_target_http_proxies.to_h[:items] || []
9
- load(data)
7
+ def all(opts = {})
8
+ items = []
9
+ next_page_token = nil
10
+ loop do
11
+ data = service.list_target_http_proxies(*opts)
12
+ next_items = data.to_h[:items] || []
13
+ items.concat(next_items)
14
+ next_page_token = data.next_page_token
15
+ break if next_page_token.nil? || next_page_token.empty?
16
+ opts[:page_token] = next_page_token
17
+ end
18
+ load(items)
10
19
  end
11
20
 
12
21
  def get(identity)
@@ -4,9 +4,18 @@ module Fog
4
4
  class TargetHttpsProxies < Fog::Collection
5
5
  model Fog::Compute::Google::TargetHttpsProxy
6
6
 
7
- def all(_filters = {})
8
- data = service.list_target_https_proxies.to_h[:items] || []
9
- load(data)
7
+ def all(opts = {})
8
+ items = []
9
+ next_page_token = nil
10
+ loop do
11
+ data = service.list_target_https_proxies(**opts)
12
+ next_items = data.to_h[:items] || []
13
+ items.concat(next_items)
14
+ next_page_token = data.next_page_token
15
+ break if next_page_token.nil? || next_page_token.empty?
16
+ opts[:page_token] = next_page_token
17
+ end
18
+ load(items)
10
19
  end
11
20
 
12
21
  def get(identity)
@@ -13,17 +13,25 @@ module Fog
13
13
  :page_token => page_token
14
14
  }
15
15
 
16
- if zone
17
- data = service.list_target_instances(zone, **opts).to_h[:items] || []
18
- else
19
- data = []
20
- service.list_aggregated_target_instances(**opts).items.each_value do |scoped_list|
21
- unless scoped_list.nil? || scoped_list.target_instances.nil?
22
- data += scoped_list.target_instances.map(&:to_h)
16
+ items = []
17
+ next_page_token = nil
18
+ loop do
19
+ if zone
20
+ data = service.list_target_instances(zone, **opts)
21
+ next_items = data.to_h[:items] || []
22
+ items.concat(next_items)
23
+ next_page_token = data.next_page_token
24
+ else
25
+ data = service.list_aggregated_target_instances(**opts)
26
+ data.items.each_value do |scoped_list|
27
+ items.concat(scoped_list.target_instances.map(&:to_h)) if scoped_list && scoped_list.target_instances
23
28
  end
29
+ next_page_token = data.next_page_token
24
30
  end
31
+ break if next_page_token.nil? || next_page_token.empty?
32
+ opts[:page_token] = next_page_token
25
33
  end
26
- load(data)
34
+ load(items)
27
35
  end
28
36
 
29
37
  def get(identity, zone = nil)
@@ -11,17 +11,25 @@ module Fog
11
11
  :order_by => order_by,
12
12
  :page_token => page_token
13
13
  }
14
- if region.nil?
15
- data = []
16
- service.list_aggregated_target_pools(**opts).items.each_value do |lst|
17
- unless lst.nil? || lst.target_pools.nil?
18
- data += lst.to_h[:target_pools]
14
+ items = []
15
+ next_page_token = nil
16
+ loop do
17
+ if region.nil?
18
+ data = service.list_aggregated_target_pools(**opts)
19
+ data.items.each_value do |lst|
20
+ items.concat(lst.to_h[:target_pools]) if lst && lst.target_pools
19
21
  end
22
+ next_page_token = data.next_page_token
23
+ else
24
+ data = service.list_target_pools(region, **opts)
25
+ next_items = data.to_h[:items] || []
26
+ items.concat(next_items)
27
+ next_page_token = data.next_page_token
20
28
  end
21
- else
22
- data = service.list_target_pools(region, **opts).to_h[:items]
29
+ break if next_page_token.nil? || next_page_token.empty?
30
+ opts[:page_token] = next_page_token
23
31
  end
24
- load(data)
32
+ load(items)
25
33
  end
26
34
 
27
35
  def get(identity, region = nil)
@@ -4,9 +4,18 @@ module Fog
4
4
  class UrlMaps < Fog::Collection
5
5
  model Fog::Compute::Google::UrlMap
6
6
 
7
- def all
8
- data = service.list_url_maps.to_h[:items] || []
9
- load(data)
7
+ def all(opts = {})
8
+ items = []
9
+ next_page_token = nil
10
+ loop do
11
+ data = service.list_url_maps(**opts)
12
+ next_items = data.to_h[:items] || []
13
+ items.concat(next_items)
14
+ next_page_token = data.next_page_token
15
+ break if next_page_token.nil? || next_page_token.empty?
16
+ opts[:page_token] = next_page_token
17
+ end
18
+ load(items)
10
19
  end
11
20
 
12
21
  def get(identity)
@@ -4,9 +4,18 @@ module Fog
4
4
  class Zones < Fog::Collection
5
5
  model Fog::Compute::Google::Zone
6
6
 
7
- def all
8
- data = service.list_zones.to_h[:items] || []
9
- load(data)
7
+ def all(opts = {})
8
+ items = []
9
+ next_page_token = nil
10
+ loop do
11
+ data = service.list_zones
12
+ next_items = data.to_h[:items] || []
13
+ items.concat(next_items)
14
+ next_page_token = data.next_page_token
15
+ break if next_page_token.nil? || next_page_token.empty?
16
+ opts[:page_token] = next_page_token
17
+ end
18
+ load(items)
10
19
  end
11
20
 
12
21
  def get(identity)
@@ -52,7 +52,7 @@ module Fog
52
52
  # :disks => [
53
53
  # {
54
54
  # :initialize_params => {
55
- # :source_image => "projects/debian-cloud/global/images/family/debian-9"
55
+ # :source_image => "projects/debian-cloud/global/images/family/debian-11"
56
56
  # }
57
57
  # }
58
58
  # ]
@@ -10,8 +10,8 @@ module Fog
10
10
  end
11
11
 
12
12
  class Real
13
- def stop_server(identity, zone)
14
- @compute.stop_instance(@project, zone.split("/")[-1], identity)
13
+ def stop_server(identity, zone, discard_local_ssd=false)
14
+ @compute.stop_instance(@project, zone.split("/")[-1], identity, discard_local_ssd: discard_local_ssd)
15
15
  end
16
16
  end
17
17
  end
@@ -67,20 +67,21 @@ module Fog
67
67
  ::Google::Apis.logger.level = ::Logger::DEBUG
68
68
  end
69
69
 
70
- auth = nil
70
+ initialize_auth(options).tap do |auth|
71
+ ::Google::Apis::RequestOptions.default.authorization = auth
72
+ end
73
+ end
71
74
 
75
+ def initialize_auth(options)
72
76
  if options[:google_json_key_location] || options[:google_json_key_string]
73
- auth = process_key_auth(options)
77
+ process_key_auth(options)
74
78
  elsif options[:google_auth]
75
- auth = options[:google_auth]
79
+ options[:google_auth]
76
80
  elsif options[:google_application_default]
77
- auth = process_application_default_auth(options)
81
+ process_application_default_auth(options)
78
82
  else
79
- auth = process_fallback_auth(options)
83
+ process_fallback_auth(options)
80
84
  end
81
-
82
- ::Google::Apis::RequestOptions.default.authorization = auth
83
- auth
84
85
  end
85
86
 
86
87
  ##
@@ -1,5 +1,5 @@
1
1
  module Fog
2
2
  module Google
3
- VERSION = "1.19.0".freeze
3
+ VERSION = "1.24.1".freeze
4
4
  end
5
5
  end
@@ -5,6 +5,7 @@ module Fog
5
5
  identity :key, :aliases => ["Key", :name]
6
6
 
7
7
  attribute :acl
8
+ attribute :uniform
8
9
  attribute :predefined_acl, :aliases => ["predefinedAcl", :predefined_acl]
9
10
  attribute :cache_control, :aliases => ["cacheControl", :cache_control]
10
11
  attribute :content_disposition, :aliases => ["contentDisposition", :content_disposition]
@@ -37,6 +38,10 @@ module Fog
37
38
  "publicReadWrite"
38
39
  ].freeze
39
40
 
41
+ def uniform=(enable)
42
+ @uniform=enable
43
+ end
44
+
40
45
  def predefined_acl=(new_predefined_acl)
41
46
  unless VALID_PREDEFINED_ACLS.include?(new_predefined_acl)
42
47
  raise ArgumentError.new("acl must be one of [#{VALID_PREDEFINED_ACLS.join(', ')}]")
@@ -111,8 +116,8 @@ module Fog
111
116
  FILE_INSERTABLE_FIELDS.map { |k| [k, attributes[k]] }
112
117
  .reject { |pair| pair[1].nil? }
113
118
  ]
114
-
115
- options[:predefined_acl] ||= @predefined_acl
119
+
120
+ options[:predefined_acl] ||= @predefined_acl unless @uniform
116
121
 
117
122
  service.put_object(directory.key, key, body, **options)
118
123
  self.content_length = Fog::Storage.get_body_size(body)
@@ -10,16 +10,12 @@ module Fog
10
10
 
11
11
  def initialize(options = {})
12
12
  shared_initialize(options[:google_project], GOOGLE_STORAGE_JSON_API_VERSION, GOOGLE_STORAGE_JSON_BASE_URL)
13
+ @options = options.dup
13
14
  options[:google_api_scope_url] = GOOGLE_STORAGE_JSON_API_SCOPE_URLS.join(" ")
14
15
  @host = options[:host] || "storage.googleapis.com"
15
16
 
16
17
  # TODO(temikus): Do we even need this client?
17
18
  @client = initialize_google_client(options)
18
- # IAM client used for SignBlob API
19
- @iam_service = ::Google::Apis::IamcredentialsV1::IAMCredentialsService.new
20
- apply_client_options(@iam_service, {
21
- google_api_scope_url: GOOGLE_STORAGE_JSON_IAM_API_SCOPE_URLS.join(" ")
22
- })
23
19
 
24
20
  @storage_json = ::Google::Apis::StorageV1::StorageService.new
25
21
  apply_client_options(@storage_json, options)
@@ -135,11 +131,24 @@ DATA
135
131
  # See https://cloud.google.com/storage/docs/access-control/signed-urls-v2
136
132
  # @return [String] Signature binary blob
137
133
  def default_signer(string_to_sign)
138
- key = OpenSSL::PKey::RSA.new(@storage_json.authorization.signing_key)
134
+ key = @storage_json.authorization.signing_key
135
+ key = OpenSSL::PKey::RSA.new(@storage_json.authorization.signing_key) unless key.respond_to?(:sign)
139
136
  digest = OpenSSL::Digest::SHA256.new
140
137
  return key.sign(digest, string_to_sign)
141
138
  end
142
139
 
140
+ # IAM client used for SignBlob API.
141
+ # Lazily initialize this since it requires another authorization request.
142
+ def iam_service
143
+ return @iam_service if defined?(@iam_service)
144
+
145
+ @iam_service = ::Google::Apis::IamcredentialsV1::IAMCredentialsService.new
146
+ apply_client_options(@iam_service, @options)
147
+ iam_options = @options.merge(google_api_scope_url: GOOGLE_STORAGE_JSON_IAM_API_SCOPE_URLS.join(" "))
148
+ @iam_service.authorization = initialize_auth(iam_options)
149
+ @iam_service
150
+ end
151
+
143
152
  ##
144
153
  # Fallback URL signer using the IAM SignServiceAccountBlob API, see
145
154
  # Google::Apis::IamcredentialsV1::IAMCredentialsService#sign_service_account_blob
@@ -161,7 +170,7 @@ DATA
161
170
  )
162
171
 
163
172
  resource = "projects/-/serviceAccounts/#{google_access_id}"
164
- response = @iam_service.sign_service_account_blob(resource, request)
173
+ response = iam_service.sign_service_account_blob(resource, request)
165
174
 
166
175
  return response.signed_blob
167
176
  end
@@ -1,3 +1,5 @@
1
+ require 'addressable'
2
+
1
3
  module Fog
2
4
  module Storage
3
5
  class GoogleJSON
@@ -19,10 +21,7 @@ module Fog
19
21
 
20
22
  def host_path_query(params, expires)
21
23
  params[:headers]["Date"] = expires.to_i
22
- # implementation from CGI.escape, but without ' ' to '+' conversion
23
- params[:path] = params[:path].b.gsub(/([^a-zA-Z0-9_.\-~]+)/) { |m|
24
- '%' + m.unpack('H2' * m.bytesize).join('%').upcase
25
- }.gsub("%2F", "/")
24
+ params[:path] = ::Addressable::URI.encode_component(params[:path], ::Addressable::URI::CharacterClasses::PATH)
26
25
 
27
26
  query = []
28
27
 
@@ -29,7 +29,7 @@ module Fog
29
29
 
30
30
  # Version of IAM API used for blob signing, see Fog::Storage::GoogleJSON::Real#iam_signer
31
31
  GOOGLE_STORAGE_JSON_IAM_API_VERSION = "v1".freeze
32
- GOOGLE_STORAGE_JSON_IAM_API_SCOPE_URLS = %w(https://www.googleapis.com/auth/devstorage.full_control).freeze
32
+ GOOGLE_STORAGE_JSON_IAM_API_SCOPE_URLS = %w(https://www.googleapis.com/auth/iam).freeze
33
33
 
34
34
  # TODO: Come up with a way to only request a subset of permissions.
35
35
  # https://cloud.google.com/storage/docs/json_api/v1/how-tos/authorizing
@@ -17,9 +17,9 @@ TEST_ZONE = "us-central1-f".freeze
17
17
  TEST_REGION = "us-central1".freeze
18
18
  TEST_SIZE_GB = 10
19
19
  TEST_MACHINE_TYPE = "n1-standard-1".freeze
20
- TEST_IMAGE = "debian-9-stretch-v20180611".freeze
20
+ TEST_IMAGE = "debian-11-bullseye-v20220920".freeze
21
21
  TEST_IMAGE_PROJECT = "debian-cloud".freeze
22
- TEST_IMAGE_FAMILY = "debian-9".freeze
22
+ TEST_IMAGE_FAMILY = "debian-11".freeze
23
23
 
24
24
  # XXX This depends on a public image in gs://fog-test-bucket; there may be a better way to do this
25
25
  # The image was created like so: https://cloud.google.com/compute/docs/images/export-image
@@ -93,7 +93,7 @@ KEY
93
93
  RETRIABLE_TRIES = 3
94
94
  RETRIABLE_BASE_INTERVAL = 50
95
95
 
96
- class FogIntegrationTest < MiniTest::Test
96
+ class FogIntegrationTest < Minitest::Test
97
97
  def namespaced_name
98
98
  "#{self.class}_#{name}"
99
99
  end
@@ -132,6 +132,92 @@ class TestServers < FogIntegrationTest
132
132
  assert server.ready?
133
133
  end
134
134
 
135
+ def test_start_stop_discard_local_ssd
136
+ server = @factory.create
137
+
138
+ async = true
139
+ discard_local_ssd = true
140
+
141
+ server.stop(async, discard_local_ssd)
142
+ server.wait_for { stopped? }
143
+
144
+ assert server.stopped?
145
+ end
146
+
147
+ def test_attach_disk
148
+ # Creating server
149
+ server = @factory.create
150
+ server.wait_for { ready? }
151
+
152
+ disk_name = "fog-test-1-testservers-test-attach-disk-attachable" # suffix forces disk name to differ from the existing disk
153
+ # Creating disk #{disk_name}
154
+ disk = @disks.create(
155
+ :name => disk_name,
156
+ :source_image => TEST_IMAGE,
157
+ :size_gb => 64
158
+ )
159
+ device_name = "#{disk.name}-device"
160
+
161
+ # Attaching disk #{disk.name} as device #{device_name}
162
+ self_link = "https://www.googleapis.com/compute/v1/projects/#{TEST_PROJECT}/zones/#{TEST_ZONE}/disks/#{disk.name}"
163
+ server.attach_disk(self_link, true, device_name: device_name)
164
+
165
+ # Waiting for attachment
166
+ disk.wait_for { ! users.nil? && users != []}
167
+
168
+ assert_equal "https://www.googleapis.com/compute/v1/projects/#{TEST_PROJECT}/zones/#{TEST_ZONE}/instances/#{server.name}", disk.users[0]
169
+
170
+ server.reload
171
+ server_attached_disk = server.disks.select{|d| d[:boot] == false}[0]
172
+ assert_equal device_name, server_attached_disk[:device_name]
173
+ end
174
+
175
+ def test_detach_disk
176
+ # Creating server
177
+ server = @factory.create
178
+ server.wait_for { ready? }
179
+
180
+ disk_name = "fog-test-1-testservers-test-detach-attachable" # suffix forces disk name to differ from the existing disk
181
+ # Creating disk #{disk_name}
182
+ disk = @disks.create(
183
+ :name => disk_name,
184
+ :source_image => TEST_IMAGE,
185
+ :size_gb => 64
186
+ )
187
+ device_name = "#{disk.name}-device"
188
+
189
+ # Attaching disk #{disk.name} as device #{device_name}
190
+ self_link = "https://www.googleapis.com/compute/v1/projects/#{TEST_PROJECT}/zones/#{TEST_ZONE}/disks/#{disk.name}"
191
+ server.attach_disk(self_link, true, device_name: device_name)
192
+ disk.wait_for { ! users.nil? && users != []}
193
+
194
+ server.reload
195
+ server_attached_disk = server.disks.select{|d| d[:boot] == false}[0]
196
+ assert_equal device_name, server_attached_disk[:device_name]
197
+
198
+ # Detaching (synchronous) disk #{disk.name}
199
+ server.detach_disk(device_name, false)
200
+
201
+ disk.reload
202
+ assert disk.users.nil? || disk.users == []
203
+
204
+ # Re-attaching disk #{disk.name} as device #{device_name}
205
+ server.attach_disk(self_link, true, device_name: device_name)
206
+ disk.wait_for { ! users.nil? && users != []}
207
+
208
+ server.reload
209
+ server_attached_disk = server.disks.select{|d| d[:boot] == false}[0]
210
+ assert_equal device_name, server_attached_disk[:device_name]
211
+
212
+ # Detaching (async) disk #{disk.name}
213
+ server.detach_disk(device_name, true)
214
+
215
+ # Waiting for detachment
216
+ disk.wait_for { users.nil? || users == []}
217
+
218
+ assert disk.users.nil? || disk.users == []
219
+ end
220
+
135
221
  def test_reset_windows_password
136
222
  win_disk = @disks.create(
137
223
  :name => "fog-test-1-testservers-test-reset-windows-password-2",