From 9e64b018255bd8d9b31d60e8f396966251de946b Mon Sep 17 00:00:00 2001 From: Tyler Bui-Palsulich <26876514+tbpg@users.noreply.github.com> Date: Thu, 8 Oct 2020 11:00:04 -0400 Subject: [PATCH] feat(internal/godocfx): HTML-ify package summary (#2986) This makes GoDoc headers actual headers. The other changes _should_ be minimal in appearance. The golden diff is a bit difficult to read -- try searching for `\nPackage storage provides an easy way to work with Google Cloud Storage.\nGoogle Cloud Storage stores data in named objects, which are grouped into buckets.\n

\n

\nMore information about Google Cloud Storage is available at\nhttps://cloud.google.com/storage/docs.\n

\n

\nSee https://godoc.org/cloud.google.com/go for authentication, timeouts,\nconnection pooling and similar aspects of this package.\n

\n

\nAll of the methods of this package use exponential backoff to retry calls that fail\nwith certain errors, as described in\nhttps://cloud.google.com/storage/docs/exponential-backoff. Retrying continues\nindefinitely unless the controlling context is canceled or the client is closed. See\ncontext.WithTimeout and context.WithCancel.\n

\n

Creating a Client

\n

\nTo start working with this package, create a client:\n

\n
ctx := context.Background()\nclient, err := storage.NewClient(ctx)\nif err != nil {\n    // TODO: Handle error.\n}\n
\n

\nThe client will use your default application credentials. Clients should be\nreused instead of created as needed. The methods of Client are safe for\nconcurrent use by multiple goroutines.\n

\n

\nIf you only wish to access public data, you can create\nan unauthenticated client with\n

\n
client, err := storage.NewClient(ctx, option.WithoutAuthentication())\n
\n

Buckets

\n

\nA Google Cloud Storage bucket is a collection of objects. To work with a\nbucket, make a bucket handle:\n

\n
bkt := client.Bucket(bucketName)\n
\n

\nA handle is a reference to a bucket. You can have a handle even if the\nbucket doesn't exist yet. To create a bucket in Google Cloud Storage,\ncall Create on the handle:\n

\n
if err := bkt.Create(ctx, projectID, nil); err != nil {\n    // TODO: Handle error.\n}\n
\n

\nNote that although buckets are associated with projects, bucket names are\nglobal across all projects.\n

\n

\nEach bucket has associated metadata, represented in this package by\nBucketAttrs. The third argument to BucketHandle.Create allows you to set\nthe initial BucketAttrs of a bucket. To retrieve a bucket's attributes, use\nAttrs:\n

\n
attrs, err := bkt.Attrs(ctx)\nif err != nil {\n    // TODO: Handle error.\n}\nfmt.Printf("bucket %s, created at %s, is located in %s with storage class %s\\n",\n    attrs.Name, attrs.Created, attrs.Location, attrs.StorageClass)\n
\n

Objects

\n

\nAn object holds arbitrary data as a sequence of bytes, like a file. You\nrefer to objects using a handle, just as with buckets, but unlike buckets\nyou don't explicitly create an object. Instead, the first time you write\nto an object it will be created. You can use the standard Go io.Reader\nand io.Writer interfaces to read and write object data:\n

\n
obj := bkt.Object("data")\n// Write something to obj.\n// w implements io.Writer.\nw := obj.NewWriter(ctx)\n// Write some text to obj. This will either create the object or overwrite whatever is there already.\nif _, err := fmt.Fprintf(w, "This object contains text.\\n"); err != nil {\n    // TODO: Handle error.\n}\n// Close, just like writing a file.\nif err := w.Close(); err != nil {\n    // TODO: Handle error.\n}\n\n// Read it back.\nr, err := obj.NewReader(ctx)\nif err != nil {\n    // TODO: Handle error.\n}\ndefer r.Close()\nif _, err := io.Copy(os.Stdout, r); err != nil {\n    // TODO: Handle error.\n}\n// Prints "This object contains text."\n
\n

\nObjects also have attributes, which you can fetch with Attrs:\n

\n
objAttrs, err := obj.Attrs(ctx)\nif err != nil {\n    // TODO: Handle error.\n}\nfmt.Printf("object %s has size %d and can be read using %s\\n",\n    objAttrs.Name, objAttrs.Size, objAttrs.MediaLink)\n
\n

Listing objects

\n

\nListing objects in a bucket is done with the Bucket.Objects method:\n

\n
query := &storage.Query{Prefix: ""}\n\nvar names []string\nit := bkt.Objects(ctx, query)\nfor {\n    attrs, err := it.Next()\n    if err == iterator.Done {\n        break\n    }\n    if err != nil {\n        log.Fatal(err)\n    }\n    names = append(names, attrs.Name)\n}\n
\n

\nIf only a subset of object attributes is needed when listing, specifying this\nsubset using Query.SetAttrSelection may speed up the listing process:\n

\n
query := &storage.Query{Prefix: ""}\nquery.SetAttrSelection([]string{"Name"})\n\n// ... as before\n
\n

ACLs

\n

\nBoth objects and buckets have ACLs (Access Control Lists). An ACL is a list of\nACLRules, each of which specifies the role of a user, group or project. ACLs\nare suitable for fine-grained control, but you may prefer using IAM to control\naccess at the project level (see\nhttps://cloud.google.com/storage/docs/access-control/iam).\n

\n

\nTo list the ACLs of a bucket or object, obtain an ACLHandle and call its List method:\n

\n
acls, err := obj.ACL().List(ctx)\nif err != nil {\n    // TODO: Handle error.\n}\nfor _, rule := range acls {\n    fmt.Printf("%s has role %s\\n", rule.Entity, rule.Role)\n}\n
\n

\nYou can also set and delete ACLs.\n

\n

Conditions

\n

\nEvery object has a generation and a metageneration. The generation changes\nwhenever the content changes, and the metageneration changes whenever the\nmetadata changes. Conditions let you check these values before an operation;\nthe operation only executes if the conditions match. You can use conditions to\nprevent race conditions in read-modify-write operations.\n

\n

\nFor example, say you've read an object's metadata into objAttrs. Now\nyou want to write to that object, but only if its contents haven't changed\nsince you read it. Here is how to express that:\n

\n
w = obj.If(storage.Conditions{GenerationMatch: objAttrs.Generation}).NewWriter(ctx)\n// Proceed with writing as above.\n
\n

Signed URLs

\n

\nYou can obtain a URL that lets anyone read or write an object for a limited time.\nYou don't need to create a client to do this. See the documentation of\nSignedURL for details.\n

\n
url, err := storage.SignedURL(bucketName, "shared-object", opts)\nif err != nil {\n    // TODO: Handle error.\n}\nfmt.Println(url)\n
\n

Post Policy V4 Signed Request

\n

\nA type of signed request that allows uploads through HTML forms directly to Cloud Storage with\ntemporary permission. Conditions can be applied to restrict how the HTML form is used and exercised\nby a user.\n

\n

\nFor more information, please see https://cloud.google.com/storage/docs/xml-api/post-object as well\nas the documentation of GenerateSignedPostPolicyV4.\n

\n
pv4, err := storage.GenerateSignedPostPolicyV4(bucketName, objectName, opts)\nif err != nil {\n    // TODO: Handle error.\n}\nfmt.Printf("URL: %s\\nFields; %v\\n", pv4.URL, pv4.Fields)\n
\n

Errors

\n

\nErrors returned by this client are often of the type [`googleapi.Error`](https://godoc.org/google.golang.org/api/googleapi#Error).\nThese errors can be introspected for more information by type asserting to the richer `googleapi.Error` type. For example:\n

\n
if e, ok := err.(*googleapi.Error); ok {\n\t  if e.Code == 409 { ... }\n}\n
\n" type: package langs: - go