Skip to content

Commit b725d9f

Browse files
committed
Documenting buckets in full.
1 parent d34a15e commit b725d9f

File tree

2 files changed

+319
-0
lines changed

2 files changed

+319
-0
lines changed

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
datastore-transactions
1111
datastore-batches
1212
datastore-dataset
13+
storage-surface
1314
storage-api
1415
storage-blobs
1516
storage-buckets

docs/storage-surface.rst

Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
``gcloud.storage`` API
2+
======================
3+
4+
Connection / Authorization
5+
--------------------------
6+
7+
- Inferred defaults used to create connection if none configured explicitly:
8+
9+
- credentials (derived from GAE / GCE environ if present).
10+
11+
- ``project`` (derived from GAE / GCE environ if present).
12+
13+
- ``bucket`` (derived from GAE / GCE environ if present).
14+
15+
- By calling methods which require authentication
16+
17+
.. code-block:: python
18+
19+
>>> from gcloud import storage
20+
>>> bucket = storage.get_bucket('my-bucket')
21+
22+
the default connection "just works" out of the box and will be lazily
23+
loaded and stored after the first use.
24+
25+
- Set defaults in a declarative fashion
26+
27+
.. code-block:: python
28+
29+
>>> storage.set_defaults()
30+
31+
or instead of using implicit behavior, pass in defaults
32+
33+
.. code-block:: python
34+
35+
>>> storage.set_defaults(connection=connection, project='some-project')
36+
... bucket=some_bucket)
37+
38+
though not all are needed
39+
40+
.. code-block:: python
41+
42+
>>> storage.set_defaults(project='some-project', bucket=some_bucket)
43+
44+
- Set defaults one-by-one
45+
46+
.. code-block:: python
47+
48+
>>> storage.set_default_bucket(some_bucket)
49+
>>> storage.set_default_connection(connection)
50+
>>> storage.set_default_project(project)
51+
52+
53+
Manage buckets
54+
--------------
55+
56+
Create a new bucket:
57+
58+
.. code-block:: python
59+
60+
>>> from gcloud import storage
61+
>>> new_bucket = storage.create_bucket(bucket_name)
62+
63+
if you desire to be declarative, you may pass in a connection to
64+
override the default:
65+
66+
.. code-block:: python
67+
68+
>>> new_bucket = storage.create_bucket(bucket_name, connection=connection)
69+
70+
Retrieve an existing bucket:
71+
72+
.. code-block:: python
73+
74+
>>> existing_bucket = storage.get_bucket(bucket_name)
75+
76+
but if the bucket does not exist an exception will occur
77+
78+
.. code-block:: python
79+
80+
>>> existing_bucket = storage.get_bucket(bucket_name)
81+
Traceback (most recent call last):
82+
File "<stdin>", line 1, in <module>
83+
gcloud.exceptions.NotFound: 404 Some Message
84+
85+
To get a null response instead of an exception, use
86+
:func:`lookup_bucket <gcloud.storage.api.lookup_bucket>`:
87+
88+
.. code-block:: python
89+
90+
>>> non_existent = storage.lookup_bucket(bucket_name)
91+
>>> print non_existent
92+
None
93+
94+
To list all buckets:
95+
96+
.. code-block:: python
97+
98+
>>> for bucket in storage.get_buckets():
99+
... print bucket
100+
<Bucket: foo>
101+
<Bucket: bar>
102+
<Bucket: baz>
103+
104+
or to use a project other than the default
105+
106+
.. code-block:: python
107+
108+
>>> for bucket in storage.get_buckets('some-project'):
109+
... print bucket
110+
111+
To limit the list of buckets returned,
112+
:func:`get_buckets() <gcloud.storage.get_buckets>` accepts optional
113+
arguments
114+
115+
.. code-block:: python
116+
117+
>>> bucket_iterator = storage.get_buckets(max_results=2,
118+
... page_token='next-bucket-name',
119+
... prefix='foo',
120+
... projection='noAcl',
121+
... fields=None)
122+
>>> for bucket in bucket_iterator:
123+
... print bucket
124+
125+
See the `buckets list`_ documenation for details.
126+
127+
.. _buckets list: https://cloud.google.com/storage/docs/json_api/v1/buckets/list
128+
129+
To delete a bucket
130+
131+
.. code-block:: python
132+
133+
>>> storage.delete_bucket(bucket_name)
134+
135+
.. note::
136+
Deleting a bucket should happen very infrequently. Be careful that you
137+
actually mean to delete the bucket.
138+
139+
In the case that the bucket has existing objects (``Blob`` here), the backend
140+
will return a `409 conflict`_ and raise
141+
142+
.. code-block:: python
143+
144+
>>> storage.delete_bucket(bucket_name)
145+
Traceback (most recent call last):
146+
File "<stdin>", line 1, in <module>
147+
gcloud.exceptions.Conflict: 409 Some Message
148+
149+
this can be addressed by using the ``force`` keyword:
150+
151+
>>> storage.delete_bucket(bucket_name, force=True)
152+
153+
This too will fail if the bucket contains more than 256 blobs.
154+
In this case, the blobs should be deleted manually first.
155+
156+
.. _409 conflict: http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_Client_Error
157+
158+
Working with Buckets
159+
--------------------
160+
161+
To create a bucket directly
162+
163+
.. code-block:: python
164+
165+
>>> bucket = storage.Bucket('bucket-name')
166+
>>> bucket.exists()
167+
False
168+
>>> bucket.create()
169+
>>> bucket.exists()
170+
True
171+
172+
You can also use an explicit connection
173+
174+
.. code-block:: python
175+
176+
>>> bucket = storage.Bucket('bucket-name', connection=connection)
177+
178+
.. note::
179+
An explicitly passed connection will be bound to the ``bucket`` and
180+
all objects associated with the bucket. This means that within a batch of
181+
updates, the ``connection`` will be used to make the request instead of
182+
the batch.
183+
184+
To load all bucket properties
185+
186+
.. code-block:: python
187+
188+
>>> bucket = storage.Bucket('bucket-name')
189+
>>> print bucket.last_sync
190+
None
191+
>>> bucket.properties
192+
{}
193+
>>> bucket.reload()
194+
>>> bucket.last_sync
195+
datetime.datetime(2015, 1, 1, 12, 0)
196+
>>> bucket.properties
197+
{u'etag': u'CAE=',
198+
u'id': u'bucket-name',
199+
...}
200+
>>> bucket.acl.loaded
201+
False
202+
>>> bucket.acl.reload()
203+
>>> bucket.acl.loaded
204+
True
205+
>>> bucket.acl.entities
206+
{'project-editors-111111': <ACL Entity: project-editors-111111 (OWNER)>,
207+
'project-owners-111111': <ACL Entity: project-owners-111111 (OWNER)>,
208+
'project-viewers-111111': <ACL Entity: project-viewers-111111 (READER)>,
209+
'user-01234': <ACL Entity: user-01234 (OWNER)>}
210+
211+
Instead of calling
212+
:meth:`Bucket.reload() <gcloud.storage.bucket.Bucket.reload>` and
213+
:meth:`BucketACL.reload() <gcloud.storage.acl.BucketACL.reload>`, you
214+
can load the properties when the object is instantiated by using the
215+
``eager`` keyword:
216+
217+
.. code-block:: python
218+
219+
>>> bucket = storage.Bucket('bucket-name', eager=True)
220+
>>> bucket.last_sync
221+
datetime.datetime(2015, 1, 1, 12, 0)
222+
>>> bucket.acl.loaded
223+
True
224+
225+
To delete a bucket
226+
227+
.. code-block:: python
228+
229+
>>> bucket.delete()
230+
231+
or
232+
233+
.. code-block:: python
234+
235+
>>> bucket.delete(force=True)
236+
237+
as above.
238+
239+
To make updates to the bucket use
240+
:meth:`Bucket.patch() <gcloud.storage.bucket.Bucket.patch>`
241+
242+
.. code-block:: python
243+
244+
>>> bucket.versioning_enabled = True
245+
>>> bucket.patch()
246+
247+
If there are no updates to send, an exception will occur
248+
249+
.. code-block:: python
250+
251+
>>> bucket.patch()
252+
Traceback (most recent call last):
253+
File "<stdin>", line 1, in <module>
254+
ValueError: No updates to send.
255+
256+
In total, the properties that can be updated are
257+
258+
.. code-block:: python
259+
260+
>>> bucket.cors = [
261+
... {
262+
... 'origin': ['http://example.appspot.com'],
263+
... 'responseHeader': ['Content-Type'],
264+
... 'method': ['GET', 'HEAD', 'DELETE'],
265+
... 'maxAgeSeconds': 3600,
266+
... }
267+
... ]
268+
>>> bucket.lifecycle = [
269+
... {
270+
... 'action': {'type': 'Delete'},
271+
... 'condition': {'age': 365},
272+
... },
273+
... ]
274+
>>> bucket.location = 'ASIA'
275+
>>> bucket.logging = {
276+
... 'logBucket': 'bucket-name',
277+
... 'logObjectPrefix': 'foo/',
278+
... }
279+
>>> bucket.versioning_enabled = True
280+
>>> bucket.website = {
281+
... 'mainPageSuffix': 'index.html',
282+
... 'notFoundPage': '404.html',
283+
... }
284+
>>> bucket.storage_class = 'DURABLE_REDUCED_AVAILABILITY'
285+
286+
See `buckets`_ specification for more details. In general, many of these
287+
properties are optional and will not need to be used (or changed from the
288+
defaults).
289+
290+
Other data -- namely `access control`_ -- is associated with buckets, but
291+
this data is handled through ``Bucket.acl``.
292+
293+
.. _buckets: https://cloud.google.com/storage/docs/json_api/v1/buckets
294+
.. _access control: https://cloud.google.com/storage/docs/access-control
295+
296+
Manage Blobs
297+
------------
298+
299+
Interacting with blobs requires an associated bucket.
300+
301+
To retrieve a blob, a bucket can be used directly
302+
303+
.. code-block:: python
304+
305+
>>> bucket.get_blob('blob-name')
306+
<Blob: bucket-name, blob-name>
307+
308+
or the default bucket can be used implicitly
309+
310+
.. code-block:: python
311+
312+
>>> storage.get_blob('blob-name')
313+
<Blob: default-bucket-name, blob-name>
314+
315+
Dealing with ACLs
316+
-----------------
317+
318+
To do

0 commit comments

Comments
 (0)