gcloud 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG.md +21 -0
  3. data/lib/gcloud.rb +0 -5
  4. data/lib/gcloud/bigquery.rb +31 -62
  5. data/lib/gcloud/bigquery/connection.rb +58 -35
  6. data/lib/gcloud/bigquery/dataset.rb +147 -18
  7. data/lib/gcloud/bigquery/dataset/access.rb +477 -0
  8. data/lib/gcloud/bigquery/dataset/list.rb +1 -1
  9. data/lib/gcloud/bigquery/errors.rb +2 -0
  10. data/lib/gcloud/bigquery/job.rb +30 -6
  11. data/lib/gcloud/bigquery/job/list.rb +1 -1
  12. data/lib/gcloud/bigquery/project.rb +47 -8
  13. data/lib/gcloud/bigquery/query_job.rb +1 -5
  14. data/lib/gcloud/bigquery/table.rb +185 -47
  15. data/lib/gcloud/bigquery/table/list.rb +1 -1
  16. data/lib/gcloud/bigquery/table/schema.rb +252 -0
  17. data/lib/gcloud/bigquery/view.rb +25 -0
  18. data/lib/gcloud/datastore/connection.rb +4 -0
  19. data/lib/gcloud/datastore/dataset.rb +5 -2
  20. data/lib/gcloud/datastore/errors.rb +1 -1
  21. data/lib/gcloud/datastore/properties.rb +1 -0
  22. data/lib/gcloud/datastore/proto.rb +3 -0
  23. data/lib/gcloud/errors.rb +23 -0
  24. data/lib/gcloud/gce.rb +62 -0
  25. data/lib/gcloud/pubsub/connection.rb +4 -0
  26. data/lib/gcloud/pubsub/errors.rb +2 -0
  27. data/lib/gcloud/pubsub/project.rb +5 -3
  28. data/lib/gcloud/pubsub/subscription/list.rb +1 -1
  29. data/lib/gcloud/pubsub/topic.rb +1 -1
  30. data/lib/gcloud/pubsub/topic/list.rb +1 -1
  31. data/lib/gcloud/storage.rb +16 -0
  32. data/lib/gcloud/storage/bucket.rb +31 -1
  33. data/lib/gcloud/storage/bucket/acl.rb +12 -10
  34. data/lib/gcloud/storage/bucket/list.rb +1 -1
  35. data/lib/gcloud/storage/connection.rb +4 -0
  36. data/lib/gcloud/storage/errors.rb +2 -0
  37. data/lib/gcloud/storage/file.rb +13 -0
  38. data/lib/gcloud/storage/file/acl.rb +6 -5
  39. data/lib/gcloud/storage/file/list.rb +1 -1
  40. data/lib/gcloud/storage/project.rb +4 -2
  41. data/lib/gcloud/version.rb +1 -1
  42. metadata +6 -2
@@ -38,7 +38,7 @@ module Gcloud
38
38
 
39
39
  ##
40
40
  # New Table::List from a response object.
41
- def self.from_resp resp, conn #:nodoc:
41
+ def self.from_response resp, conn #:nodoc:
42
42
  tables = List.new(Array(resp.data["tables"]).map do |gapi_object|
43
43
  Table.from_gapi gapi_object, conn
44
44
  end)
@@ -0,0 +1,252 @@
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 Bigquery
18
+ class Table
19
+ ##
20
+ # = Table Schema
21
+ #
22
+ # A builder for BigQuery table schemas, passed to block arguments to
23
+ # Dataset#create_table and Table#schema. Supports nested and
24
+ # repeated fields via a nested block. For more information about BigQuery
25
+ # schema definitions, see {Preparing Data for BigQuery
26
+ # }[https://cloud.google.com/bigquery/preparing-data-for-bigquery].
27
+ #
28
+ # require "gcloud"
29
+ #
30
+ # gcloud = Gcloud.new
31
+ # bigquery = gcloud.bigquery
32
+ # dataset = bigquery.dataset "my_dataset"
33
+ # table = dataset.create_table "my_table"
34
+ #
35
+ # table.schema do |schema|
36
+ # schema.string "first_name", mode: :required
37
+ # schema.record "cities_lived", mode: :repeated do |cities_lived|
38
+ # cities_lived.string "place", mode: :required
39
+ # cities_lived.integer "number_of_years", mode: :required
40
+ # end
41
+ # end
42
+ #
43
+ class Schema
44
+ MODES = %w( NULLABLE REQUIRED REPEATED ) #:nodoc:
45
+ TYPES = %w( STRING INTEGER FLOAT BOOLEAN TIMESTAMP RECORD ) #:nodoc:
46
+
47
+ attr_reader :fields #:nodoc:
48
+
49
+ ##
50
+ # Initializes a new schema object with an existing schema.
51
+ def initialize schema = nil, nested = false #:nodoc:
52
+ fields = (schema && schema["fields"]) || []
53
+ @original_fields = fields.dup
54
+ @fields = fields.dup
55
+ @nested = nested
56
+ end
57
+
58
+ def changed? #:nodoc:
59
+ @original_fields != @fields
60
+ end
61
+
62
+ ##
63
+ # Returns the schema as hash containing the keys and values specified by
64
+ # the Google Cloud BigQuery {Rest API
65
+ # }[https://cloud.google.com/bigquery/docs/reference/v2/tables#resource]
66
+ # .
67
+ def schema #:nodoc:
68
+ {
69
+ "fields" => @fields
70
+ }
71
+ end
72
+
73
+ ##
74
+ # Adds a string field to the schema.
75
+ #
76
+ # === Parameters
77
+ #
78
+ # +name+::
79
+ # The field name. The name must contain only letters (a-z, A-Z),
80
+ # numbers (0-9), or underscores (_), and must start with a letter or
81
+ # underscore. The maximum length is 128 characters. (+String+)
82
+ # +options+::
83
+ # An optional Hash for controlling additional behavior. (+Hash+)
84
+ # <code>options[:description]</code>::
85
+ # A description of the field. (+String+)
86
+ # <code>options[:mode]</code>::
87
+ # The field's mode. The possible values are +:nullable+, +:required+,
88
+ # and +:repeated+. The default value is +:nullable+. (+Symbol+)
89
+ def string name, options = {}
90
+ add_field name, :string, nil, options
91
+ end
92
+
93
+ ##
94
+ # Adds an integer field to the schema.
95
+ #
96
+ # === Parameters
97
+ #
98
+ # +name+::
99
+ # The field name. The name must contain only letters (a-z, A-Z),
100
+ # numbers (0-9), or underscores (_), and must start with a letter or
101
+ # underscore. The maximum length is 128 characters. (+String+)
102
+ # +options+::
103
+ # An optional Hash for controlling additional behavior. (+Hash+)
104
+ # <code>options[:description]</code>::
105
+ # A description of the field. (+String+)
106
+ # <code>options[:mode]</code>::
107
+ # The field's mode. The possible values are +:nullable+, +:required+,
108
+ # and +:repeated+. The default value is +:nullable+. (+Symbol+)
109
+ def integer name, options = {}
110
+ add_field name, :integer, nil, options
111
+ end
112
+
113
+ ##
114
+ # Adds a floating-point number field to the schema.
115
+ #
116
+ # === Parameters
117
+ #
118
+ # +name+::
119
+ # The field name. The name must contain only letters (a-z, A-Z),
120
+ # numbers (0-9), or underscores (_), and must start with a letter or
121
+ # underscore. The maximum length is 128 characters. (+String+)
122
+ # +options+::
123
+ # An optional Hash for controlling additional behavior. (+Hash+)
124
+ # <code>options[:description]</code>::
125
+ # A description of the field. (+String+)
126
+ # <code>options[:mode]</code>::
127
+ # The field's mode. The possible values are +:nullable+, +:required+,
128
+ # and +:repeated+. The default value is +:nullable+. (+Symbol+)
129
+ def float name, options = {}
130
+ add_field name, :float, nil, options
131
+ end
132
+
133
+ ##
134
+ # Adds a boolean field to the schema.
135
+ #
136
+ # === Parameters
137
+ #
138
+ # +name+::
139
+ # The field name. The name must contain only letters (a-z, A-Z),
140
+ # numbers (0-9), or underscores (_), and must start with a letter or
141
+ # underscore. The maximum length is 128 characters. (+String+)
142
+ # +options+::
143
+ # An optional Hash for controlling additional behavior. (+Hash+)
144
+ # <code>options[:description]</code>::
145
+ # A description of the field. (+String+)
146
+ # <code>options[:mode]</code>::
147
+ # The field's mode. The possible values are +:nullable+, +:required+,
148
+ # and +:repeated+. The default value is +:nullable+. (+Symbol+)
149
+ def boolean name, options = {}
150
+ add_field name, :boolean, nil, options
151
+ end
152
+
153
+ ##
154
+ # Adds a timestamp field to the schema.
155
+ #
156
+ # === Parameters
157
+ #
158
+ # +name+::
159
+ # The field name. The name must contain only letters (a-z, A-Z),
160
+ # numbers (0-9), or underscores (_), and must start with a letter or
161
+ # underscore. The maximum length is 128 characters. (+String+)
162
+ # +options+::
163
+ # An optional Hash for controlling additional behavior. (+Hash+)
164
+ # <code>options[:description]</code>::
165
+ # A description of the field. (+String+)
166
+ # <code>options[:mode]</code>::
167
+ # The field's mode. The possible values are +:nullable+, +:required+,
168
+ # and +:repeated+. The default value is +:nullable+. (+Symbol+)
169
+ def timestamp name, options = {}
170
+ add_field name, :timestamp, nil, options
171
+ end
172
+
173
+ ##
174
+ # Adds a record field to the schema. A block must be passed describing
175
+ # the nested fields of the record. For more information about nested
176
+ # and repeated records, see {Preparing Data for BigQuery
177
+ # }[https://cloud.google.com/bigquery/preparing-data-for-bigquery].
178
+ #
179
+ # === Parameters
180
+ #
181
+ # +name+::
182
+ # The field name. The name must contain only letters (a-z, A-Z),
183
+ # numbers (0-9), or underscores (_), and must start with a letter or
184
+ # underscore. The maximum length is 128 characters. (+String+)
185
+ # +options+::
186
+ # An optional Hash for controlling additional behavior. (+Hash+)
187
+ # <code>options[:description]</code>::
188
+ # A description of the field. (+String+)
189
+ # <code>options[:mode]</code>::
190
+ # The field's mode. The possible values are +:nullable+, +:required+,
191
+ # and +:repeated+. The default value is +:nullable+. (+Symbol+)
192
+ #
193
+ # === Example
194
+ #
195
+ # require "gcloud"
196
+ #
197
+ # gcloud = Gcloud.new
198
+ # bigquery = gcloud.bigquery
199
+ # dataset = bigquery.dataset "my_dataset"
200
+ # table = dataset.create_table "my_table"
201
+ #
202
+ # table.schema do |schema|
203
+ # schema.string "first_name", mode: :required
204
+ # schema.record "cities_lived", mode: :repeated do |cities_lived|
205
+ # cities_lived.string "place", mode: :required
206
+ # cities_lived.integer "number_of_years", mode: :required
207
+ # end
208
+ # end
209
+ #
210
+ def record name, options = {}
211
+ fail ArgumentError, "nested RECORD type is not permitted" if @nested
212
+ fail ArgumentError, "a block is required" unless block_given?
213
+ nested_schema = self.class.new nil, true
214
+ yield nested_schema
215
+ add_field name, :record, nested_schema.fields, options
216
+ end
217
+
218
+ protected
219
+
220
+ def upcase_type type
221
+ upcase_type = type.to_s.upcase
222
+ unless TYPES.include? upcase_type
223
+ fail ArgumentError,
224
+ "Type '#{upcase_type}' not found in #{TYPES.inspect}"
225
+ end
226
+ upcase_type
227
+ end
228
+
229
+ def upcase_mode mode
230
+ upcase_mode = mode.to_s.upcase
231
+ unless MODES.include? upcase_mode
232
+ fail ArgumentError "Unable to determine mode for '#{mode}'"
233
+ end
234
+ upcase_mode
235
+ end
236
+
237
+ def add_field name, type, nested_fields, options
238
+ # Remove any existing field of this name
239
+ @fields.reject! { |h| h["name"] == name }
240
+ field = {
241
+ "name" => name,
242
+ "type" => upcase_type(type)
243
+ }
244
+ field["mode"] = upcase_mode(options[:mode]) if options[:mode]
245
+ field["description"] =options[:description] if options[:description]
246
+ field["fields"] = nested_fields if nested_fields
247
+ @fields << field
248
+ end
249
+ end
250
+ end
251
+ end
252
+ end
@@ -83,6 +83,15 @@ module Gcloud
83
83
  @gapi["tableReference"]["projectId"]
84
84
  end
85
85
 
86
+ ##
87
+ # The gapi fragment containing the Project ID, Dataset ID, and Table ID as
88
+ # a camel-cased hash.
89
+ def table_ref #:nodoc:
90
+ table_ref = @gapi["tableReference"]
91
+ table_ref = table_ref.to_hash if table_ref.respond_to? :to_hash
92
+ table_ref
93
+ end
94
+
86
95
  ##
87
96
  # The name of the table.
88
97
  #
@@ -367,6 +376,22 @@ module Gcloud
367
376
  end
368
377
  end
369
378
 
379
+ ##
380
+ # Reloads the table with current data from the BigQuery service.
381
+ #
382
+ # :category: Lifecycle
383
+ #
384
+ def reload!
385
+ ensure_connection!
386
+ resp = connection.get_table dataset_id, table_id
387
+ if resp.success?
388
+ @gapi = resp.data
389
+ else
390
+ fail ApiError.from_response(resp)
391
+ end
392
+ end
393
+ alias_method :refresh!, :reload!
394
+
370
395
  ##
371
396
  # New Table from a Google API Client object.
372
397
  def self.from_gapi gapi, conn #:nodoc:
@@ -144,6 +144,10 @@ module Gcloud
144
144
  @http_host = new_http_host
145
145
  end
146
146
 
147
+ def inspect #:nodoc:
148
+ "#{self.class}(#{@dataset_id})"
149
+ end
150
+
147
151
  protected
148
152
 
149
153
  ##
@@ -13,6 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
+ require "gcloud/gce"
16
17
  require "gcloud/datastore/connection"
17
18
  require "gcloud/datastore/credentials"
18
19
  require "gcloud/datastore/entity"
@@ -77,9 +78,11 @@ module Gcloud
77
78
  ##
78
79
  # Default project.
79
80
  def self.default_project #:nodoc:
80
- ENV["DATASTORE_PROJECT"] ||
81
+ ENV["DATASTORE_DATASET"] ||
82
+ ENV["DATASTORE_PROJECT"] ||
81
83
  ENV["GCLOUD_PROJECT"] ||
82
- ENV["GOOGLE_CLOUD_PROJECT"]
84
+ ENV["GOOGLE_CLOUD_PROJECT"] ||
85
+ Gcloud::GCE.project_id
83
86
  end
84
87
 
85
88
  ##
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "gcloud"
16
+ require "gcloud/errors"
17
17
 
18
18
  module Gcloud
19
19
  module Datastore
@@ -89,6 +89,7 @@ module Gcloud
89
89
  if Time === value ||
90
90
  Gcloud::Datastore::Key === value ||
91
91
  Gcloud::Datastore::Entity === value ||
92
+ NilClass === value ||
92
93
  TrueClass === value ||
93
94
  FalseClass === value ||
94
95
  Float === value ||
@@ -14,6 +14,7 @@
14
14
  # limitations under the License.
15
15
 
16
16
  require "gcloud/proto/datastore_v1.pb"
17
+ require "gcloud/datastore/errors"
17
18
 
18
19
  module Gcloud
19
20
  module Datastore
@@ -63,6 +64,8 @@ module Gcloud
63
64
  v.key_value = value.to_proto
64
65
  elsif Gcloud::Datastore::Entity === value
65
66
  v.entity_value = value.to_proto
67
+ elsif NilClass === value
68
+ # The correct behavior is to not set a value property
66
69
  elsif TrueClass === value
67
70
  v.boolean_value = true
68
71
  elsif FalseClass === value
@@ -0,0 +1,23 @@
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
+ #--
17
+ # Google Cloud Errors
18
+ module Gcloud
19
+ ##
20
+ # Base Gcloud exception class.
21
+ class Error < StandardError
22
+ end
23
+ end
data/lib/gcloud/gce.rb ADDED
@@ -0,0 +1,62 @@
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 "faraday"
17
+
18
+ #--
19
+ # Google Cloud Compute Engine
20
+ module Gcloud
21
+ ##
22
+ # Represents the Google Compute Engine environment.
23
+ module GCE #:nodoc:
24
+ CHECK_URI = "http://169.254.169.254"
25
+ PROJECT_URI = "#{CHECK_URI}/computeMetadata/v1/project/project-id"
26
+
27
+ # rubocop:disable all
28
+ # Disabled rubocop because this is private and we don't need more methods.
29
+
30
+ def self.gce? options = {}
31
+ conn = options[:connection] || Faraday.default_connection
32
+ resp = conn.get CHECK_URI do |req|
33
+ req.options.timeout = 0.1
34
+ end
35
+ return false unless resp.status == 200
36
+ return false unless resp.headers.key? "Metadata-Flavor"
37
+ return resp.headers["Metadata-Flavor"] == "Google"
38
+ rescue Faraday::TimeoutError, Faraday::ConnectionFailed
39
+ return false
40
+ end
41
+
42
+ def self.project_id options = {}
43
+ @gce ||= {}
44
+ return @gce[:project_id] if @gce.key? :project_id
45
+ conn = options[:connection] || Faraday.default_connection
46
+ conn.headers = { "Metadata-Flavor" => "Google" }
47
+ resp = conn.get PROJECT_URI do |req|
48
+ req.options.timeout = 0.1
49
+ end
50
+ if resp.status == 200
51
+ @gce[:project_id] = resp.body
52
+ else
53
+ @gce[:project_id] = nil
54
+ end
55
+ rescue Faraday::TimeoutError, Faraday::ConnectionFailed
56
+ @gce ||= {}
57
+ @gce[:project_id] = nil
58
+ end
59
+
60
+ # rubocop:enable all
61
+ end
62
+ end