gcloud 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/CHANGELOG.md +12 -0
- data/OVERVIEW.md +28 -0
- data/lib/gcloud.rb +46 -0
- data/lib/gcloud/bigquery.rb +15 -6
- data/lib/gcloud/bigquery/connection.rb +25 -12
- data/lib/gcloud/bigquery/table.rb +74 -7
- data/lib/gcloud/dns.rb +280 -0
- data/lib/gcloud/dns/change.rb +163 -0
- data/lib/gcloud/dns/change/list.rb +70 -0
- data/lib/gcloud/dns/connection.rb +164 -0
- data/lib/gcloud/dns/credentials.rb +29 -0
- data/lib/gcloud/dns/errors.rb +64 -0
- data/lib/gcloud/dns/importer.rb +195 -0
- data/lib/gcloud/dns/project.rb +291 -0
- data/lib/gcloud/dns/record.rb +152 -0
- data/lib/gcloud/dns/record/list.rb +92 -0
- data/lib/gcloud/dns/zone.rb +924 -0
- data/lib/gcloud/dns/zone/list.rb +75 -0
- data/lib/gcloud/dns/zone/transaction.rb +192 -0
- data/lib/gcloud/storage.rb +15 -6
- data/lib/gcloud/storage/bucket.rb +16 -7
- data/lib/gcloud/version.rb +1 -1
- metadata +29 -2
@@ -0,0 +1,163 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2015 Google Inc. All rights reserved.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
require "gcloud/dns/change/list"
|
17
|
+
require "time"
|
18
|
+
|
19
|
+
module Gcloud
|
20
|
+
module Dns
|
21
|
+
##
|
22
|
+
# = DNS Change
|
23
|
+
#
|
24
|
+
# Represents a request containing additions or deletions or records.
|
25
|
+
# Additions and deletions can be done in bulk, in a single atomic
|
26
|
+
# transaction, and take effect at the same time in each authoritative DNS
|
27
|
+
# server.
|
28
|
+
#
|
29
|
+
# require "gcloud"
|
30
|
+
#
|
31
|
+
# gcloud = Gcloud.new
|
32
|
+
# dns = gcloud.dns
|
33
|
+
# zone = dns.zone "example-com"
|
34
|
+
# zone.changes.each do |change|
|
35
|
+
# puts "Change includes #{change.additions.count} additions " \
|
36
|
+
# "and #{change.additions.count} deletions."
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
class Change
|
40
|
+
##
|
41
|
+
# The Zone object this Change belongs to.
|
42
|
+
attr_accessor :zone #:nodoc:
|
43
|
+
|
44
|
+
##
|
45
|
+
# The Google API Client object.
|
46
|
+
attr_accessor :gapi #:nodoc:
|
47
|
+
|
48
|
+
##
|
49
|
+
# Create an empty Change object.
|
50
|
+
def initialize #:nodoc:
|
51
|
+
@zone = nil
|
52
|
+
@gapi = {}
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# Unique identifier for the resource; defined by the server.
|
57
|
+
#
|
58
|
+
def id
|
59
|
+
@gapi["id"]
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# The records added in this change request.
|
64
|
+
#
|
65
|
+
def additions
|
66
|
+
Array(@gapi["additions"]).map { |gapi| Record.from_gapi gapi }
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# The records removed in this change request.
|
71
|
+
#
|
72
|
+
def deletions
|
73
|
+
Array(@gapi["deletions"]).map { |gapi| Record.from_gapi gapi }
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# Status of the operation. Values are +"done"+ and +"pending"+.
|
78
|
+
#
|
79
|
+
def status
|
80
|
+
@gapi["status"]
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
# Checks if the status is +"done"+.
|
85
|
+
def done?
|
86
|
+
return false if status.nil?
|
87
|
+
"done".casecmp(status).zero?
|
88
|
+
end
|
89
|
+
|
90
|
+
##
|
91
|
+
# Checks if the status is +"pending"+.
|
92
|
+
def pending?
|
93
|
+
return false if status.nil?
|
94
|
+
"pending".casecmp(status).zero?
|
95
|
+
end
|
96
|
+
|
97
|
+
##
|
98
|
+
# The time that this operation was started by the server.
|
99
|
+
#
|
100
|
+
def started_at
|
101
|
+
Time.parse @gapi["startTime"]
|
102
|
+
rescue
|
103
|
+
nil
|
104
|
+
end
|
105
|
+
|
106
|
+
##
|
107
|
+
# Reloads the change with updated status from the DNS service.
|
108
|
+
def reload!
|
109
|
+
ensure_connection!
|
110
|
+
resp = zone.connection.get_change @zone.id, id
|
111
|
+
if resp.success?
|
112
|
+
@gapi = resp.data
|
113
|
+
else
|
114
|
+
fail ApiError.from_response(resp)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
alias_method :refresh!, :reload!
|
118
|
+
|
119
|
+
##
|
120
|
+
# Refreshes the change until the status is +done+.
|
121
|
+
# The delay between refreshes will incrementally increase.
|
122
|
+
#
|
123
|
+
# === Example
|
124
|
+
#
|
125
|
+
# require "gcloud"
|
126
|
+
#
|
127
|
+
# gcloud = Gcloud.new
|
128
|
+
# dns = gcloud.dns
|
129
|
+
# zone = dns.zone "example-com"
|
130
|
+
# change = zone.change 1234567890
|
131
|
+
# change.done? #=> false
|
132
|
+
# change.wait_until_done!
|
133
|
+
# change.done? #=> true
|
134
|
+
#
|
135
|
+
def wait_until_done!
|
136
|
+
backoff = ->(retries) { sleep 2 * retries + 5 }
|
137
|
+
retries = 0
|
138
|
+
until done?
|
139
|
+
backoff.call retries
|
140
|
+
retries += 1
|
141
|
+
reload!
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
##
|
146
|
+
# New Change from a Google API Client object.
|
147
|
+
def self.from_gapi gapi, zone #:nodoc:
|
148
|
+
new.tap do |f|
|
149
|
+
f.gapi = gapi
|
150
|
+
f.zone = zone
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
protected
|
155
|
+
|
156
|
+
##
|
157
|
+
# Raise an error unless an active connection is available.
|
158
|
+
def ensure_connection!
|
159
|
+
fail "Must have active connection" unless zone && zone.connection
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2015 Google Inc. All rights reserved.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
module Gcloud
|
17
|
+
module Dns
|
18
|
+
class Change
|
19
|
+
##
|
20
|
+
# Change::List is a special case Array with additional values.
|
21
|
+
class List < DelegateClass(::Array)
|
22
|
+
##
|
23
|
+
# If not empty, indicates that there are more records that match
|
24
|
+
# the request and this value should be passed to continue.
|
25
|
+
attr_accessor :token
|
26
|
+
|
27
|
+
##
|
28
|
+
# Create a new Change::List with an array of Change instances.
|
29
|
+
def initialize arr = []
|
30
|
+
super arr
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Whether there a next page of zones.
|
35
|
+
def next?
|
36
|
+
!token.nil?
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Retrieve the next page of zones.
|
41
|
+
def next
|
42
|
+
return nil unless next?
|
43
|
+
ensure_zone!
|
44
|
+
@zone.changes token: token
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# New Changes::List from a response object.
|
49
|
+
def self.from_response resp, zone #:nodoc:
|
50
|
+
changes = new(Array(resp.data["changes"]).map do |gapi_object|
|
51
|
+
Change.from_gapi gapi_object, zone
|
52
|
+
end)
|
53
|
+
changes.instance_eval do
|
54
|
+
@token = resp.data["nextPageToken"]
|
55
|
+
@zone = zone
|
56
|
+
end
|
57
|
+
changes
|
58
|
+
end
|
59
|
+
|
60
|
+
protected
|
61
|
+
|
62
|
+
##
|
63
|
+
# Raise an error unless an active connection is available.
|
64
|
+
def ensure_zone!
|
65
|
+
fail "Must have active connection" unless @zone
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2015 Google Inc. All rights reserved.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
require "gcloud/version"
|
17
|
+
require "google/api_client"
|
18
|
+
|
19
|
+
module Gcloud
|
20
|
+
module Dns
|
21
|
+
##
|
22
|
+
# Represents the connection to DNS,
|
23
|
+
# as well as expose the API calls.
|
24
|
+
class Connection #:nodoc:
|
25
|
+
API_VERSION = "v1"
|
26
|
+
|
27
|
+
attr_accessor :project
|
28
|
+
attr_accessor :credentials #:nodoc:
|
29
|
+
|
30
|
+
##
|
31
|
+
# Creates a new Connection instance.
|
32
|
+
def initialize project, credentials #:nodoc:
|
33
|
+
@project = project
|
34
|
+
@credentials = credentials
|
35
|
+
@client = Google::APIClient.new application_name: "gcloud-ruby",
|
36
|
+
application_version: Gcloud::VERSION
|
37
|
+
@client.authorization = @credentials.client
|
38
|
+
@dns = @client.discovered_api "dns", API_VERSION
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_project project_id = @project
|
42
|
+
@client.execute(
|
43
|
+
api_method: @dns.projects.get,
|
44
|
+
parameters: { project: project_id }
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_zone zone_id
|
49
|
+
@client.execute(
|
50
|
+
api_method: @dns.managed_zones.get,
|
51
|
+
parameters: { project: @project, managedZone: zone_id }
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
def list_zones options = {}
|
56
|
+
params = { project: @project,
|
57
|
+
pageToken: options.delete(:token),
|
58
|
+
maxResults: options.delete(:max)
|
59
|
+
}.delete_if { |_, v| v.nil? }
|
60
|
+
|
61
|
+
@client.execute(
|
62
|
+
api_method: @dns.managed_zones.list,
|
63
|
+
parameters: params
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
def create_zone zone_name, zone_dns, options = {}
|
68
|
+
body = { kind: "dns#managedZone",
|
69
|
+
name: zone_name, dnsName: zone_dns,
|
70
|
+
description: (options[:description] || ""),
|
71
|
+
nameServerSet: options[:name_server_set]
|
72
|
+
}.delete_if { |_, v| v.nil? }
|
73
|
+
|
74
|
+
@client.execute(
|
75
|
+
api_method: @dns.managed_zones.create,
|
76
|
+
parameters: { project: @project },
|
77
|
+
body_object: body
|
78
|
+
)
|
79
|
+
end
|
80
|
+
|
81
|
+
def delete_zone zone_id
|
82
|
+
@client.execute(
|
83
|
+
api_method: @dns.managed_zones.delete,
|
84
|
+
parameters: { project: @project, managedZone: zone_id }
|
85
|
+
)
|
86
|
+
end
|
87
|
+
|
88
|
+
def get_change zone_id, change_id
|
89
|
+
@client.execute(
|
90
|
+
api_method: @dns.changes.get,
|
91
|
+
parameters: { project: @project, managedZone: zone_id,
|
92
|
+
changeId: change_id }
|
93
|
+
)
|
94
|
+
end
|
95
|
+
|
96
|
+
def list_changes zone_id, options = {}
|
97
|
+
params = { project: @project, managedZone: zone_id,
|
98
|
+
pageToken: options.delete(:token),
|
99
|
+
maxResults: options.delete(:max),
|
100
|
+
sortBy: options.delete(:sort),
|
101
|
+
sortOrder: options.delete(:order)
|
102
|
+
}.delete_if { |_, v| v.nil? }
|
103
|
+
|
104
|
+
@client.execute(
|
105
|
+
api_method: @dns.changes.list,
|
106
|
+
parameters: params
|
107
|
+
)
|
108
|
+
end
|
109
|
+
|
110
|
+
def create_change zone_id, additions, deletions
|
111
|
+
change = { "kind" => "dns#change",
|
112
|
+
"additions" => Array(additions),
|
113
|
+
"deletions" => Array(deletions) }
|
114
|
+
|
115
|
+
@client.execute(
|
116
|
+
api_method: @dns.changes.create,
|
117
|
+
parameters: { project: @project, managedZone: zone_id },
|
118
|
+
body_object: change
|
119
|
+
)
|
120
|
+
end
|
121
|
+
|
122
|
+
def list_records zone_id, options = {}
|
123
|
+
params = { project: @project, managedZone: zone_id,
|
124
|
+
pageToken: options.delete(:token),
|
125
|
+
maxResults: options.delete(:max),
|
126
|
+
name: options.delete(:name),
|
127
|
+
type: options.delete(:type)
|
128
|
+
}.delete_if { |_, v| v.nil? }
|
129
|
+
|
130
|
+
@client.execute(
|
131
|
+
api_method: @dns.resource_record_sets.list,
|
132
|
+
parameters: params
|
133
|
+
)
|
134
|
+
end
|
135
|
+
|
136
|
+
##
|
137
|
+
# Fully Qualified Domain Name
|
138
|
+
def self.fqdn name, origin_dns #:nodoc:
|
139
|
+
name = name.to_s.strip
|
140
|
+
return name if self.ip_addr? name
|
141
|
+
name = origin_dns if name.empty?
|
142
|
+
name = origin_dns if name == "@"
|
143
|
+
name = "#{name}.#{origin_dns}" unless name.include? "."
|
144
|
+
name = "#{name}." unless name.end_with? "."
|
145
|
+
name
|
146
|
+
end
|
147
|
+
|
148
|
+
require "ipaddr"
|
149
|
+
# Fix to make ip_addr? work on ruby 1.9
|
150
|
+
IPAddr::Error = ArgumentError unless defined? IPAddr::Error #:nodoc:
|
151
|
+
|
152
|
+
def self.ip_addr? name #:nodoc:
|
153
|
+
IPAddr.new name
|
154
|
+
true
|
155
|
+
rescue IPAddr::Error
|
156
|
+
false
|
157
|
+
end
|
158
|
+
|
159
|
+
def inspect #:nodoc:
|
160
|
+
"#{self.class}(#{@project})"
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2015 Google Inc. All rights reserved.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
require "gcloud/credentials"
|
17
|
+
|
18
|
+
module Gcloud
|
19
|
+
module Dns
|
20
|
+
##
|
21
|
+
# Represents the Oauth2 signing logic for DNS.
|
22
|
+
class Credentials < Gcloud::Credentials #:nodoc:
|
23
|
+
SCOPE = ["https://www.googleapis.com/auth/ndev.clouddns.readwrite"]
|
24
|
+
PATH_ENV_VARS = %w(DNS_KEYFILE GCLOUD_KEYFILE GOOGLE_CLOUD_KEYFILE)
|
25
|
+
JSON_ENV_VARS = %w(DNS_KEYFILE_JSON GCLOUD_KEYFILE_JSON
|
26
|
+
GOOGLE_CLOUD_KEYFILE_JSON)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2015 Google Inc. All rights reserved.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
require "gcloud/errors"
|
17
|
+
|
18
|
+
module Gcloud
|
19
|
+
module Dns
|
20
|
+
##
|
21
|
+
# Base DNS exception class.
|
22
|
+
class Error < Gcloud::Error
|
23
|
+
end
|
24
|
+
|
25
|
+
##
|
26
|
+
# Raised when an API call is not successful.
|
27
|
+
class ApiError < Error
|
28
|
+
##
|
29
|
+
# The code of the error.
|
30
|
+
attr_reader :code
|
31
|
+
|
32
|
+
##
|
33
|
+
# The errors encountered.
|
34
|
+
attr_reader :errors
|
35
|
+
|
36
|
+
def initialize message, code, errors = [] #:nodoc:
|
37
|
+
super message
|
38
|
+
@code = code
|
39
|
+
@errors = errors
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.from_response resp #:nodoc:
|
43
|
+
if resp.data? && resp.data["error"]
|
44
|
+
from_response_data resp.data["error"]
|
45
|
+
else
|
46
|
+
from_response_status resp
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.from_response_data error #:nodoc:
|
51
|
+
new error["message"], error["code"], error["errors"]
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.from_response_status resp #:nodoc:
|
55
|
+
if resp.status == 404
|
56
|
+
new "#{resp.error_message}: #{resp.request.uri.request_uri}",
|
57
|
+
resp.status
|
58
|
+
else
|
59
|
+
new resp.error_message, resp.status
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|