fog-google 1.3.3 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +1 -5
- data/.travis.yml +3 -0
- data/CHANGELOG.md +79 -0
- data/CONTRIBUTING.md +9 -10
- data/README.md +5 -5
- data/ci/README.md +5 -10
- data/ci/credentials.yml.template +28 -0
- data/ci/pipeline.yml +72 -11
- data/ci/tasks/run-int.sh +2 -1
- data/ci/tasks/run-int.yml +1 -0
- data/examples/create_instance.rb +4 -4
- data/examples/get_list_images.rb +1 -1
- data/examples/load-balance.rb +1 -1
- data/examples/metadata.rb +1 -1
- data/examples/network.rb +1 -1
- data/examples/storage_json.rb +1 -1
- data/fog-google.gemspec +3 -1
- data/lib/fog/compute/google.rb +2 -0
- data/lib/fog/compute/google/mock.rb +0 -19
- data/lib/fog/compute/google/models/disk.rb +12 -5
- data/lib/fog/compute/google/models/instance_group.rb +4 -0
- data/lib/fog/compute/google/models/network.rb +8 -2
- data/lib/fog/compute/google/models/server.rb +28 -4
- data/lib/fog/compute/google/models/servers.rb +1 -0
- data/lib/fog/compute/google/models/subnetworks.rb +1 -1
- data/lib/fog/compute/google/models/target_pool.rb +12 -1
- data/lib/fog/compute/google/requests/insert_disk.rb +12 -5
- data/lib/fog/compute/google/requests/insert_server.rb +6 -1
- data/lib/fog/compute/google/requests/insert_url_map.rb +12 -1
- data/lib/fog/compute/google/requests/set_server_metadata.rb +2 -0
- data/lib/fog/google/shared.rb +1 -2
- data/lib/fog/google/version.rb +1 -1
- data/lib/fog/storage/google_json/models/file.rb +31 -1
- data/lib/fog/storage/google_json/requests/put_object.rb +22 -12
- data/lib/fog/storage/google_xml/models/directory.rb +2 -3
- data/lib/fog/storage/google_xml/models/file.rb +2 -13
- data/lib/fog/storage/google_xml/requests/put_bucket.rb +1 -1
- data/lib/fog/storage/google_xml/requests/put_object.rb +1 -1
- data/lib/fog/storage/google_xml/requests/put_object_acl.rb +11 -2
- data/lib/fog/storage/google_xml/utils.rb +11 -0
- data/tasks/test.rake +63 -1
- data/test/integration/compute/addresses/addresses_shared.rb +1 -1
- data/test/integration/compute/test_compute_addresses_collection.rb +4 -3
- data/test/integration/compute/test_compute_networks_collection.rb +9 -6
- data/test/integration/compute/test_servers.rb +9 -0
- data/test/integration/compute/test_target_pools.rb +22 -0
- data/test/integration/factories/collection_factory.rb +1 -1
- data/test/integration/monitoring/test_timeseries.rb +78 -28
- data/test/integration/storage/test_files.rb +1 -1
- data/test/integration/storage/test_objects.rb +6 -0
- data/test/integration/test_authentication.rb +0 -18
- data/test/unit/compute/test_common_collections.rb +31 -0
- data/test/unit/compute/test_common_models.rb +36 -0
- metadata +39 -6
- data/ci/credentials.yml.tpl +0 -13
data/examples/get_list_images.rb
CHANGED
@@ -23,7 +23,7 @@ def test
|
|
23
23
|
|
24
24
|
puts "Fetching a single image from a global project..."
|
25
25
|
puts "------------------------------------------------"
|
26
|
-
img = connection.images.get("debian-8-jessie-
|
26
|
+
img = connection.images.get("debian-8-jessie-v20180329")
|
27
27
|
raise "Could not GET the image" unless img
|
28
28
|
puts img.inspect
|
29
29
|
|
data/examples/load-balance.rb
CHANGED
data/examples/metadata.rb
CHANGED
data/examples/network.rb
CHANGED
data/examples/storage_json.rb
CHANGED
@@ -15,7 +15,7 @@ def test
|
|
15
15
|
|
16
16
|
puts "Put a bucket..."
|
17
17
|
puts "----------------"
|
18
|
-
connection.put_bucket("fog-smoke-test",
|
18
|
+
connection.put_bucket("fog-smoke-test", predefined_acl: "publicReadWrite")
|
19
19
|
|
20
20
|
puts "Get the bucket..."
|
21
21
|
puts "-----------------"
|
data/fog-google.gemspec
CHANGED
@@ -25,14 +25,16 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_dependency "fog-xml"
|
26
26
|
|
27
27
|
# Hard Requirement as of 1.0
|
28
|
-
spec.add_dependency "google-api-client", "~> 0.
|
28
|
+
spec.add_dependency "google-api-client", "~> 0.23.0"
|
29
29
|
|
30
30
|
spec.add_development_dependency "coveralls"
|
31
31
|
spec.add_development_dependency "mime-types"
|
32
32
|
spec.add_development_dependency "minitest"
|
33
33
|
spec.add_development_dependency "osrcry"
|
34
34
|
spec.add_development_dependency "pry"
|
35
|
+
spec.add_development_dependency "pry-byebug"
|
35
36
|
spec.add_development_dependency "rake"
|
37
|
+
spec.add_development_dependency "retriable"
|
36
38
|
spec.add_development_dependency "rubocop"
|
37
39
|
spec.add_development_dependency "shindo"
|
38
40
|
spec.add_development_dependency "vcr"
|
data/lib/fog/compute/google.rb
CHANGED
@@ -26,8 +26,10 @@ module Fog
|
|
26
26
|
https://www.googleapis.com/auth/ndev.cloudman
|
27
27
|
https://www.googleapis.com/auth/cloud-platform).freeze
|
28
28
|
GOOGLE_COMPUTE_DEFAULT_NETWORK = "default".freeze
|
29
|
+
# TODO: Do we need those constants?
|
29
30
|
RUNNING = "RUNNING".freeze
|
30
31
|
PROVISIONING = "PROVISIONING".freeze
|
32
|
+
STAGING = "STAGING".freeze
|
31
33
|
|
32
34
|
request_path "fog/compute/google/requests"
|
33
35
|
request :add_backend_service_backends
|
@@ -181,25 +181,6 @@ module Fog
|
|
181
181
|
|
182
182
|
}
|
183
183
|
},
|
184
|
-
:backend_services => {
|
185
|
-
"test-backend-service" => {
|
186
|
-
"kind" => "compute#backend_service",
|
187
|
-
"id" => "1361932147851415729",
|
188
|
-
"creationTimestamp" => "2014-08-23T10:06:13.951-07:00",
|
189
|
-
"name" => "test-backend-service",
|
190
|
-
"description" => "",
|
191
|
-
"backends" => [
|
192
|
-
{
|
193
|
-
"description" => "",
|
194
|
-
"group" => "https://www.googleapis.com/resourceviews/v1beta1/projects#{@project}/zones/us-central1-a/zoneViews/name",
|
195
|
-
"balancingMode" => "RATE",
|
196
|
-
"capacityScaler" => 1.1,
|
197
|
-
"maxRate" => 0.5
|
198
|
-
}
|
199
|
-
],
|
200
|
-
"selfLink" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/global/backendServices/test-backend-service"
|
201
|
-
}
|
202
|
-
},
|
203
184
|
:servers => {
|
204
185
|
"fog-1" => {
|
205
186
|
"kind" => "compute#instance",
|
@@ -33,14 +33,21 @@ module Fog
|
|
33
33
|
|
34
34
|
options = {
|
35
35
|
:description => description || default_description,
|
36
|
-
:source_image => source_image,
|
37
|
-
:source_snapshot => source_snapshot,
|
38
|
-
:size_gb => size_gb,
|
39
36
|
:type => type,
|
40
|
-
:
|
37
|
+
:size_gb => size_gb,
|
38
|
+
:source_image => source_image,
|
39
|
+
:source_snapshot => source_snapshot
|
41
40
|
}
|
42
41
|
|
43
|
-
|
42
|
+
if options[:source_image]
|
43
|
+
unless source_image.include?("projects/")
|
44
|
+
options[:source_image] = service.images.get(source_image).self_link
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Request needs backward compatibility so source image is specified in
|
49
|
+
# method arguments
|
50
|
+
data = service.insert_disk(name, zone, options[:source_image], options)
|
44
51
|
operation = Fog::Compute::Google::Operations.new(:service => service)
|
45
52
|
.get(data.name, data.zone)
|
46
53
|
operation.wait_for { !pending? }
|
@@ -11,8 +11,10 @@ module Fog
|
|
11
11
|
attribute :auto_create_subnetworks, aliases => "autoCreateSubnetworks"
|
12
12
|
attribute :creation_timestamp, aliases => "creationTimestamp"
|
13
13
|
attribute :description
|
14
|
-
|
15
|
-
|
14
|
+
# TODO: Naming issue in the client lib, rename after this is resolved:
|
15
|
+
# https://github.com/google/google-api-ruby-client/issues/666
|
16
|
+
attribute :gateway_i_pv4, aliases => %w(gateway_ipv4 gatewayIPv4)
|
17
|
+
attribute :i_pv4_range, aliases => %w(ipv4_range IPv4Range)
|
16
18
|
attribute :id
|
17
19
|
attribute :kind
|
18
20
|
attribute :peerings
|
@@ -20,6 +22,10 @@ module Fog
|
|
20
22
|
attribute :self_link, aliases => "selfLink"
|
21
23
|
attribute :subnetworks
|
22
24
|
|
25
|
+
# TODO: Naming issue in the client lib, rename after this is resolved:
|
26
|
+
# https://github.com/google/google-api-ruby-client/issues/666
|
27
|
+
alias_method :ipv4_range, :i_pv4_range
|
28
|
+
|
23
29
|
def save
|
24
30
|
requires :identity, :ipv4_range
|
25
31
|
|
@@ -145,7 +145,7 @@ module Fog
|
|
145
145
|
attribute :tags
|
146
146
|
|
147
147
|
# @return [String]
|
148
|
-
attribute :zone
|
148
|
+
attribute :zone, :aliases => :zone_name
|
149
149
|
|
150
150
|
GCE_SCOPE_ALIASES = {
|
151
151
|
"default" => %w(
|
@@ -200,6 +200,14 @@ module Fog
|
|
200
200
|
operation
|
201
201
|
end
|
202
202
|
|
203
|
+
# Helper method that returns first public ip address
|
204
|
+
# for Fog::Compute::Server.ssh default behavior
|
205
|
+
#
|
206
|
+
# @return [String]
|
207
|
+
def public_ip_address
|
208
|
+
public_ip_addresses.first
|
209
|
+
end
|
210
|
+
|
203
211
|
def public_ip_addresses
|
204
212
|
addresses = []
|
205
213
|
if network_interfaces.respond_to? :flat_map
|
@@ -342,15 +350,25 @@ module Fog
|
|
342
350
|
reload
|
343
351
|
end
|
344
352
|
|
353
|
+
# Set an instance metadata
|
354
|
+
#
|
355
|
+
# @param [Bool] async Perform the operation asyncronously
|
356
|
+
# @param [Hash] new_metadata A new metadata object
|
357
|
+
# Format: {'foo' => 'bar', 'baz'=>'foo'}
|
358
|
+
#
|
359
|
+
# @returns [Fog::Compute::Google::Server] server object
|
345
360
|
def set_metadata(new_metadata = {}, async = true)
|
346
361
|
requires :identity, :zone
|
347
362
|
|
348
|
-
|
349
|
-
|
363
|
+
unless new_metadata.is_a?(Hash)
|
364
|
+
raise Fog::Errors::Error.new("Instance metadata should be a hash")
|
350
365
|
end
|
351
366
|
|
367
|
+
# If metadata is presented in {'foo' => 'bar', 'baz'=>'foo'}
|
368
|
+
new_metadata_items = new_metadata.each.map { |k, v| { :key => k.to_s, :value => v.to_s } }
|
369
|
+
|
352
370
|
data = service.set_server_metadata(
|
353
|
-
identity, zone_name, metadata[:fingerprint],
|
371
|
+
identity, zone_name, metadata[:fingerprint], new_metadata_items
|
354
372
|
)
|
355
373
|
operation = Fog::Compute::Google::Operations
|
356
374
|
.new(:service => service)
|
@@ -376,6 +394,12 @@ module Fog
|
|
376
394
|
status == PROVISIONING
|
377
395
|
end
|
378
396
|
|
397
|
+
# Check if instance is Staging. On staging vs. provisioning difference:
|
398
|
+
# https://cloud.google.com/compute/docs/instances/checking-instance-status
|
399
|
+
def staging?
|
400
|
+
status == STAGING
|
401
|
+
end
|
402
|
+
|
379
403
|
def ready?
|
380
404
|
status == RUNNING
|
381
405
|
end
|
@@ -15,7 +15,7 @@ module Fog
|
|
15
15
|
if region.nil?
|
16
16
|
data = []
|
17
17
|
service.list_aggregated_subnetworks(filters).to_h[:items].each_value do |region_obj|
|
18
|
-
data.concat(region_obj[
|
18
|
+
data.concat(region_obj[:subnetworks]) if region_obj[:subnetworks]
|
19
19
|
end
|
20
20
|
else
|
21
21
|
data = service.list_subnetworks(region, filters).to_h[:items]
|
@@ -97,6 +97,15 @@ module Fog
|
|
97
97
|
# behavior returns health checks for all instances associated with
|
98
98
|
# this check.
|
99
99
|
# @returns [Hash<String, Array<Hash>>] a map of instance URL to health checks
|
100
|
+
#
|
101
|
+
# Example Hash:
|
102
|
+
# {
|
103
|
+
# "https://www.googleapis.com/compute/v1/projects/myproject/zones/us-central1-f/instances/myinstance"=>
|
104
|
+
# [{:health_state=>"UNHEALTHY",
|
105
|
+
# :instance=>"https://www.googleapis.com/compute/v1/projects/myproject/zones/us-central1-f/instances/myinstance"
|
106
|
+
# }]
|
107
|
+
# }
|
108
|
+
#
|
100
109
|
def get_health(instance_name = nil)
|
101
110
|
requires :identity, :region
|
102
111
|
|
@@ -104,9 +113,11 @@ module Fog
|
|
104
113
|
instance = service.servers.get(instance_name)
|
105
114
|
data = service.get_target_pool_health(identity, region, instance.self_link)
|
106
115
|
.to_h[:health_status] || []
|
107
|
-
results = [instance.self_link, data]
|
116
|
+
results = [[instance.self_link, data]]
|
108
117
|
else
|
109
118
|
results = instances.map do |self_link|
|
119
|
+
# TODO: Improve the returned object, current is hard to navigate
|
120
|
+
# [{instance => @instance, health_state => "HEALTHY"}, ...]
|
110
121
|
data = service.get_target_pool_health(identity, region, self_link)
|
111
122
|
.to_h[:health_status] || []
|
112
123
|
[self_link, data]
|
@@ -13,24 +13,31 @@ module Fog
|
|
13
13
|
#
|
14
14
|
# @param disk_name [String] Name of the disk to create
|
15
15
|
# @param zone_name [String] Zone the disk reside in
|
16
|
-
# @param
|
16
|
+
# @param source_image [String] Optional self_link or family formatted url of the image to
|
17
|
+
# create the disk from, see https://cloud.google.com/compute/docs/reference/latest/disks/insert
|
17
18
|
# @param opts [Hash] Optional hash of options
|
18
19
|
# @option options [String] size_gb Number of GB to allocate to an empty disk
|
19
20
|
# @option options [String] source_snapshot Snapshot to create the disk from
|
20
21
|
# @option options [String] description Human friendly description of the disk
|
21
22
|
# @option options [String] type URL of the disk type resource describing which disk type to use
|
22
|
-
|
23
|
+
# TODO: change source_image to keyword argument in 2.0 and properly deprecate
|
24
|
+
def insert_disk(disk_name, zone, source_image = nil,
|
23
25
|
description: nil, type: nil, size_gb: nil,
|
24
26
|
source_snapshot: nil, **_opts)
|
27
|
+
|
28
|
+
if source_image && !source_image.include?("projects/")
|
29
|
+
raise ArgumentError.new("source_image needs to be self-link formatted or specify a family")
|
30
|
+
end
|
31
|
+
|
25
32
|
disk = ::Google::Apis::ComputeV1::Disk.new(
|
26
33
|
:name => disk_name,
|
27
34
|
:description => description,
|
28
35
|
:type => type,
|
29
36
|
:size_gb => size_gb,
|
30
|
-
:source_snapshot => source_snapshot
|
37
|
+
:source_snapshot => source_snapshot,
|
38
|
+
:source_image => source_image
|
31
39
|
)
|
32
|
-
@compute.insert_disk(@project, zone.split("/")[-1], disk
|
33
|
-
:source_image => image_name)
|
40
|
+
@compute.insert_disk(@project, zone.split("/")[-1], disk)
|
34
41
|
end
|
35
42
|
end
|
36
43
|
end
|
@@ -99,7 +99,12 @@ module Fog
|
|
99
99
|
end
|
100
100
|
|
101
101
|
if data[:tags]
|
102
|
-
|
102
|
+
if options[:tags].is_a?(Array)
|
103
|
+
# Process classic tag notation, i.e. ["fog"]
|
104
|
+
data[:tags] = ::Google::Apis::ComputeV1::Tags.new({ :items => options[:tags] })
|
105
|
+
else
|
106
|
+
data[:tags] = ::Google::Apis::ComputeV1::Tags.new(options[:tags])
|
107
|
+
end
|
103
108
|
end
|
104
109
|
|
105
110
|
instance = ::Google::Apis::ComputeV1::Instance.new(data)
|
@@ -16,7 +16,18 @@ module Fog
|
|
16
16
|
url_map_obj = ::Google::Apis::ComputeV1::UrlMap.new(
|
17
17
|
url_map.merge(:name => url_map_name)
|
18
18
|
)
|
19
|
-
|
19
|
+
# HACK: Currently URL map insert may fail even though the backend
|
20
|
+
# service operation is done. Retriable is not used to not add another
|
21
|
+
# runtime dependency.
|
22
|
+
# TODO: Remove after that has been corrected.
|
23
|
+
begin
|
24
|
+
retries ||= 0
|
25
|
+
@compute.insert_url_map(@project, url_map_obj)
|
26
|
+
rescue ::Google::Apis::ClientError
|
27
|
+
Fog::Logger.warning("URL map insert failed, retrying...")
|
28
|
+
sleep 10
|
29
|
+
retry if (retries += 1) < 2
|
30
|
+
end
|
20
31
|
end
|
21
32
|
end
|
22
33
|
end
|
@@ -18,6 +18,8 @@ module Fog
|
|
18
18
|
# instance.reload
|
19
19
|
# fingerprint = instance.metadata['fingerprint']
|
20
20
|
# @param [Hash] metadata A new metadata object
|
21
|
+
# Should have the following structure:
|
22
|
+
# {:items=>[{:key=>"foo", :value=>"bar"}, {:key=>"baz", :value=>"foo"}]}
|
21
23
|
#
|
22
24
|
# @returns [::Google::Apis::ComputeV1::Operation] set operation
|
23
25
|
def set_server_metadata(instance, zone, fingerprint, metadata_items = [])
|
data/lib/fog/google/shared.rb
CHANGED
@@ -42,12 +42,11 @@ module Fog
|
|
42
42
|
require "google/apis/compute_#{Fog::Compute::Google::GOOGLE_COMPUTE_API_VERSION}"
|
43
43
|
require "google/apis/dns_#{Fog::DNS::Google::GOOGLE_DNS_API_VERSION}"
|
44
44
|
require "google/apis/pubsub_#{Fog::Google::Pubsub::GOOGLE_PUBSUB_API_VERSION}"
|
45
|
-
require "google/apis/resourceviews_v1beta2"
|
46
45
|
require "google/apis/sqladmin_#{Fog::Google::SQL::GOOGLE_SQL_API_VERSION}"
|
47
46
|
require "google/apis/storage_#{Fog::Storage::GoogleJSON::GOOGLE_STORAGE_JSON_API_VERSION}"
|
48
47
|
require "googleauth"
|
49
48
|
rescue LoadError => error
|
50
|
-
Fog::
|
49
|
+
Fog::Errors::Error.new("Please install the google-api-client (>= 0.9) gem before using this provider")
|
51
50
|
raise error
|
52
51
|
end
|
53
52
|
|
data/lib/fog/google/version.rb
CHANGED
@@ -26,6 +26,24 @@ module Fog
|
|
26
26
|
|
27
27
|
# attribute :body
|
28
28
|
|
29
|
+
# https://cloud.google.com/storage/docs/access-control/lists#predefined-acls
|
30
|
+
VALID_PREDEFINED_ACLS = [
|
31
|
+
"authenticatedRead",
|
32
|
+
"bucketOwnerFullControl",
|
33
|
+
"bucketOwnerRead",
|
34
|
+
"private",
|
35
|
+
"projectPrivate",
|
36
|
+
"publicRead",
|
37
|
+
"publicReadWrite"
|
38
|
+
].freeze
|
39
|
+
|
40
|
+
def predefined_acl=(new_predefined_acl)
|
41
|
+
unless VALID_PREDEFINED_ACLS.include?(new_predefined_acl)
|
42
|
+
raise ArgumentError.new("acl must be one of [#{VALID_PREDEFINED_ACLS.join(', ')}]")
|
43
|
+
end
|
44
|
+
@predefined_acl = new_predefined_acl
|
45
|
+
end
|
46
|
+
|
29
47
|
def body
|
30
48
|
last_modified && (file = collection.get(identity)) ? attributes[:body] ||= file.body : attributes[:body] ||= ""
|
31
49
|
end
|
@@ -52,6 +70,17 @@ module Fog
|
|
52
70
|
false
|
53
71
|
end
|
54
72
|
|
73
|
+
def public=(new_public)
|
74
|
+
unless new_public.nil?
|
75
|
+
if new_public
|
76
|
+
@predefined_acl = "publicRead"
|
77
|
+
else
|
78
|
+
@predefined_acl = "projectPrivate"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
new_public
|
82
|
+
end
|
83
|
+
|
55
84
|
def public_url
|
56
85
|
requires :directory, :key
|
57
86
|
"https://storage.googleapis.com/#{directory.key}/#{key}"
|
@@ -60,7 +89,6 @@ module Fog
|
|
60
89
|
FILE_INSERTABLE_FIELDS = %i(
|
61
90
|
content_type
|
62
91
|
predefined_acl
|
63
|
-
acl
|
64
92
|
cache_control
|
65
93
|
content_disposition
|
66
94
|
content_encoding
|
@@ -74,6 +102,8 @@ module Fog
|
|
74
102
|
FILE_INSERTABLE_FIELDS.map { |k| [k, attributes[k]] }
|
75
103
|
.reject { |pair| pair[1].nil? }
|
76
104
|
]
|
105
|
+
|
106
|
+
options[:predefined_acl] ||= @predefined_acl
|
77
107
|
|
78
108
|
service.put_object(directory.key, key, body, options)
|
79
109
|
self.content_length = Fog::Storage.get_body_size(body)
|