| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237 |
- // Copyright 2014 Google LLC
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package storage
- import (
- "context"
- "encoding/base64"
- "encoding/json"
- "errors"
- "fmt"
- "reflect"
- "strings"
- "time"
- "cloud.google.com/go/compute/metadata"
- "cloud.google.com/go/internal/optional"
- "cloud.google.com/go/internal/trace"
- "cloud.google.com/go/storage/internal/apiv2/storagepb"
- "google.golang.org/api/googleapi"
- "google.golang.org/api/iamcredentials/v1"
- "google.golang.org/api/iterator"
- "google.golang.org/api/option"
- raw "google.golang.org/api/storage/v1"
- dpb "google.golang.org/genproto/googleapis/type/date"
- "google.golang.org/protobuf/proto"
- "google.golang.org/protobuf/types/known/durationpb"
- )
- // BucketHandle provides operations on a Google Cloud Storage bucket.
- // Use Client.Bucket to get a handle.
- type BucketHandle struct {
- c *Client
- name string
- acl ACLHandle
- defaultObjectACL ACLHandle
- conds *BucketConditions
- userProject string // project for Requester Pays buckets
- retry *retryConfig
- enableObjectRetention *bool
- }
- // Bucket returns a BucketHandle, which provides operations on the named bucket.
- // This call does not perform any network operations.
- //
- // The supplied name must contain only lowercase letters, numbers, dashes,
- // underscores, and dots. The full specification for valid bucket names can be
- // found at:
- //
- // https://cloud.google.com/storage/docs/bucket-naming
- func (c *Client) Bucket(name string) *BucketHandle {
- retry := c.retry.clone()
- return &BucketHandle{
- c: c,
- name: name,
- acl: ACLHandle{
- c: c,
- bucket: name,
- retry: retry,
- },
- defaultObjectACL: ACLHandle{
- c: c,
- bucket: name,
- isDefault: true,
- retry: retry,
- },
- retry: retry,
- }
- }
- // Create creates the Bucket in the project.
- // If attrs is nil the API defaults will be used.
- func (b *BucketHandle) Create(ctx context.Context, projectID string, attrs *BucketAttrs) (err error) {
- ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.Create")
- defer func() { trace.EndSpan(ctx, err) }()
- o := makeStorageOpts(true, b.retry, b.userProject)
- if _, err := b.c.tc.CreateBucket(ctx, projectID, b.name, attrs, b.enableObjectRetention, o...); err != nil {
- return err
- }
- return nil
- }
- // Delete deletes the Bucket.
- func (b *BucketHandle) Delete(ctx context.Context) (err error) {
- ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.Delete")
- defer func() { trace.EndSpan(ctx, err) }()
- o := makeStorageOpts(true, b.retry, b.userProject)
- return b.c.tc.DeleteBucket(ctx, b.name, b.conds, o...)
- }
- // ACL returns an ACLHandle, which provides access to the bucket's access control list.
- // This controls who can list, create or overwrite the objects in a bucket.
- // This call does not perform any network operations.
- func (b *BucketHandle) ACL() *ACLHandle {
- return &b.acl
- }
- // DefaultObjectACL returns an ACLHandle, which provides access to the bucket's default object ACLs.
- // These ACLs are applied to newly created objects in this bucket that do not have a defined ACL.
- // This call does not perform any network operations.
- func (b *BucketHandle) DefaultObjectACL() *ACLHandle {
- return &b.defaultObjectACL
- }
- // Object returns an ObjectHandle, which provides operations on the named object.
- // This call does not perform any network operations such as fetching the object or verifying its existence.
- // Use methods on ObjectHandle to perform network operations.
- //
- // name must consist entirely of valid UTF-8-encoded runes. The full specification
- // for valid object names can be found at:
- //
- // https://cloud.google.com/storage/docs/naming-objects
- func (b *BucketHandle) Object(name string) *ObjectHandle {
- retry := b.retry.clone()
- return &ObjectHandle{
- c: b.c,
- bucket: b.name,
- object: name,
- acl: ACLHandle{
- c: b.c,
- bucket: b.name,
- object: name,
- userProject: b.userProject,
- retry: retry,
- },
- gen: -1,
- userProject: b.userProject,
- retry: retry,
- }
- }
- // Attrs returns the metadata for the bucket.
- func (b *BucketHandle) Attrs(ctx context.Context) (attrs *BucketAttrs, err error) {
- ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.Attrs")
- defer func() { trace.EndSpan(ctx, err) }()
- o := makeStorageOpts(true, b.retry, b.userProject)
- return b.c.tc.GetBucket(ctx, b.name, b.conds, o...)
- }
- // Update updates a bucket's attributes.
- func (b *BucketHandle) Update(ctx context.Context, uattrs BucketAttrsToUpdate) (attrs *BucketAttrs, err error) {
- ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.Update")
- defer func() { trace.EndSpan(ctx, err) }()
- isIdempotent := b.conds != nil && b.conds.MetagenerationMatch != 0
- o := makeStorageOpts(isIdempotent, b.retry, b.userProject)
- return b.c.tc.UpdateBucket(ctx, b.name, &uattrs, b.conds, o...)
- }
- // SignedURL returns a URL for the specified object. Signed URLs allow anyone
- // access to a restricted resource for a limited time without needing a Google
- // account or signing in.
- // For more information about signed URLs, see "[Overview of access control]."
- //
- // This method requires the Method and Expires fields in the specified
- // SignedURLOptions to be non-nil. You may need to set the GoogleAccessID and
- // PrivateKey fields in some cases. Read more on the [automatic detection of credentials]
- // for this method.
- //
- // [Overview of access control]: https://cloud.google.com/storage/docs/accesscontrol#signed_urls_query_string_authentication
- // [automatic detection of credentials]: https://pkg.go.dev/cloud.google.com/go/storage#hdr-Credential_requirements_for_signing
- func (b *BucketHandle) SignedURL(object string, opts *SignedURLOptions) (string, error) {
- // Make a copy of opts so we don't modify the pointer parameter.
- newopts := opts.clone()
- if newopts.Hostname == "" {
- // Extract the correct host from the readhost set on the client
- newopts.Hostname = b.c.xmlHost
- }
- if opts.GoogleAccessID != "" && (opts.SignBytes != nil || len(opts.PrivateKey) > 0) {
- return SignedURL(b.name, object, newopts)
- }
- if newopts.GoogleAccessID == "" {
- id, err := b.detectDefaultGoogleAccessID()
- if err != nil {
- return "", err
- }
- newopts.GoogleAccessID = id
- }
- if newopts.SignBytes == nil && len(newopts.PrivateKey) == 0 {
- if b.c.creds != nil && len(b.c.creds.JSON) > 0 {
- var sa struct {
- PrivateKey string `json:"private_key"`
- }
- err := json.Unmarshal(b.c.creds.JSON, &sa)
- if err == nil && sa.PrivateKey != "" {
- newopts.PrivateKey = []byte(sa.PrivateKey)
- }
- }
- // Don't error out if we can't unmarshal the private key from the client,
- // fallback to the default sign function for the service account.
- if len(newopts.PrivateKey) == 0 {
- newopts.SignBytes = b.defaultSignBytesFunc(newopts.GoogleAccessID)
- }
- }
- return SignedURL(b.name, object, newopts)
- }
- // GenerateSignedPostPolicyV4 generates a PostPolicyV4 value from bucket, object and opts.
- // The generated URL and fields will then allow an unauthenticated client to perform multipart uploads.
- //
- // This method requires the Expires field in the specified PostPolicyV4Options
- // to be non-nil. You may need to set the GoogleAccessID and PrivateKey fields
- // in some cases. Read more on the [automatic detection of credentials] for this method.
- //
- // [automatic detection of credentials]: https://pkg.go.dev/cloud.google.com/go/storage#hdr-Credential_requirements_for_signing
- func (b *BucketHandle) GenerateSignedPostPolicyV4(object string, opts *PostPolicyV4Options) (*PostPolicyV4, error) {
- // Make a copy of opts so we don't modify the pointer parameter.
- newopts := opts.clone()
- if newopts.Hostname == "" {
- // Extract the correct host from the readhost set on the client
- newopts.Hostname = b.c.xmlHost
- }
- if opts.GoogleAccessID != "" && (opts.SignRawBytes != nil || opts.SignBytes != nil || len(opts.PrivateKey) > 0) {
- return GenerateSignedPostPolicyV4(b.name, object, newopts)
- }
- if newopts.GoogleAccessID == "" {
- id, err := b.detectDefaultGoogleAccessID()
- if err != nil {
- return nil, err
- }
- newopts.GoogleAccessID = id
- }
- if newopts.SignBytes == nil && newopts.SignRawBytes == nil && len(newopts.PrivateKey) == 0 {
- if b.c.creds != nil && len(b.c.creds.JSON) > 0 {
- var sa struct {
- PrivateKey string `json:"private_key"`
- }
- err := json.Unmarshal(b.c.creds.JSON, &sa)
- if err == nil && sa.PrivateKey != "" {
- newopts.PrivateKey = []byte(sa.PrivateKey)
- }
- }
- // Don't error out if we can't unmarshal the private key from the client,
- // fallback to the default sign function for the service account.
- if len(newopts.PrivateKey) == 0 {
- newopts.SignRawBytes = b.defaultSignBytesFunc(newopts.GoogleAccessID)
- }
- }
- return GenerateSignedPostPolicyV4(b.name, object, newopts)
- }
- func (b *BucketHandle) detectDefaultGoogleAccessID() (string, error) {
- returnErr := errors.New("no credentials found on client and not on GCE (Google Compute Engine)")
- if b.c.creds != nil && len(b.c.creds.JSON) > 0 {
- var sa struct {
- ClientEmail string `json:"client_email"`
- SAImpersonationURL string `json:"service_account_impersonation_url"`
- CredType string `json:"type"`
- }
- err := json.Unmarshal(b.c.creds.JSON, &sa)
- if err != nil {
- returnErr = err
- } else {
- switch sa.CredType {
- case "impersonated_service_account", "external_account":
- start, end := strings.LastIndex(sa.SAImpersonationURL, "/"), strings.LastIndex(sa.SAImpersonationURL, ":")
- if end <= start {
- returnErr = errors.New("error parsing external or impersonated service account credentials")
- } else {
- return sa.SAImpersonationURL[start+1 : end], nil
- }
- case "service_account":
- if sa.ClientEmail != "" {
- return sa.ClientEmail, nil
- }
- returnErr = errors.New("empty service account client email")
- default:
- returnErr = errors.New("unable to parse credentials; only service_account, external_account and impersonated_service_account credentials are supported")
- }
- }
- }
- // Don't error out if we can't unmarshal, fallback to GCE check.
- if metadata.OnGCE() {
- email, err := metadata.Email("default")
- if err == nil && email != "" {
- return email, nil
- } else if err != nil {
- returnErr = err
- } else {
- returnErr = errors.New("empty email from GCE metadata service")
- }
- }
- return "", fmt.Errorf("storage: unable to detect default GoogleAccessID: %w. Please provide the GoogleAccessID or use a supported means for autodetecting it (see https://pkg.go.dev/cloud.google.com/go/storage#hdr-Credential_requirements_for_signing)", returnErr)
- }
- func (b *BucketHandle) defaultSignBytesFunc(email string) func([]byte) ([]byte, error) {
- return func(in []byte) ([]byte, error) {
- ctx := context.Background()
- // It's ok to recreate this service per call since we pass in the http client,
- // circumventing the cost of recreating the auth/transport layer
- svc, err := iamcredentials.NewService(ctx, option.WithHTTPClient(b.c.hc))
- if err != nil {
- return nil, fmt.Errorf("unable to create iamcredentials client: %w", err)
- }
- resp, err := svc.Projects.ServiceAccounts.SignBlob(fmt.Sprintf("projects/-/serviceAccounts/%s", email), &iamcredentials.SignBlobRequest{
- Payload: base64.StdEncoding.EncodeToString(in),
- }).Do()
- if err != nil {
- return nil, fmt.Errorf("unable to sign bytes: %w", err)
- }
- out, err := base64.StdEncoding.DecodeString(resp.SignedBlob)
- if err != nil {
- return nil, fmt.Errorf("unable to base64 decode response: %w", err)
- }
- return out, nil
- }
- }
- // BucketAttrs represents the metadata for a Google Cloud Storage bucket.
- // Read-only fields are ignored by BucketHandle.Create.
- type BucketAttrs struct {
- // Name is the name of the bucket.
- // This field is read-only.
- Name string
- // ACL is the list of access control rules on the bucket.
- ACL []ACLRule
- // BucketPolicyOnly is an alias for UniformBucketLevelAccess. Use of
- // UniformBucketLevelAccess is recommended above the use of this field.
- // Setting BucketPolicyOnly.Enabled OR UniformBucketLevelAccess.Enabled to
- // true, will enable UniformBucketLevelAccess.
- BucketPolicyOnly BucketPolicyOnly
- // UniformBucketLevelAccess configures access checks to use only bucket-level IAM
- // policies and ignore any ACL rules for the bucket.
- // See https://cloud.google.com/storage/docs/uniform-bucket-level-access
- // for more information.
- UniformBucketLevelAccess UniformBucketLevelAccess
- // PublicAccessPrevention is the setting for the bucket's
- // PublicAccessPrevention policy, which can be used to prevent public access
- // of data in the bucket. See
- // https://cloud.google.com/storage/docs/public-access-prevention for more
- // information.
- PublicAccessPrevention PublicAccessPrevention
- // DefaultObjectACL is the list of access controls to
- // apply to new objects when no object ACL is provided.
- DefaultObjectACL []ACLRule
- // DefaultEventBasedHold is the default value for event-based hold on
- // newly created objects in this bucket. It defaults to false.
- DefaultEventBasedHold bool
- // If not empty, applies a predefined set of access controls. It should be set
- // only when creating a bucket.
- // It is always empty for BucketAttrs returned from the service.
- // See https://cloud.google.com/storage/docs/json_api/v1/buckets/insert
- // for valid values.
- PredefinedACL string
- // If not empty, applies a predefined set of default object access controls.
- // It should be set only when creating a bucket.
- // It is always empty for BucketAttrs returned from the service.
- // See https://cloud.google.com/storage/docs/json_api/v1/buckets/insert
- // for valid values.
- PredefinedDefaultObjectACL string
- // Location is the location of the bucket. It defaults to "US".
- // If specifying a dual-region, CustomPlacementConfig should be set in conjunction.
- Location string
- // The bucket's custom placement configuration that holds a list of
- // regional locations for custom dual regions.
- CustomPlacementConfig *CustomPlacementConfig
- // MetaGeneration is the metadata generation of the bucket.
- // This field is read-only.
- MetaGeneration int64
- // StorageClass is the default storage class of the bucket. This defines
- // how objects in the bucket are stored and determines the SLA
- // and the cost of storage. Typical values are "STANDARD", "NEARLINE",
- // "COLDLINE" and "ARCHIVE". Defaults to "STANDARD".
- // See https://cloud.google.com/storage/docs/storage-classes for all
- // valid values.
- StorageClass string
- // Created is the creation time of the bucket.
- // This field is read-only.
- Created time.Time
- // VersioningEnabled reports whether this bucket has versioning enabled.
- VersioningEnabled bool
- // Labels are the bucket's labels.
- Labels map[string]string
- // RequesterPays reports whether the bucket is a Requester Pays bucket.
- // Clients performing operations on Requester Pays buckets must provide
- // a user project (see BucketHandle.UserProject), which will be billed
- // for the operations.
- RequesterPays bool
- // Lifecycle is the lifecycle configuration for objects in the bucket.
- Lifecycle Lifecycle
- // Retention policy enforces a minimum retention time for all objects
- // contained in the bucket. A RetentionPolicy of nil implies the bucket
- // has no minimum data retention.
- //
- // This feature is in private alpha release. It is not currently available to
- // most customers. It might be changed in backwards-incompatible ways and is not
- // subject to any SLA or deprecation policy.
- RetentionPolicy *RetentionPolicy
- // The bucket's Cross-Origin Resource Sharing (CORS) configuration.
- CORS []CORS
- // The encryption configuration used by default for newly inserted objects.
- Encryption *BucketEncryption
- // The logging configuration.
- Logging *BucketLogging
- // The website configuration.
- Website *BucketWebsite
- // Etag is the HTTP/1.1 Entity tag for the bucket.
- // This field is read-only.
- Etag string
- // LocationType describes how data is stored and replicated.
- // Typical values are "multi-region", "region" and "dual-region".
- // This field is read-only.
- LocationType string
- // The project number of the project the bucket belongs to.
- // This field is read-only.
- ProjectNumber uint64
- // RPO configures the Recovery Point Objective (RPO) policy of the bucket.
- // Set to RPOAsyncTurbo to turn on Turbo Replication for a bucket.
- // See https://cloud.google.com/storage/docs/managing-turbo-replication for
- // more information.
- RPO RPO
- // Autoclass holds the bucket's autoclass configuration. If enabled,
- // allows for the automatic selection of the best storage class
- // based on object access patterns.
- Autoclass *Autoclass
- // ObjectRetentionMode reports whether individual objects in the bucket can
- // be configured with a retention policy. An empty value means that object
- // retention is disabled.
- // This field is read-only. Object retention can be enabled only by creating
- // a bucket with SetObjectRetention set to true on the BucketHandle. It
- // cannot be modified once the bucket is created.
- // ObjectRetention cannot be configured or reported through the gRPC API.
- ObjectRetentionMode string
- }
- // BucketPolicyOnly is an alias for UniformBucketLevelAccess.
- // Use of UniformBucketLevelAccess is preferred above BucketPolicyOnly.
- type BucketPolicyOnly struct {
- // Enabled specifies whether access checks use only bucket-level IAM
- // policies. Enabled may be disabled until the locked time.
- Enabled bool
- // LockedTime specifies the deadline for changing Enabled from true to
- // false.
- LockedTime time.Time
- }
- // UniformBucketLevelAccess configures access checks to use only bucket-level IAM
- // policies.
- type UniformBucketLevelAccess struct {
- // Enabled specifies whether access checks use only bucket-level IAM
- // policies. Enabled may be disabled until the locked time.
- Enabled bool
- // LockedTime specifies the deadline for changing Enabled from true to
- // false.
- LockedTime time.Time
- }
- // PublicAccessPrevention configures the Public Access Prevention feature, which
- // can be used to disallow public access to any data in a bucket. See
- // https://cloud.google.com/storage/docs/public-access-prevention for more
- // information.
- type PublicAccessPrevention int
- const (
- // PublicAccessPreventionUnknown is a zero value, used only if this field is
- // not set in a call to GCS.
- PublicAccessPreventionUnknown PublicAccessPrevention = iota
- // PublicAccessPreventionUnspecified corresponds to a value of "unspecified".
- // Deprecated: use PublicAccessPreventionInherited
- PublicAccessPreventionUnspecified
- // PublicAccessPreventionEnforced corresponds to a value of "enforced". This
- // enforces Public Access Prevention on the bucket.
- PublicAccessPreventionEnforced
- // PublicAccessPreventionInherited corresponds to a value of "inherited"
- // and is the default for buckets.
- PublicAccessPreventionInherited
- publicAccessPreventionUnknown string = ""
- // TODO: remove unspecified when change is fully completed
- publicAccessPreventionUnspecified = "unspecified"
- publicAccessPreventionEnforced = "enforced"
- publicAccessPreventionInherited = "inherited"
- )
- func (p PublicAccessPrevention) String() string {
- switch p {
- case PublicAccessPreventionInherited, PublicAccessPreventionUnspecified:
- return publicAccessPreventionInherited
- case PublicAccessPreventionEnforced:
- return publicAccessPreventionEnforced
- default:
- return publicAccessPreventionUnknown
- }
- }
- // Lifecycle is the lifecycle configuration for objects in the bucket.
- type Lifecycle struct {
- Rules []LifecycleRule
- }
- // RetentionPolicy enforces a minimum retention time for all objects
- // contained in the bucket.
- //
- // Any attempt to overwrite or delete objects younger than the retention
- // period will result in an error. An unlocked retention policy can be
- // modified or removed from the bucket via the Update method. A
- // locked retention policy cannot be removed or shortened in duration
- // for the lifetime of the bucket.
- //
- // This feature is in private alpha release. It is not currently available to
- // most customers. It might be changed in backwards-incompatible ways and is not
- // subject to any SLA or deprecation policy.
- type RetentionPolicy struct {
- // RetentionPeriod specifies the duration that objects need to be
- // retained. Retention duration must be greater than zero and less than
- // 100 years. Note that enforcement of retention periods less than a day
- // is not guaranteed. Such periods should only be used for testing
- // purposes.
- RetentionPeriod time.Duration
- // EffectiveTime is the time from which the policy was enforced and
- // effective. This field is read-only.
- EffectiveTime time.Time
- // IsLocked describes whether the bucket is locked. Once locked, an
- // object retention policy cannot be modified.
- // This field is read-only.
- IsLocked bool
- }
- const (
- // RFC3339 timestamp with only the date segment, used for CreatedBefore,
- // CustomTimeBefore, and NoncurrentTimeBefore in LifecycleRule.
- rfc3339Date = "2006-01-02"
- // DeleteAction is a lifecycle action that deletes a live and/or archived
- // objects. Takes precedence over SetStorageClass actions.
- DeleteAction = "Delete"
- // SetStorageClassAction changes the storage class of live and/or archived
- // objects.
- SetStorageClassAction = "SetStorageClass"
- // AbortIncompleteMPUAction is a lifecycle action that aborts an incomplete
- // multipart upload when the multipart upload meets the conditions specified
- // in the lifecycle rule. The AgeInDays condition is the only allowed
- // condition for this action. AgeInDays is measured from the time the
- // multipart upload was created.
- AbortIncompleteMPUAction = "AbortIncompleteMultipartUpload"
- )
- // LifecycleRule is a lifecycle configuration rule.
- //
- // When all the configured conditions are met by an object in the bucket, the
- // configured action will automatically be taken on that object.
- type LifecycleRule struct {
- // Action is the action to take when all of the associated conditions are
- // met.
- Action LifecycleAction
- // Condition is the set of conditions that must be met for the associated
- // action to be taken.
- Condition LifecycleCondition
- }
- // LifecycleAction is a lifecycle configuration action.
- type LifecycleAction struct {
- // Type is the type of action to take on matching objects.
- //
- // Acceptable values are storage.DeleteAction, storage.SetStorageClassAction,
- // and storage.AbortIncompleteMPUAction.
- Type string
- // StorageClass is the storage class to set on matching objects if the Action
- // is "SetStorageClass".
- StorageClass string
- }
- // Liveness specifies whether the object is live or not.
- type Liveness int
- const (
- // LiveAndArchived includes both live and archived objects.
- LiveAndArchived Liveness = iota
- // Live specifies that the object is still live.
- Live
- // Archived specifies that the object is archived.
- Archived
- )
- // LifecycleCondition is a set of conditions used to match objects and take an
- // action automatically.
- //
- // All configured conditions must be met for the associated action to be taken.
- type LifecycleCondition struct {
- // AllObjects is used to select all objects in a bucket by
- // setting AgeInDays to 0.
- AllObjects bool
- // AgeInDays is the age of the object in days.
- // If you want to set AgeInDays to `0` use AllObjects set to `true`.
- AgeInDays int64
- // CreatedBefore is the time the object was created.
- //
- // This condition is satisfied when an object is created before midnight of
- // the specified date in UTC.
- CreatedBefore time.Time
- // CustomTimeBefore is the CustomTime metadata field of the object. This
- // condition is satisfied when an object's CustomTime timestamp is before
- // midnight of the specified date in UTC.
- //
- // This condition can only be satisfied if CustomTime has been set.
- CustomTimeBefore time.Time
- // DaysSinceCustomTime is the days elapsed since the CustomTime date of the
- // object. This condition can only be satisfied if CustomTime has been set.
- // Note: Using `0` as the value will be ignored by the library and not sent to the API.
- DaysSinceCustomTime int64
- // DaysSinceNoncurrentTime is the days elapsed since the noncurrent timestamp
- // of the object. This condition is relevant only for versioned objects.
- // Note: Using `0` as the value will be ignored by the library and not sent to the API.
- DaysSinceNoncurrentTime int64
- // Liveness specifies the object's liveness. Relevant only for versioned objects
- Liveness Liveness
- // MatchesPrefix is the condition matching an object if any of the
- // matches_prefix strings are an exact prefix of the object's name.
- MatchesPrefix []string
- // MatchesStorageClasses is the condition matching the object's storage
- // class.
- //
- // Values include "STANDARD", "NEARLINE", "COLDLINE" and "ARCHIVE".
- MatchesStorageClasses []string
- // MatchesSuffix is the condition matching an object if any of the
- // matches_suffix strings are an exact suffix of the object's name.
- MatchesSuffix []string
- // NoncurrentTimeBefore is the noncurrent timestamp of the object. This
- // condition is satisfied when an object's noncurrent timestamp is before
- // midnight of the specified date in UTC.
- //
- // This condition is relevant only for versioned objects.
- NoncurrentTimeBefore time.Time
- // NumNewerVersions is the condition matching objects with a number of newer versions.
- //
- // If the value is N, this condition is satisfied when there are at least N
- // versions (including the live version) newer than this version of the
- // object.
- // Note: Using `0` as the value will be ignored by the library and not sent to the API.
- NumNewerVersions int64
- }
- // BucketLogging holds the bucket's logging configuration, which defines the
- // destination bucket and optional name prefix for the current bucket's
- // logs.
- type BucketLogging struct {
- // The destination bucket where the current bucket's logs
- // should be placed.
- LogBucket string
- // A prefix for log object names.
- LogObjectPrefix string
- }
- // BucketWebsite holds the bucket's website configuration, controlling how the
- // service behaves when accessing bucket contents as a web site. See
- // https://cloud.google.com/storage/docs/static-website for more information.
- type BucketWebsite struct {
- // If the requested object path is missing, the service will ensure the path has
- // a trailing '/', append this suffix, and attempt to retrieve the resulting
- // object. This allows the creation of index.html objects to represent directory
- // pages.
- MainPageSuffix string
- // If the requested object path is missing, and any mainPageSuffix object is
- // missing, if applicable, the service will return the named object from this
- // bucket as the content for a 404 Not Found result.
- NotFoundPage string
- }
- // CustomPlacementConfig holds the bucket's custom placement
- // configuration for Custom Dual Regions. See
- // https://cloud.google.com/storage/docs/locations#location-dr for more information.
- type CustomPlacementConfig struct {
- // The list of regional locations in which data is placed.
- // Custom Dual Regions require exactly 2 regional locations.
- DataLocations []string
- }
- // Autoclass holds the bucket's autoclass configuration. If enabled,
- // allows for the automatic selection of the best storage class
- // based on object access patterns. See
- // https://cloud.google.com/storage/docs/using-autoclass for more information.
- type Autoclass struct {
- // Enabled specifies whether the autoclass feature is enabled
- // on the bucket.
- Enabled bool
- // ToggleTime is the time from which Autoclass was last toggled.
- // If Autoclass is enabled when the bucket is created, the ToggleTime
- // is set to the bucket creation time. This field is read-only.
- ToggleTime time.Time
- // TerminalStorageClass: The storage class that objects in the bucket
- // eventually transition to if they are not read for a certain length of
- // time. Valid values are NEARLINE and ARCHIVE.
- TerminalStorageClass string
- // TerminalStorageClassUpdateTime represents the time of the most recent
- // update to "TerminalStorageClass".
- TerminalStorageClassUpdateTime time.Time
- }
- func newBucket(b *raw.Bucket) (*BucketAttrs, error) {
- if b == nil {
- return nil, nil
- }
- rp, err := toRetentionPolicy(b.RetentionPolicy)
- if err != nil {
- return nil, err
- }
- return &BucketAttrs{
- Name: b.Name,
- Location: b.Location,
- MetaGeneration: b.Metageneration,
- DefaultEventBasedHold: b.DefaultEventBasedHold,
- StorageClass: b.StorageClass,
- Created: convertTime(b.TimeCreated),
- VersioningEnabled: b.Versioning != nil && b.Versioning.Enabled,
- ACL: toBucketACLRules(b.Acl),
- DefaultObjectACL: toObjectACLRules(b.DefaultObjectAcl),
- Labels: b.Labels,
- RequesterPays: b.Billing != nil && b.Billing.RequesterPays,
- Lifecycle: toLifecycle(b.Lifecycle),
- RetentionPolicy: rp,
- ObjectRetentionMode: toBucketObjectRetention(b.ObjectRetention),
- CORS: toCORS(b.Cors),
- Encryption: toBucketEncryption(b.Encryption),
- Logging: toBucketLogging(b.Logging),
- Website: toBucketWebsite(b.Website),
- BucketPolicyOnly: toBucketPolicyOnly(b.IamConfiguration),
- UniformBucketLevelAccess: toUniformBucketLevelAccess(b.IamConfiguration),
- PublicAccessPrevention: toPublicAccessPrevention(b.IamConfiguration),
- Etag: b.Etag,
- LocationType: b.LocationType,
- ProjectNumber: b.ProjectNumber,
- RPO: toRPO(b),
- CustomPlacementConfig: customPlacementFromRaw(b.CustomPlacementConfig),
- Autoclass: toAutoclassFromRaw(b.Autoclass),
- }, nil
- }
- func newBucketFromProto(b *storagepb.Bucket) *BucketAttrs {
- if b == nil {
- return nil
- }
- return &BucketAttrs{
- Name: parseBucketName(b.GetName()),
- Location: b.GetLocation(),
- MetaGeneration: b.GetMetageneration(),
- DefaultEventBasedHold: b.GetDefaultEventBasedHold(),
- StorageClass: b.GetStorageClass(),
- Created: b.GetCreateTime().AsTime(),
- VersioningEnabled: b.GetVersioning().GetEnabled(),
- ACL: toBucketACLRulesFromProto(b.GetAcl()),
- DefaultObjectACL: toObjectACLRulesFromProto(b.GetDefaultObjectAcl()),
- Labels: b.GetLabels(),
- RequesterPays: b.GetBilling().GetRequesterPays(),
- Lifecycle: toLifecycleFromProto(b.GetLifecycle()),
- RetentionPolicy: toRetentionPolicyFromProto(b.GetRetentionPolicy()),
- CORS: toCORSFromProto(b.GetCors()),
- Encryption: toBucketEncryptionFromProto(b.GetEncryption()),
- Logging: toBucketLoggingFromProto(b.GetLogging()),
- Website: toBucketWebsiteFromProto(b.GetWebsite()),
- BucketPolicyOnly: toBucketPolicyOnlyFromProto(b.GetIamConfig()),
- UniformBucketLevelAccess: toUniformBucketLevelAccessFromProto(b.GetIamConfig()),
- PublicAccessPrevention: toPublicAccessPreventionFromProto(b.GetIamConfig()),
- LocationType: b.GetLocationType(),
- RPO: toRPOFromProto(b),
- CustomPlacementConfig: customPlacementFromProto(b.GetCustomPlacementConfig()),
- ProjectNumber: parseProjectNumber(b.GetProject()), // this can return 0 the project resource name is ID based
- Autoclass: toAutoclassFromProto(b.GetAutoclass()),
- }
- }
- // toRawBucket copies the editable attribute from b to the raw library's Bucket type.
- func (b *BucketAttrs) toRawBucket() *raw.Bucket {
- // Copy label map.
- var labels map[string]string
- if len(b.Labels) > 0 {
- labels = make(map[string]string, len(b.Labels))
- for k, v := range b.Labels {
- labels[k] = v
- }
- }
- // Ignore VersioningEnabled if it is false. This is OK because
- // we only call this method when creating a bucket, and by default
- // new buckets have versioning off.
- var v *raw.BucketVersioning
- if b.VersioningEnabled {
- v = &raw.BucketVersioning{Enabled: true}
- }
- var bb *raw.BucketBilling
- if b.RequesterPays {
- bb = &raw.BucketBilling{RequesterPays: true}
- }
- var bktIAM *raw.BucketIamConfiguration
- if b.UniformBucketLevelAccess.Enabled || b.BucketPolicyOnly.Enabled || b.PublicAccessPrevention != PublicAccessPreventionUnknown {
- bktIAM = &raw.BucketIamConfiguration{}
- if b.UniformBucketLevelAccess.Enabled || b.BucketPolicyOnly.Enabled {
- bktIAM.UniformBucketLevelAccess = &raw.BucketIamConfigurationUniformBucketLevelAccess{
- Enabled: true,
- }
- }
- if b.PublicAccessPrevention != PublicAccessPreventionUnknown {
- bktIAM.PublicAccessPrevention = b.PublicAccessPrevention.String()
- }
- }
- return &raw.Bucket{
- Name: b.Name,
- Location: b.Location,
- StorageClass: b.StorageClass,
- Acl: toRawBucketACL(b.ACL),
- DefaultObjectAcl: toRawObjectACL(b.DefaultObjectACL),
- Versioning: v,
- Labels: labels,
- Billing: bb,
- Lifecycle: toRawLifecycle(b.Lifecycle),
- RetentionPolicy: b.RetentionPolicy.toRawRetentionPolicy(),
- Cors: toRawCORS(b.CORS),
- Encryption: b.Encryption.toRawBucketEncryption(),
- Logging: b.Logging.toRawBucketLogging(),
- Website: b.Website.toRawBucketWebsite(),
- IamConfiguration: bktIAM,
- Rpo: b.RPO.String(),
- CustomPlacementConfig: b.CustomPlacementConfig.toRawCustomPlacement(),
- Autoclass: b.Autoclass.toRawAutoclass(),
- }
- }
- func (b *BucketAttrs) toProtoBucket() *storagepb.Bucket {
- if b == nil {
- return &storagepb.Bucket{}
- }
- // Copy label map.
- var labels map[string]string
- if len(b.Labels) > 0 {
- labels = make(map[string]string, len(b.Labels))
- for k, v := range b.Labels {
- labels[k] = v
- }
- }
- // Ignore VersioningEnabled if it is false. This is OK because
- // we only call this method when creating a bucket, and by default
- // new buckets have versioning off.
- var v *storagepb.Bucket_Versioning
- if b.VersioningEnabled {
- v = &storagepb.Bucket_Versioning{Enabled: true}
- }
- var bb *storagepb.Bucket_Billing
- if b.RequesterPays {
- bb = &storagepb.Bucket_Billing{RequesterPays: true}
- }
- var bktIAM *storagepb.Bucket_IamConfig
- if b.UniformBucketLevelAccess.Enabled || b.BucketPolicyOnly.Enabled || b.PublicAccessPrevention != PublicAccessPreventionUnknown {
- bktIAM = &storagepb.Bucket_IamConfig{}
- if b.UniformBucketLevelAccess.Enabled || b.BucketPolicyOnly.Enabled {
- bktIAM.UniformBucketLevelAccess = &storagepb.Bucket_IamConfig_UniformBucketLevelAccess{
- Enabled: true,
- }
- }
- if b.PublicAccessPrevention != PublicAccessPreventionUnknown {
- bktIAM.PublicAccessPrevention = b.PublicAccessPrevention.String()
- }
- }
- return &storagepb.Bucket{
- Name: b.Name,
- Location: b.Location,
- StorageClass: b.StorageClass,
- Acl: toProtoBucketACL(b.ACL),
- DefaultObjectAcl: toProtoObjectACL(b.DefaultObjectACL),
- Versioning: v,
- Labels: labels,
- Billing: bb,
- Lifecycle: toProtoLifecycle(b.Lifecycle),
- RetentionPolicy: b.RetentionPolicy.toProtoRetentionPolicy(),
- Cors: toProtoCORS(b.CORS),
- Encryption: b.Encryption.toProtoBucketEncryption(),
- Logging: b.Logging.toProtoBucketLogging(),
- Website: b.Website.toProtoBucketWebsite(),
- IamConfig: bktIAM,
- Rpo: b.RPO.String(),
- CustomPlacementConfig: b.CustomPlacementConfig.toProtoCustomPlacement(),
- Autoclass: b.Autoclass.toProtoAutoclass(),
- }
- }
- func (ua *BucketAttrsToUpdate) toProtoBucket() *storagepb.Bucket {
- if ua == nil {
- return &storagepb.Bucket{}
- }
- var v *storagepb.Bucket_Versioning
- if ua.VersioningEnabled != nil {
- v = &storagepb.Bucket_Versioning{Enabled: optional.ToBool(ua.VersioningEnabled)}
- }
- var bb *storagepb.Bucket_Billing
- if ua.RequesterPays != nil {
- bb = &storagepb.Bucket_Billing{RequesterPays: optional.ToBool(ua.RequesterPays)}
- }
- var bktIAM *storagepb.Bucket_IamConfig
- if ua.UniformBucketLevelAccess != nil || ua.BucketPolicyOnly != nil || ua.PublicAccessPrevention != PublicAccessPreventionUnknown {
- bktIAM = &storagepb.Bucket_IamConfig{}
- if ua.BucketPolicyOnly != nil {
- bktIAM.UniformBucketLevelAccess = &storagepb.Bucket_IamConfig_UniformBucketLevelAccess{
- Enabled: optional.ToBool(ua.BucketPolicyOnly.Enabled),
- }
- }
- if ua.UniformBucketLevelAccess != nil {
- // UniformBucketLevelAccess takes precedence over BucketPolicyOnly,
- // so Enabled will be overriden here if both are set
- bktIAM.UniformBucketLevelAccess = &storagepb.Bucket_IamConfig_UniformBucketLevelAccess{
- Enabled: optional.ToBool(ua.UniformBucketLevelAccess.Enabled),
- }
- }
- if ua.PublicAccessPrevention != PublicAccessPreventionUnknown {
- bktIAM.PublicAccessPrevention = ua.PublicAccessPrevention.String()
- }
- }
- var defaultHold bool
- if ua.DefaultEventBasedHold != nil {
- defaultHold = optional.ToBool(ua.DefaultEventBasedHold)
- }
- var lifecycle Lifecycle
- if ua.Lifecycle != nil {
- lifecycle = *ua.Lifecycle
- }
- var bktACL []*storagepb.BucketAccessControl
- if ua.acl != nil {
- bktACL = toProtoBucketACL(ua.acl)
- }
- if ua.PredefinedACL != "" {
- // Clear ACL or the call will fail.
- bktACL = nil
- }
- var bktDefaultObjectACL []*storagepb.ObjectAccessControl
- if ua.defaultObjectACL != nil {
- bktDefaultObjectACL = toProtoObjectACL(ua.defaultObjectACL)
- }
- if ua.PredefinedDefaultObjectACL != "" {
- // Clear ACLs or the call will fail.
- bktDefaultObjectACL = nil
- }
- return &storagepb.Bucket{
- StorageClass: ua.StorageClass,
- Acl: bktACL,
- DefaultObjectAcl: bktDefaultObjectACL,
- DefaultEventBasedHold: defaultHold,
- Versioning: v,
- Billing: bb,
- Lifecycle: toProtoLifecycle(lifecycle),
- RetentionPolicy: ua.RetentionPolicy.toProtoRetentionPolicy(),
- Cors: toProtoCORS(ua.CORS),
- Encryption: ua.Encryption.toProtoBucketEncryption(),
- Logging: ua.Logging.toProtoBucketLogging(),
- Website: ua.Website.toProtoBucketWebsite(),
- IamConfig: bktIAM,
- Rpo: ua.RPO.String(),
- Autoclass: ua.Autoclass.toProtoAutoclass(),
- Labels: ua.setLabels,
- }
- }
- // CORS is the bucket's Cross-Origin Resource Sharing (CORS) configuration.
- type CORS struct {
- // MaxAge is the value to return in the Access-Control-Max-Age
- // header used in preflight responses.
- MaxAge time.Duration
- // Methods is the list of HTTP methods on which to include CORS response
- // headers, (GET, OPTIONS, POST, etc) Note: "*" is permitted in the list
- // of methods, and means "any method".
- Methods []string
- // Origins is the list of Origins eligible to receive CORS response
- // headers. Note: "*" is permitted in the list of origins, and means
- // "any Origin".
- Origins []string
- // ResponseHeaders is the list of HTTP headers other than the simple
- // response headers to give permission for the user-agent to share
- // across domains.
- ResponseHeaders []string
- }
- // BucketEncryption is a bucket's encryption configuration.
- type BucketEncryption struct {
- // A Cloud KMS key name, in the form
- // projects/P/locations/L/keyRings/R/cryptoKeys/K, that will be used to encrypt
- // objects inserted into this bucket, if no encryption method is specified.
- // The key's location must be the same as the bucket's.
- DefaultKMSKeyName string
- }
- // BucketAttrsToUpdate define the attributes to update during an Update call.
- type BucketAttrsToUpdate struct {
- // If set, updates whether the bucket uses versioning.
- VersioningEnabled optional.Bool
- // If set, updates whether the bucket is a Requester Pays bucket.
- RequesterPays optional.Bool
- // DefaultEventBasedHold is the default value for event-based hold on
- // newly created objects in this bucket.
- DefaultEventBasedHold optional.Bool
- // BucketPolicyOnly is an alias for UniformBucketLevelAccess. Use of
- // UniformBucketLevelAccess is recommended above the use of this field.
- // Setting BucketPolicyOnly.Enabled OR UniformBucketLevelAccess.Enabled to
- // true, will enable UniformBucketLevelAccess. If both BucketPolicyOnly and
- // UniformBucketLevelAccess are set, the value of UniformBucketLevelAccess
- // will take precedence.
- BucketPolicyOnly *BucketPolicyOnly
- // UniformBucketLevelAccess configures access checks to use only bucket-level IAM
- // policies and ignore any ACL rules for the bucket.
- // See https://cloud.google.com/storage/docs/uniform-bucket-level-access
- // for more information.
- UniformBucketLevelAccess *UniformBucketLevelAccess
- // PublicAccessPrevention is the setting for the bucket's
- // PublicAccessPrevention policy, which can be used to prevent public access
- // of data in the bucket. See
- // https://cloud.google.com/storage/docs/public-access-prevention for more
- // information.
- PublicAccessPrevention PublicAccessPrevention
- // StorageClass is the default storage class of the bucket. This defines
- // how objects in the bucket are stored and determines the SLA
- // and the cost of storage. Typical values are "STANDARD", "NEARLINE",
- // "COLDLINE" and "ARCHIVE". Defaults to "STANDARD".
- // See https://cloud.google.com/storage/docs/storage-classes for all
- // valid values.
- StorageClass string
- // If set, updates the retention policy of the bucket. Using
- // RetentionPolicy.RetentionPeriod = 0 will delete the existing policy.
- //
- // This feature is in private alpha release. It is not currently available to
- // most customers. It might be changed in backwards-incompatible ways and is not
- // subject to any SLA or deprecation policy.
- RetentionPolicy *RetentionPolicy
- // If set, replaces the CORS configuration with a new configuration.
- // An empty (rather than nil) slice causes all CORS policies to be removed.
- CORS []CORS
- // If set, replaces the encryption configuration of the bucket. Using
- // BucketEncryption.DefaultKMSKeyName = "" will delete the existing
- // configuration.
- Encryption *BucketEncryption
- // If set, replaces the lifecycle configuration of the bucket.
- Lifecycle *Lifecycle
- // If set, replaces the logging configuration of the bucket.
- Logging *BucketLogging
- // If set, replaces the website configuration of the bucket.
- Website *BucketWebsite
- // If not empty, applies a predefined set of access controls.
- // See https://cloud.google.com/storage/docs/json_api/v1/buckets/patch.
- PredefinedACL string
- // If not empty, applies a predefined set of default object access controls.
- // See https://cloud.google.com/storage/docs/json_api/v1/buckets/patch.
- PredefinedDefaultObjectACL string
- // RPO configures the Recovery Point Objective (RPO) policy of the bucket.
- // Set to RPOAsyncTurbo to turn on Turbo Replication for a bucket.
- // See https://cloud.google.com/storage/docs/managing-turbo-replication for
- // more information.
- RPO RPO
- // If set, updates the autoclass configuration of the bucket.
- // See https://cloud.google.com/storage/docs/using-autoclass for more information.
- Autoclass *Autoclass
- // acl is the list of access control rules on the bucket.
- // It is unexported and only used internally by the gRPC client.
- // Library users should use ACLHandle methods directly.
- acl []ACLRule
- // defaultObjectACL is the list of access controls to
- // apply to new objects when no object ACL is provided.
- // It is unexported and only used internally by the gRPC client.
- // Library users should use ACLHandle methods directly.
- defaultObjectACL []ACLRule
- setLabels map[string]string
- deleteLabels map[string]bool
- }
- // SetLabel causes a label to be added or modified when ua is used
- // in a call to Bucket.Update.
- func (ua *BucketAttrsToUpdate) SetLabel(name, value string) {
- if ua.setLabels == nil {
- ua.setLabels = map[string]string{}
- }
- ua.setLabels[name] = value
- }
- // DeleteLabel causes a label to be deleted when ua is used in a
- // call to Bucket.Update.
- func (ua *BucketAttrsToUpdate) DeleteLabel(name string) {
- if ua.deleteLabels == nil {
- ua.deleteLabels = map[string]bool{}
- }
- ua.deleteLabels[name] = true
- }
- func (ua *BucketAttrsToUpdate) toRawBucket() *raw.Bucket {
- rb := &raw.Bucket{}
- if ua.CORS != nil {
- rb.Cors = toRawCORS(ua.CORS)
- rb.ForceSendFields = append(rb.ForceSendFields, "Cors")
- }
- if ua.DefaultEventBasedHold != nil {
- rb.DefaultEventBasedHold = optional.ToBool(ua.DefaultEventBasedHold)
- rb.ForceSendFields = append(rb.ForceSendFields, "DefaultEventBasedHold")
- }
- if ua.RetentionPolicy != nil {
- if ua.RetentionPolicy.RetentionPeriod == 0 {
- rb.NullFields = append(rb.NullFields, "RetentionPolicy")
- rb.RetentionPolicy = nil
- } else {
- rb.RetentionPolicy = ua.RetentionPolicy.toRawRetentionPolicy()
- }
- }
- if ua.VersioningEnabled != nil {
- rb.Versioning = &raw.BucketVersioning{
- Enabled: optional.ToBool(ua.VersioningEnabled),
- ForceSendFields: []string{"Enabled"},
- }
- }
- if ua.RequesterPays != nil {
- rb.Billing = &raw.BucketBilling{
- RequesterPays: optional.ToBool(ua.RequesterPays),
- ForceSendFields: []string{"RequesterPays"},
- }
- }
- if ua.BucketPolicyOnly != nil {
- rb.IamConfiguration = &raw.BucketIamConfiguration{
- UniformBucketLevelAccess: &raw.BucketIamConfigurationUniformBucketLevelAccess{
- Enabled: ua.BucketPolicyOnly.Enabled,
- ForceSendFields: []string{"Enabled"},
- },
- }
- }
- if ua.UniformBucketLevelAccess != nil {
- rb.IamConfiguration = &raw.BucketIamConfiguration{
- UniformBucketLevelAccess: &raw.BucketIamConfigurationUniformBucketLevelAccess{
- Enabled: ua.UniformBucketLevelAccess.Enabled,
- ForceSendFields: []string{"Enabled"},
- },
- }
- }
- if ua.PublicAccessPrevention != PublicAccessPreventionUnknown {
- if rb.IamConfiguration == nil {
- rb.IamConfiguration = &raw.BucketIamConfiguration{}
- }
- rb.IamConfiguration.PublicAccessPrevention = ua.PublicAccessPrevention.String()
- }
- if ua.Encryption != nil {
- if ua.Encryption.DefaultKMSKeyName == "" {
- rb.NullFields = append(rb.NullFields, "Encryption")
- rb.Encryption = nil
- } else {
- rb.Encryption = ua.Encryption.toRawBucketEncryption()
- }
- }
- if ua.Lifecycle != nil {
- rb.Lifecycle = toRawLifecycle(*ua.Lifecycle)
- rb.ForceSendFields = append(rb.ForceSendFields, "Lifecycle")
- }
- if ua.Logging != nil {
- if *ua.Logging == (BucketLogging{}) {
- rb.NullFields = append(rb.NullFields, "Logging")
- rb.Logging = nil
- } else {
- rb.Logging = ua.Logging.toRawBucketLogging()
- }
- }
- if ua.Website != nil {
- if *ua.Website == (BucketWebsite{}) {
- rb.NullFields = append(rb.NullFields, "Website")
- rb.Website = nil
- } else {
- rb.Website = ua.Website.toRawBucketWebsite()
- }
- }
- if ua.Autoclass != nil {
- rb.Autoclass = &raw.BucketAutoclass{
- Enabled: ua.Autoclass.Enabled,
- TerminalStorageClass: ua.Autoclass.TerminalStorageClass,
- ForceSendFields: []string{"Enabled"},
- }
- rb.ForceSendFields = append(rb.ForceSendFields, "Autoclass")
- }
- if ua.PredefinedACL != "" {
- // Clear ACL or the call will fail.
- rb.Acl = nil
- rb.ForceSendFields = append(rb.ForceSendFields, "Acl")
- }
- if ua.PredefinedDefaultObjectACL != "" {
- // Clear ACLs or the call will fail.
- rb.DefaultObjectAcl = nil
- rb.ForceSendFields = append(rb.ForceSendFields, "DefaultObjectAcl")
- }
- rb.StorageClass = ua.StorageClass
- rb.Rpo = ua.RPO.String()
- if ua.setLabels != nil || ua.deleteLabels != nil {
- rb.Labels = map[string]string{}
- for k, v := range ua.setLabels {
- rb.Labels[k] = v
- }
- if len(rb.Labels) == 0 && len(ua.deleteLabels) > 0 {
- rb.ForceSendFields = append(rb.ForceSendFields, "Labels")
- }
- for l := range ua.deleteLabels {
- rb.NullFields = append(rb.NullFields, "Labels."+l)
- }
- }
- return rb
- }
- // If returns a new BucketHandle that applies a set of preconditions.
- // Preconditions already set on the BucketHandle are ignored. The supplied
- // BucketConditions must have exactly one field set to a non-zero value;
- // otherwise an error will be returned from any operation on the BucketHandle.
- // Operations on the new handle will return an error if the preconditions are not
- // satisfied. The only valid preconditions for buckets are MetagenerationMatch
- // and MetagenerationNotMatch.
- func (b *BucketHandle) If(conds BucketConditions) *BucketHandle {
- b2 := *b
- b2.conds = &conds
- return &b2
- }
- // BucketConditions constrain bucket methods to act on specific metagenerations.
- //
- // The zero value is an empty set of constraints.
- type BucketConditions struct {
- // MetagenerationMatch specifies that the bucket must have the given
- // metageneration for the operation to occur.
- // If MetagenerationMatch is zero, it has no effect.
- MetagenerationMatch int64
- // MetagenerationNotMatch specifies that the bucket must not have the given
- // metageneration for the operation to occur.
- // If MetagenerationNotMatch is zero, it has no effect.
- MetagenerationNotMatch int64
- }
- func (c *BucketConditions) validate(method string) error {
- if *c == (BucketConditions{}) {
- return fmt.Errorf("storage: %s: empty conditions", method)
- }
- if c.MetagenerationMatch != 0 && c.MetagenerationNotMatch != 0 {
- return fmt.Errorf("storage: %s: multiple conditions specified for metageneration", method)
- }
- return nil
- }
- // UserProject returns a new BucketHandle that passes the project ID as the user
- // project for all subsequent calls. Calls with a user project will be billed to that
- // project rather than to the bucket's owning project.
- //
- // A user project is required for all operations on Requester Pays buckets.
- func (b *BucketHandle) UserProject(projectID string) *BucketHandle {
- b2 := *b
- b2.userProject = projectID
- b2.acl.userProject = projectID
- b2.defaultObjectACL.userProject = projectID
- return &b2
- }
- // LockRetentionPolicy locks a bucket's retention policy until a previously-configured
- // RetentionPeriod past the EffectiveTime. Note that if RetentionPeriod is set to less
- // than a day, the retention policy is treated as a development configuration and locking
- // will have no effect. The BucketHandle must have a metageneration condition that
- // matches the bucket's metageneration. See BucketHandle.If.
- //
- // This feature is in private alpha release. It is not currently available to
- // most customers. It might be changed in backwards-incompatible ways and is not
- // subject to any SLA or deprecation policy.
- func (b *BucketHandle) LockRetentionPolicy(ctx context.Context) error {
- o := makeStorageOpts(true, b.retry, b.userProject)
- return b.c.tc.LockBucketRetentionPolicy(ctx, b.name, b.conds, o...)
- }
- // SetObjectRetention returns a new BucketHandle that will enable object retention
- // on bucket creation. To enable object retention, you must use the returned
- // handle to create the bucket. This has no effect on an already existing bucket.
- // ObjectRetention is not enabled by default.
- // ObjectRetention cannot be configured through the gRPC API.
- func (b *BucketHandle) SetObjectRetention(enable bool) *BucketHandle {
- b2 := *b
- b2.enableObjectRetention = &enable
- return &b2
- }
- // applyBucketConds modifies the provided call using the conditions in conds.
- // call is something that quacks like a *raw.WhateverCall.
- func applyBucketConds(method string, conds *BucketConditions, call interface{}) error {
- if conds == nil {
- return nil
- }
- if err := conds.validate(method); err != nil {
- return err
- }
- cval := reflect.ValueOf(call)
- switch {
- case conds.MetagenerationMatch != 0:
- if !setIfMetagenerationMatch(cval, conds.MetagenerationMatch) {
- return fmt.Errorf("storage: %s: ifMetagenerationMatch not supported", method)
- }
- case conds.MetagenerationNotMatch != 0:
- if !setIfMetagenerationNotMatch(cval, conds.MetagenerationNotMatch) {
- return fmt.Errorf("storage: %s: ifMetagenerationNotMatch not supported", method)
- }
- }
- return nil
- }
- // applyBucketConds modifies the provided request message using the conditions
- // in conds. msg is a protobuf Message that has fields if_metageneration_match
- // and if_metageneration_not_match.
- func applyBucketCondsProto(method string, conds *BucketConditions, msg proto.Message) error {
- rmsg := msg.ProtoReflect()
- if conds == nil {
- return nil
- }
- if err := conds.validate(method); err != nil {
- return err
- }
- switch {
- case conds.MetagenerationMatch != 0:
- if !setConditionProtoField(rmsg, "if_metageneration_match", conds.MetagenerationMatch) {
- return fmt.Errorf("storage: %s: ifMetagenerationMatch not supported", method)
- }
- case conds.MetagenerationNotMatch != 0:
- if !setConditionProtoField(rmsg, "if_metageneration_not_match", conds.MetagenerationNotMatch) {
- return fmt.Errorf("storage: %s: ifMetagenerationNotMatch not supported", method)
- }
- }
- return nil
- }
- func (rp *RetentionPolicy) toRawRetentionPolicy() *raw.BucketRetentionPolicy {
- if rp == nil {
- return nil
- }
- return &raw.BucketRetentionPolicy{
- RetentionPeriod: int64(rp.RetentionPeriod / time.Second),
- }
- }
- func (rp *RetentionPolicy) toProtoRetentionPolicy() *storagepb.Bucket_RetentionPolicy {
- if rp == nil {
- return nil
- }
- // RetentionPeriod must be greater than 0, so if it is 0, the user left it
- // unset, and so we should not send it in the request i.e. nil is sent.
- var dur *durationpb.Duration
- if rp.RetentionPeriod != 0 {
- dur = durationpb.New(rp.RetentionPeriod)
- }
- return &storagepb.Bucket_RetentionPolicy{
- RetentionDuration: dur,
- }
- }
- func toRetentionPolicy(rp *raw.BucketRetentionPolicy) (*RetentionPolicy, error) {
- if rp == nil || rp.EffectiveTime == "" {
- return nil, nil
- }
- t, err := time.Parse(time.RFC3339, rp.EffectiveTime)
- if err != nil {
- return nil, err
- }
- return &RetentionPolicy{
- RetentionPeriod: time.Duration(rp.RetentionPeriod) * time.Second,
- EffectiveTime: t,
- IsLocked: rp.IsLocked,
- }, nil
- }
- func toRetentionPolicyFromProto(rp *storagepb.Bucket_RetentionPolicy) *RetentionPolicy {
- if rp == nil || rp.GetEffectiveTime().AsTime().Unix() == 0 {
- return nil
- }
- return &RetentionPolicy{
- RetentionPeriod: rp.GetRetentionDuration().AsDuration(),
- EffectiveTime: rp.GetEffectiveTime().AsTime(),
- IsLocked: rp.GetIsLocked(),
- }
- }
- func toBucketObjectRetention(or *raw.BucketObjectRetention) string {
- if or == nil {
- return ""
- }
- return or.Mode
- }
- func toRawCORS(c []CORS) []*raw.BucketCors {
- var out []*raw.BucketCors
- for _, v := range c {
- out = append(out, &raw.BucketCors{
- MaxAgeSeconds: int64(v.MaxAge / time.Second),
- Method: v.Methods,
- Origin: v.Origins,
- ResponseHeader: v.ResponseHeaders,
- })
- }
- return out
- }
- func toProtoCORS(c []CORS) []*storagepb.Bucket_Cors {
- var out []*storagepb.Bucket_Cors
- for _, v := range c {
- out = append(out, &storagepb.Bucket_Cors{
- MaxAgeSeconds: int32(v.MaxAge / time.Second),
- Method: v.Methods,
- Origin: v.Origins,
- ResponseHeader: v.ResponseHeaders,
- })
- }
- return out
- }
- func toCORS(rc []*raw.BucketCors) []CORS {
- var out []CORS
- for _, v := range rc {
- out = append(out, CORS{
- MaxAge: time.Duration(v.MaxAgeSeconds) * time.Second,
- Methods: v.Method,
- Origins: v.Origin,
- ResponseHeaders: v.ResponseHeader,
- })
- }
- return out
- }
- func toCORSFromProto(rc []*storagepb.Bucket_Cors) []CORS {
- var out []CORS
- for _, v := range rc {
- out = append(out, CORS{
- MaxAge: time.Duration(v.GetMaxAgeSeconds()) * time.Second,
- Methods: v.GetMethod(),
- Origins: v.GetOrigin(),
- ResponseHeaders: v.GetResponseHeader(),
- })
- }
- return out
- }
- func toRawLifecycle(l Lifecycle) *raw.BucketLifecycle {
- var rl raw.BucketLifecycle
- if len(l.Rules) == 0 {
- rl.ForceSendFields = []string{"Rule"}
- }
- for _, r := range l.Rules {
- rr := &raw.BucketLifecycleRule{
- Action: &raw.BucketLifecycleRuleAction{
- Type: r.Action.Type,
- StorageClass: r.Action.StorageClass,
- },
- Condition: &raw.BucketLifecycleRuleCondition{
- DaysSinceCustomTime: r.Condition.DaysSinceCustomTime,
- DaysSinceNoncurrentTime: r.Condition.DaysSinceNoncurrentTime,
- MatchesPrefix: r.Condition.MatchesPrefix,
- MatchesStorageClass: r.Condition.MatchesStorageClasses,
- MatchesSuffix: r.Condition.MatchesSuffix,
- NumNewerVersions: r.Condition.NumNewerVersions,
- },
- }
- // AllObjects takes precedent when both AllObjects and AgeInDays are set
- // Rationale: If you've opted into using AllObjects, it makes sense that you
- // understand the implications of how this option works with AgeInDays.
- if r.Condition.AllObjects {
- rr.Condition.Age = googleapi.Int64(0)
- rr.Condition.ForceSendFields = []string{"Age"}
- } else if r.Condition.AgeInDays > 0 {
- rr.Condition.Age = googleapi.Int64(r.Condition.AgeInDays)
- }
- switch r.Condition.Liveness {
- case LiveAndArchived:
- rr.Condition.IsLive = nil
- case Live:
- rr.Condition.IsLive = googleapi.Bool(true)
- case Archived:
- rr.Condition.IsLive = googleapi.Bool(false)
- }
- if !r.Condition.CreatedBefore.IsZero() {
- rr.Condition.CreatedBefore = r.Condition.CreatedBefore.Format(rfc3339Date)
- }
- if !r.Condition.CustomTimeBefore.IsZero() {
- rr.Condition.CustomTimeBefore = r.Condition.CustomTimeBefore.Format(rfc3339Date)
- }
- if !r.Condition.NoncurrentTimeBefore.IsZero() {
- rr.Condition.NoncurrentTimeBefore = r.Condition.NoncurrentTimeBefore.Format(rfc3339Date)
- }
- rl.Rule = append(rl.Rule, rr)
- }
- return &rl
- }
- func toProtoLifecycle(l Lifecycle) *storagepb.Bucket_Lifecycle {
- var rl storagepb.Bucket_Lifecycle
- for _, r := range l.Rules {
- rr := &storagepb.Bucket_Lifecycle_Rule{
- Action: &storagepb.Bucket_Lifecycle_Rule_Action{
- Type: r.Action.Type,
- StorageClass: r.Action.StorageClass,
- },
- Condition: &storagepb.Bucket_Lifecycle_Rule_Condition{
- // Note: The Apiary types use int64 (even though the Discovery
- // doc states "format: int32"), so the client types used int64,
- // but the proto uses int32 so we have a potentially lossy
- // conversion.
- DaysSinceCustomTime: proto.Int32(int32(r.Condition.DaysSinceCustomTime)),
- DaysSinceNoncurrentTime: proto.Int32(int32(r.Condition.DaysSinceNoncurrentTime)),
- MatchesPrefix: r.Condition.MatchesPrefix,
- MatchesStorageClass: r.Condition.MatchesStorageClasses,
- MatchesSuffix: r.Condition.MatchesSuffix,
- NumNewerVersions: proto.Int32(int32(r.Condition.NumNewerVersions)),
- },
- }
- // Only set AgeDays in the proto if it is non-zero, or if the user has set
- // Condition.AllObjects.
- if r.Condition.AgeInDays != 0 {
- rr.Condition.AgeDays = proto.Int32(int32(r.Condition.AgeInDays))
- }
- if r.Condition.AllObjects {
- rr.Condition.AgeDays = proto.Int32(0)
- }
- switch r.Condition.Liveness {
- case LiveAndArchived:
- rr.Condition.IsLive = nil
- case Live:
- rr.Condition.IsLive = proto.Bool(true)
- case Archived:
- rr.Condition.IsLive = proto.Bool(false)
- }
- if !r.Condition.CreatedBefore.IsZero() {
- rr.Condition.CreatedBefore = timeToProtoDate(r.Condition.CreatedBefore)
- }
- if !r.Condition.CustomTimeBefore.IsZero() {
- rr.Condition.CustomTimeBefore = timeToProtoDate(r.Condition.CustomTimeBefore)
- }
- if !r.Condition.NoncurrentTimeBefore.IsZero() {
- rr.Condition.NoncurrentTimeBefore = timeToProtoDate(r.Condition.NoncurrentTimeBefore)
- }
- rl.Rule = append(rl.Rule, rr)
- }
- return &rl
- }
- func toLifecycle(rl *raw.BucketLifecycle) Lifecycle {
- var l Lifecycle
- if rl == nil {
- return l
- }
- for _, rr := range rl.Rule {
- r := LifecycleRule{
- Action: LifecycleAction{
- Type: rr.Action.Type,
- StorageClass: rr.Action.StorageClass,
- },
- Condition: LifecycleCondition{
- DaysSinceCustomTime: rr.Condition.DaysSinceCustomTime,
- DaysSinceNoncurrentTime: rr.Condition.DaysSinceNoncurrentTime,
- MatchesPrefix: rr.Condition.MatchesPrefix,
- MatchesStorageClasses: rr.Condition.MatchesStorageClass,
- MatchesSuffix: rr.Condition.MatchesSuffix,
- NumNewerVersions: rr.Condition.NumNewerVersions,
- },
- }
- if rr.Condition.Age != nil {
- r.Condition.AgeInDays = *rr.Condition.Age
- if *rr.Condition.Age == 0 {
- r.Condition.AllObjects = true
- }
- }
- if rr.Condition.IsLive == nil {
- r.Condition.Liveness = LiveAndArchived
- } else if *rr.Condition.IsLive {
- r.Condition.Liveness = Live
- } else {
- r.Condition.Liveness = Archived
- }
- if rr.Condition.CreatedBefore != "" {
- r.Condition.CreatedBefore, _ = time.Parse(rfc3339Date, rr.Condition.CreatedBefore)
- }
- if rr.Condition.CustomTimeBefore != "" {
- r.Condition.CustomTimeBefore, _ = time.Parse(rfc3339Date, rr.Condition.CustomTimeBefore)
- }
- if rr.Condition.NoncurrentTimeBefore != "" {
- r.Condition.NoncurrentTimeBefore, _ = time.Parse(rfc3339Date, rr.Condition.NoncurrentTimeBefore)
- }
- l.Rules = append(l.Rules, r)
- }
- return l
- }
- func toLifecycleFromProto(rl *storagepb.Bucket_Lifecycle) Lifecycle {
- var l Lifecycle
- if rl == nil {
- return l
- }
- for _, rr := range rl.GetRule() {
- r := LifecycleRule{
- Action: LifecycleAction{
- Type: rr.GetAction().GetType(),
- StorageClass: rr.GetAction().GetStorageClass(),
- },
- Condition: LifecycleCondition{
- AgeInDays: int64(rr.GetCondition().GetAgeDays()),
- DaysSinceCustomTime: int64(rr.GetCondition().GetDaysSinceCustomTime()),
- DaysSinceNoncurrentTime: int64(rr.GetCondition().GetDaysSinceNoncurrentTime()),
- MatchesPrefix: rr.GetCondition().GetMatchesPrefix(),
- MatchesStorageClasses: rr.GetCondition().GetMatchesStorageClass(),
- MatchesSuffix: rr.GetCondition().GetMatchesSuffix(),
- NumNewerVersions: int64(rr.GetCondition().GetNumNewerVersions()),
- },
- }
- // Only set Condition.AllObjects if AgeDays is zero, not if it is nil.
- if rr.GetCondition().AgeDays != nil && rr.GetCondition().GetAgeDays() == 0 {
- r.Condition.AllObjects = true
- }
- if rr.GetCondition().IsLive == nil {
- r.Condition.Liveness = LiveAndArchived
- } else if rr.GetCondition().GetIsLive() {
- r.Condition.Liveness = Live
- } else {
- r.Condition.Liveness = Archived
- }
- if rr.GetCondition().GetCreatedBefore() != nil {
- r.Condition.CreatedBefore = protoDateToUTCTime(rr.GetCondition().GetCreatedBefore())
- }
- if rr.GetCondition().GetCustomTimeBefore() != nil {
- r.Condition.CustomTimeBefore = protoDateToUTCTime(rr.GetCondition().GetCustomTimeBefore())
- }
- if rr.GetCondition().GetNoncurrentTimeBefore() != nil {
- r.Condition.NoncurrentTimeBefore = protoDateToUTCTime(rr.GetCondition().GetNoncurrentTimeBefore())
- }
- l.Rules = append(l.Rules, r)
- }
- return l
- }
- func (e *BucketEncryption) toRawBucketEncryption() *raw.BucketEncryption {
- if e == nil {
- return nil
- }
- return &raw.BucketEncryption{
- DefaultKmsKeyName: e.DefaultKMSKeyName,
- }
- }
- func (e *BucketEncryption) toProtoBucketEncryption() *storagepb.Bucket_Encryption {
- if e == nil {
- return nil
- }
- return &storagepb.Bucket_Encryption{
- DefaultKmsKey: e.DefaultKMSKeyName,
- }
- }
- func toBucketEncryption(e *raw.BucketEncryption) *BucketEncryption {
- if e == nil {
- return nil
- }
- return &BucketEncryption{DefaultKMSKeyName: e.DefaultKmsKeyName}
- }
- func toBucketEncryptionFromProto(e *storagepb.Bucket_Encryption) *BucketEncryption {
- if e == nil {
- return nil
- }
- return &BucketEncryption{DefaultKMSKeyName: e.GetDefaultKmsKey()}
- }
- func (b *BucketLogging) toRawBucketLogging() *raw.BucketLogging {
- if b == nil {
- return nil
- }
- return &raw.BucketLogging{
- LogBucket: b.LogBucket,
- LogObjectPrefix: b.LogObjectPrefix,
- }
- }
- func (b *BucketLogging) toProtoBucketLogging() *storagepb.Bucket_Logging {
- if b == nil {
- return nil
- }
- return &storagepb.Bucket_Logging{
- LogBucket: bucketResourceName(globalProjectAlias, b.LogBucket),
- LogObjectPrefix: b.LogObjectPrefix,
- }
- }
- func toBucketLogging(b *raw.BucketLogging) *BucketLogging {
- if b == nil {
- return nil
- }
- return &BucketLogging{
- LogBucket: b.LogBucket,
- LogObjectPrefix: b.LogObjectPrefix,
- }
- }
- func toBucketLoggingFromProto(b *storagepb.Bucket_Logging) *BucketLogging {
- if b == nil {
- return nil
- }
- lb := parseBucketName(b.GetLogBucket())
- return &BucketLogging{
- LogBucket: lb,
- LogObjectPrefix: b.GetLogObjectPrefix(),
- }
- }
- func (w *BucketWebsite) toRawBucketWebsite() *raw.BucketWebsite {
- if w == nil {
- return nil
- }
- return &raw.BucketWebsite{
- MainPageSuffix: w.MainPageSuffix,
- NotFoundPage: w.NotFoundPage,
- }
- }
- func (w *BucketWebsite) toProtoBucketWebsite() *storagepb.Bucket_Website {
- if w == nil {
- return nil
- }
- return &storagepb.Bucket_Website{
- MainPageSuffix: w.MainPageSuffix,
- NotFoundPage: w.NotFoundPage,
- }
- }
- func toBucketWebsite(w *raw.BucketWebsite) *BucketWebsite {
- if w == nil {
- return nil
- }
- return &BucketWebsite{
- MainPageSuffix: w.MainPageSuffix,
- NotFoundPage: w.NotFoundPage,
- }
- }
- func toBucketWebsiteFromProto(w *storagepb.Bucket_Website) *BucketWebsite {
- if w == nil {
- return nil
- }
- return &BucketWebsite{
- MainPageSuffix: w.GetMainPageSuffix(),
- NotFoundPage: w.GetNotFoundPage(),
- }
- }
- func toBucketPolicyOnly(b *raw.BucketIamConfiguration) BucketPolicyOnly {
- if b == nil || b.BucketPolicyOnly == nil || !b.BucketPolicyOnly.Enabled {
- return BucketPolicyOnly{}
- }
- lt, err := time.Parse(time.RFC3339, b.BucketPolicyOnly.LockedTime)
- if err != nil {
- return BucketPolicyOnly{
- Enabled: true,
- }
- }
- return BucketPolicyOnly{
- Enabled: true,
- LockedTime: lt,
- }
- }
- func toBucketPolicyOnlyFromProto(b *storagepb.Bucket_IamConfig) BucketPolicyOnly {
- if b == nil || !b.GetUniformBucketLevelAccess().GetEnabled() {
- return BucketPolicyOnly{}
- }
- return BucketPolicyOnly{
- Enabled: true,
- LockedTime: b.GetUniformBucketLevelAccess().GetLockTime().AsTime(),
- }
- }
- func toUniformBucketLevelAccess(b *raw.BucketIamConfiguration) UniformBucketLevelAccess {
- if b == nil || b.UniformBucketLevelAccess == nil || !b.UniformBucketLevelAccess.Enabled {
- return UniformBucketLevelAccess{}
- }
- lt, err := time.Parse(time.RFC3339, b.UniformBucketLevelAccess.LockedTime)
- if err != nil {
- return UniformBucketLevelAccess{
- Enabled: true,
- }
- }
- return UniformBucketLevelAccess{
- Enabled: true,
- LockedTime: lt,
- }
- }
- func toUniformBucketLevelAccessFromProto(b *storagepb.Bucket_IamConfig) UniformBucketLevelAccess {
- if b == nil || !b.GetUniformBucketLevelAccess().GetEnabled() {
- return UniformBucketLevelAccess{}
- }
- return UniformBucketLevelAccess{
- Enabled: true,
- LockedTime: b.GetUniformBucketLevelAccess().GetLockTime().AsTime(),
- }
- }
- func toPublicAccessPrevention(b *raw.BucketIamConfiguration) PublicAccessPrevention {
- if b == nil {
- return PublicAccessPreventionUnknown
- }
- switch b.PublicAccessPrevention {
- case publicAccessPreventionInherited, publicAccessPreventionUnspecified:
- return PublicAccessPreventionInherited
- case publicAccessPreventionEnforced:
- return PublicAccessPreventionEnforced
- default:
- return PublicAccessPreventionUnknown
- }
- }
- func toPublicAccessPreventionFromProto(b *storagepb.Bucket_IamConfig) PublicAccessPrevention {
- if b == nil {
- return PublicAccessPreventionUnknown
- }
- switch b.GetPublicAccessPrevention() {
- case publicAccessPreventionInherited, publicAccessPreventionUnspecified:
- return PublicAccessPreventionInherited
- case publicAccessPreventionEnforced:
- return PublicAccessPreventionEnforced
- default:
- return PublicAccessPreventionUnknown
- }
- }
- func toRPO(b *raw.Bucket) RPO {
- if b == nil {
- return RPOUnknown
- }
- switch b.Rpo {
- case rpoDefault:
- return RPODefault
- case rpoAsyncTurbo:
- return RPOAsyncTurbo
- default:
- return RPOUnknown
- }
- }
- func toRPOFromProto(b *storagepb.Bucket) RPO {
- if b == nil {
- return RPOUnknown
- }
- switch b.GetRpo() {
- case rpoDefault:
- return RPODefault
- case rpoAsyncTurbo:
- return RPOAsyncTurbo
- default:
- return RPOUnknown
- }
- }
- func customPlacementFromRaw(c *raw.BucketCustomPlacementConfig) *CustomPlacementConfig {
- if c == nil {
- return nil
- }
- return &CustomPlacementConfig{DataLocations: c.DataLocations}
- }
- func (c *CustomPlacementConfig) toRawCustomPlacement() *raw.BucketCustomPlacementConfig {
- if c == nil {
- return nil
- }
- return &raw.BucketCustomPlacementConfig{
- DataLocations: c.DataLocations,
- }
- }
- func (c *CustomPlacementConfig) toProtoCustomPlacement() *storagepb.Bucket_CustomPlacementConfig {
- if c == nil {
- return nil
- }
- return &storagepb.Bucket_CustomPlacementConfig{
- DataLocations: c.DataLocations,
- }
- }
- func customPlacementFromProto(c *storagepb.Bucket_CustomPlacementConfig) *CustomPlacementConfig {
- if c == nil {
- return nil
- }
- return &CustomPlacementConfig{DataLocations: c.GetDataLocations()}
- }
- func (a *Autoclass) toRawAutoclass() *raw.BucketAutoclass {
- if a == nil {
- return nil
- }
- // Excluding read only fields ToggleTime and TerminalStorageClassUpdateTime.
- return &raw.BucketAutoclass{
- Enabled: a.Enabled,
- TerminalStorageClass: a.TerminalStorageClass,
- }
- }
- func (a *Autoclass) toProtoAutoclass() *storagepb.Bucket_Autoclass {
- if a == nil {
- return nil
- }
- // Excluding read only fields ToggleTime and TerminalStorageClassUpdateTime.
- ba := &storagepb.Bucket_Autoclass{
- Enabled: a.Enabled,
- }
- if a.TerminalStorageClass != "" {
- ba.TerminalStorageClass = &a.TerminalStorageClass
- }
- return ba
- }
- func toAutoclassFromRaw(a *raw.BucketAutoclass) *Autoclass {
- if a == nil || a.ToggleTime == "" {
- return nil
- }
- ac := &Autoclass{
- Enabled: a.Enabled,
- TerminalStorageClass: a.TerminalStorageClass,
- }
- // Return ToggleTime and TSCUpdateTime only if parsed with valid values.
- t, err := time.Parse(time.RFC3339, a.ToggleTime)
- if err == nil {
- ac.ToggleTime = t
- }
- ut, err := time.Parse(time.RFC3339, a.TerminalStorageClassUpdateTime)
- if err == nil {
- ac.TerminalStorageClassUpdateTime = ut
- }
- return ac
- }
- func toAutoclassFromProto(a *storagepb.Bucket_Autoclass) *Autoclass {
- if a == nil || a.GetToggleTime().AsTime().Unix() == 0 {
- return nil
- }
- return &Autoclass{
- Enabled: a.GetEnabled(),
- ToggleTime: a.GetToggleTime().AsTime(),
- TerminalStorageClass: a.GetTerminalStorageClass(),
- TerminalStorageClassUpdateTime: a.GetTerminalStorageClassUpdateTime().AsTime(),
- }
- }
- // Objects returns an iterator over the objects in the bucket that match the
- // Query q. If q is nil, no filtering is done. Objects will be iterated over
- // lexicographically by name.
- //
- // Note: The returned iterator is not safe for concurrent operations without explicit synchronization.
- func (b *BucketHandle) Objects(ctx context.Context, q *Query) *ObjectIterator {
- o := makeStorageOpts(true, b.retry, b.userProject)
- return b.c.tc.ListObjects(ctx, b.name, q, o...)
- }
- // Retryer returns a bucket handle that is configured with custom retry
- // behavior as specified by the options that are passed to it. All operations
- // on the new handle will use the customized retry configuration.
- // Retry options set on a object handle will take precedence over options set on
- // the bucket handle.
- // These retry options will merge with the client's retry configuration (if set)
- // for the returned handle. Options passed into this method will take precedence
- // over retry options on the client. Note that you must explicitly pass in each
- // option you want to override.
- func (b *BucketHandle) Retryer(opts ...RetryOption) *BucketHandle {
- b2 := *b
- var retry *retryConfig
- if b.retry != nil {
- // merge the options with the existing retry
- retry = b.retry
- } else {
- retry = &retryConfig{}
- }
- for _, opt := range opts {
- opt.apply(retry)
- }
- b2.retry = retry
- b2.acl.retry = retry
- b2.defaultObjectACL.retry = retry
- return &b2
- }
- // An ObjectIterator is an iterator over ObjectAttrs.
- //
- // Note: This iterator is not safe for concurrent operations without explicit synchronization.
- type ObjectIterator struct {
- ctx context.Context
- query Query
- pageInfo *iterator.PageInfo
- nextFunc func() error
- items []*ObjectAttrs
- }
- // PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
- //
- // Note: This method is not safe for concurrent operations without explicit synchronization.
- func (it *ObjectIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }
- // Next returns the next result. Its second return value is iterator.Done if
- // there are no more results. Once Next returns iterator.Done, all subsequent
- // calls will return iterator.Done.
- //
- // In addition, if Next returns an error other than iterator.Done, all
- // subsequent calls will return the same error. To continue iteration, a new
- // `ObjectIterator` must be created. Since objects are ordered lexicographically
- // by name, `Query.StartOffset` can be used to create a new iterator which will
- // start at the desired place. See
- // https://pkg.go.dev/cloud.google.com/go/storage?tab=doc#hdr-Listing_objects.
- //
- // If Query.Delimiter is non-empty, some of the ObjectAttrs returned by Next will
- // have a non-empty Prefix field, and a zero value for all other fields. These
- // represent prefixes.
- //
- // Note: This method is not safe for concurrent operations without explicit synchronization.
- func (it *ObjectIterator) Next() (*ObjectAttrs, error) {
- if err := it.nextFunc(); err != nil {
- return nil, err
- }
- item := it.items[0]
- it.items = it.items[1:]
- return item, nil
- }
- // Buckets returns an iterator over the buckets in the project. You may
- // optionally set the iterator's Prefix field to restrict the list to buckets
- // whose names begin with the prefix. By default, all buckets in the project
- // are returned.
- //
- // Note: The returned iterator is not safe for concurrent operations without explicit synchronization.
- func (c *Client) Buckets(ctx context.Context, projectID string) *BucketIterator {
- o := makeStorageOpts(true, c.retry, "")
- return c.tc.ListBuckets(ctx, projectID, o...)
- }
- // A BucketIterator is an iterator over BucketAttrs.
- //
- // Note: This iterator is not safe for concurrent operations without explicit synchronization.
- type BucketIterator struct {
- // Prefix restricts the iterator to buckets whose names begin with it.
- Prefix string
- ctx context.Context
- projectID string
- buckets []*BucketAttrs
- pageInfo *iterator.PageInfo
- nextFunc func() error
- }
- // Next returns the next result. Its second return value is iterator.Done if
- // there are no more results. Once Next returns iterator.Done, all subsequent
- // calls will return iterator.Done.
- //
- // Note: This method is not safe for concurrent operations without explicit synchronization.
- func (it *BucketIterator) Next() (*BucketAttrs, error) {
- if err := it.nextFunc(); err != nil {
- return nil, err
- }
- b := it.buckets[0]
- it.buckets = it.buckets[1:]
- return b, nil
- }
- // PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
- //
- // Note: This method is not safe for concurrent operations without explicit synchronization.
- func (it *BucketIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }
- // RPO (Recovery Point Objective) configures the turbo replication feature. See
- // https://cloud.google.com/storage/docs/managing-turbo-replication for more information.
- type RPO int
- const (
- // RPOUnknown is a zero value. It may be returned from bucket.Attrs() if RPO
- // is not present in the bucket metadata, that is, the bucket is not dual-region.
- // This value is also used if the RPO field is not set in a call to GCS.
- RPOUnknown RPO = iota
- // RPODefault represents default replication. It is used to reset RPO on an
- // existing bucket that has this field set to RPOAsyncTurbo. Otherwise it
- // is equivalent to RPOUnknown, and is always ignored. This value is valid
- // for dual- or multi-region buckets.
- RPODefault
- // RPOAsyncTurbo represents turbo replication and is used to enable Turbo
- // Replication on a bucket. This value is only valid for dual-region buckets.
- RPOAsyncTurbo
- rpoUnknown string = ""
- rpoDefault = "DEFAULT"
- rpoAsyncTurbo = "ASYNC_TURBO"
- )
- func (rpo RPO) String() string {
- switch rpo {
- case RPODefault:
- return rpoDefault
- case RPOAsyncTurbo:
- return rpoAsyncTurbo
- default:
- return rpoUnknown
- }
- }
- // protoDateToUTCTime returns a new Time based on the google.type.Date, in UTC.
- //
- // Hours, minutes, seconds, and nanoseconds are set to 0.
- func protoDateToUTCTime(d *dpb.Date) time.Time {
- return protoDateToTime(d, time.UTC)
- }
- // protoDateToTime returns a new Time based on the google.type.Date and provided
- // *time.Location.
- //
- // Hours, minutes, seconds, and nanoseconds are set to 0.
- func protoDateToTime(d *dpb.Date, l *time.Location) time.Time {
- return time.Date(int(d.GetYear()), time.Month(d.GetMonth()), int(d.GetDay()), 0, 0, 0, 0, l)
- }
- // timeToProtoDate returns a new google.type.Date based on the provided time.Time.
- // The location is ignored, as is anything more precise than the day.
- func timeToProtoDate(t time.Time) *dpb.Date {
- return &dpb.Date{
- Year: int32(t.Year()),
- Month: int32(t.Month()),
- Day: int32(t.Day()),
- }
- }
|