bucket.go 76 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237
  1. // Copyright 2014 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package storage
  15. import (
  16. "context"
  17. "encoding/base64"
  18. "encoding/json"
  19. "errors"
  20. "fmt"
  21. "reflect"
  22. "strings"
  23. "time"
  24. "cloud.google.com/go/compute/metadata"
  25. "cloud.google.com/go/internal/optional"
  26. "cloud.google.com/go/internal/trace"
  27. "cloud.google.com/go/storage/internal/apiv2/storagepb"
  28. "google.golang.org/api/googleapi"
  29. "google.golang.org/api/iamcredentials/v1"
  30. "google.golang.org/api/iterator"
  31. "google.golang.org/api/option"
  32. raw "google.golang.org/api/storage/v1"
  33. dpb "google.golang.org/genproto/googleapis/type/date"
  34. "google.golang.org/protobuf/proto"
  35. "google.golang.org/protobuf/types/known/durationpb"
  36. )
  37. // BucketHandle provides operations on a Google Cloud Storage bucket.
  38. // Use Client.Bucket to get a handle.
  39. type BucketHandle struct {
  40. c *Client
  41. name string
  42. acl ACLHandle
  43. defaultObjectACL ACLHandle
  44. conds *BucketConditions
  45. userProject string // project for Requester Pays buckets
  46. retry *retryConfig
  47. enableObjectRetention *bool
  48. }
  49. // Bucket returns a BucketHandle, which provides operations on the named bucket.
  50. // This call does not perform any network operations.
  51. //
  52. // The supplied name must contain only lowercase letters, numbers, dashes,
  53. // underscores, and dots. The full specification for valid bucket names can be
  54. // found at:
  55. //
  56. // https://cloud.google.com/storage/docs/bucket-naming
  57. func (c *Client) Bucket(name string) *BucketHandle {
  58. retry := c.retry.clone()
  59. return &BucketHandle{
  60. c: c,
  61. name: name,
  62. acl: ACLHandle{
  63. c: c,
  64. bucket: name,
  65. retry: retry,
  66. },
  67. defaultObjectACL: ACLHandle{
  68. c: c,
  69. bucket: name,
  70. isDefault: true,
  71. retry: retry,
  72. },
  73. retry: retry,
  74. }
  75. }
  76. // Create creates the Bucket in the project.
  77. // If attrs is nil the API defaults will be used.
  78. func (b *BucketHandle) Create(ctx context.Context, projectID string, attrs *BucketAttrs) (err error) {
  79. ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.Create")
  80. defer func() { trace.EndSpan(ctx, err) }()
  81. o := makeStorageOpts(true, b.retry, b.userProject)
  82. if _, err := b.c.tc.CreateBucket(ctx, projectID, b.name, attrs, b.enableObjectRetention, o...); err != nil {
  83. return err
  84. }
  85. return nil
  86. }
  87. // Delete deletes the Bucket.
  88. func (b *BucketHandle) Delete(ctx context.Context) (err error) {
  89. ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.Delete")
  90. defer func() { trace.EndSpan(ctx, err) }()
  91. o := makeStorageOpts(true, b.retry, b.userProject)
  92. return b.c.tc.DeleteBucket(ctx, b.name, b.conds, o...)
  93. }
  94. // ACL returns an ACLHandle, which provides access to the bucket's access control list.
  95. // This controls who can list, create or overwrite the objects in a bucket.
  96. // This call does not perform any network operations.
  97. func (b *BucketHandle) ACL() *ACLHandle {
  98. return &b.acl
  99. }
  100. // DefaultObjectACL returns an ACLHandle, which provides access to the bucket's default object ACLs.
  101. // These ACLs are applied to newly created objects in this bucket that do not have a defined ACL.
  102. // This call does not perform any network operations.
  103. func (b *BucketHandle) DefaultObjectACL() *ACLHandle {
  104. return &b.defaultObjectACL
  105. }
  106. // Object returns an ObjectHandle, which provides operations on the named object.
  107. // This call does not perform any network operations such as fetching the object or verifying its existence.
  108. // Use methods on ObjectHandle to perform network operations.
  109. //
  110. // name must consist entirely of valid UTF-8-encoded runes. The full specification
  111. // for valid object names can be found at:
  112. //
  113. // https://cloud.google.com/storage/docs/naming-objects
  114. func (b *BucketHandle) Object(name string) *ObjectHandle {
  115. retry := b.retry.clone()
  116. return &ObjectHandle{
  117. c: b.c,
  118. bucket: b.name,
  119. object: name,
  120. acl: ACLHandle{
  121. c: b.c,
  122. bucket: b.name,
  123. object: name,
  124. userProject: b.userProject,
  125. retry: retry,
  126. },
  127. gen: -1,
  128. userProject: b.userProject,
  129. retry: retry,
  130. }
  131. }
  132. // Attrs returns the metadata for the bucket.
  133. func (b *BucketHandle) Attrs(ctx context.Context) (attrs *BucketAttrs, err error) {
  134. ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.Attrs")
  135. defer func() { trace.EndSpan(ctx, err) }()
  136. o := makeStorageOpts(true, b.retry, b.userProject)
  137. return b.c.tc.GetBucket(ctx, b.name, b.conds, o...)
  138. }
  139. // Update updates a bucket's attributes.
  140. func (b *BucketHandle) Update(ctx context.Context, uattrs BucketAttrsToUpdate) (attrs *BucketAttrs, err error) {
  141. ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.Update")
  142. defer func() { trace.EndSpan(ctx, err) }()
  143. isIdempotent := b.conds != nil && b.conds.MetagenerationMatch != 0
  144. o := makeStorageOpts(isIdempotent, b.retry, b.userProject)
  145. return b.c.tc.UpdateBucket(ctx, b.name, &uattrs, b.conds, o...)
  146. }
  147. // SignedURL returns a URL for the specified object. Signed URLs allow anyone
  148. // access to a restricted resource for a limited time without needing a Google
  149. // account or signing in.
  150. // For more information about signed URLs, see "[Overview of access control]."
  151. //
  152. // This method requires the Method and Expires fields in the specified
  153. // SignedURLOptions to be non-nil. You may need to set the GoogleAccessID and
  154. // PrivateKey fields in some cases. Read more on the [automatic detection of credentials]
  155. // for this method.
  156. //
  157. // [Overview of access control]: https://cloud.google.com/storage/docs/accesscontrol#signed_urls_query_string_authentication
  158. // [automatic detection of credentials]: https://pkg.go.dev/cloud.google.com/go/storage#hdr-Credential_requirements_for_signing
  159. func (b *BucketHandle) SignedURL(object string, opts *SignedURLOptions) (string, error) {
  160. // Make a copy of opts so we don't modify the pointer parameter.
  161. newopts := opts.clone()
  162. if newopts.Hostname == "" {
  163. // Extract the correct host from the readhost set on the client
  164. newopts.Hostname = b.c.xmlHost
  165. }
  166. if opts.GoogleAccessID != "" && (opts.SignBytes != nil || len(opts.PrivateKey) > 0) {
  167. return SignedURL(b.name, object, newopts)
  168. }
  169. if newopts.GoogleAccessID == "" {
  170. id, err := b.detectDefaultGoogleAccessID()
  171. if err != nil {
  172. return "", err
  173. }
  174. newopts.GoogleAccessID = id
  175. }
  176. if newopts.SignBytes == nil && len(newopts.PrivateKey) == 0 {
  177. if b.c.creds != nil && len(b.c.creds.JSON) > 0 {
  178. var sa struct {
  179. PrivateKey string `json:"private_key"`
  180. }
  181. err := json.Unmarshal(b.c.creds.JSON, &sa)
  182. if err == nil && sa.PrivateKey != "" {
  183. newopts.PrivateKey = []byte(sa.PrivateKey)
  184. }
  185. }
  186. // Don't error out if we can't unmarshal the private key from the client,
  187. // fallback to the default sign function for the service account.
  188. if len(newopts.PrivateKey) == 0 {
  189. newopts.SignBytes = b.defaultSignBytesFunc(newopts.GoogleAccessID)
  190. }
  191. }
  192. return SignedURL(b.name, object, newopts)
  193. }
  194. // GenerateSignedPostPolicyV4 generates a PostPolicyV4 value from bucket, object and opts.
  195. // The generated URL and fields will then allow an unauthenticated client to perform multipart uploads.
  196. //
  197. // This method requires the Expires field in the specified PostPolicyV4Options
  198. // to be non-nil. You may need to set the GoogleAccessID and PrivateKey fields
  199. // in some cases. Read more on the [automatic detection of credentials] for this method.
  200. //
  201. // [automatic detection of credentials]: https://pkg.go.dev/cloud.google.com/go/storage#hdr-Credential_requirements_for_signing
  202. func (b *BucketHandle) GenerateSignedPostPolicyV4(object string, opts *PostPolicyV4Options) (*PostPolicyV4, error) {
  203. // Make a copy of opts so we don't modify the pointer parameter.
  204. newopts := opts.clone()
  205. if newopts.Hostname == "" {
  206. // Extract the correct host from the readhost set on the client
  207. newopts.Hostname = b.c.xmlHost
  208. }
  209. if opts.GoogleAccessID != "" && (opts.SignRawBytes != nil || opts.SignBytes != nil || len(opts.PrivateKey) > 0) {
  210. return GenerateSignedPostPolicyV4(b.name, object, newopts)
  211. }
  212. if newopts.GoogleAccessID == "" {
  213. id, err := b.detectDefaultGoogleAccessID()
  214. if err != nil {
  215. return nil, err
  216. }
  217. newopts.GoogleAccessID = id
  218. }
  219. if newopts.SignBytes == nil && newopts.SignRawBytes == nil && len(newopts.PrivateKey) == 0 {
  220. if b.c.creds != nil && len(b.c.creds.JSON) > 0 {
  221. var sa struct {
  222. PrivateKey string `json:"private_key"`
  223. }
  224. err := json.Unmarshal(b.c.creds.JSON, &sa)
  225. if err == nil && sa.PrivateKey != "" {
  226. newopts.PrivateKey = []byte(sa.PrivateKey)
  227. }
  228. }
  229. // Don't error out if we can't unmarshal the private key from the client,
  230. // fallback to the default sign function for the service account.
  231. if len(newopts.PrivateKey) == 0 {
  232. newopts.SignRawBytes = b.defaultSignBytesFunc(newopts.GoogleAccessID)
  233. }
  234. }
  235. return GenerateSignedPostPolicyV4(b.name, object, newopts)
  236. }
  237. func (b *BucketHandle) detectDefaultGoogleAccessID() (string, error) {
  238. returnErr := errors.New("no credentials found on client and not on GCE (Google Compute Engine)")
  239. if b.c.creds != nil && len(b.c.creds.JSON) > 0 {
  240. var sa struct {
  241. ClientEmail string `json:"client_email"`
  242. SAImpersonationURL string `json:"service_account_impersonation_url"`
  243. CredType string `json:"type"`
  244. }
  245. err := json.Unmarshal(b.c.creds.JSON, &sa)
  246. if err != nil {
  247. returnErr = err
  248. } else {
  249. switch sa.CredType {
  250. case "impersonated_service_account", "external_account":
  251. start, end := strings.LastIndex(sa.SAImpersonationURL, "/"), strings.LastIndex(sa.SAImpersonationURL, ":")
  252. if end <= start {
  253. returnErr = errors.New("error parsing external or impersonated service account credentials")
  254. } else {
  255. return sa.SAImpersonationURL[start+1 : end], nil
  256. }
  257. case "service_account":
  258. if sa.ClientEmail != "" {
  259. return sa.ClientEmail, nil
  260. }
  261. returnErr = errors.New("empty service account client email")
  262. default:
  263. returnErr = errors.New("unable to parse credentials; only service_account, external_account and impersonated_service_account credentials are supported")
  264. }
  265. }
  266. }
  267. // Don't error out if we can't unmarshal, fallback to GCE check.
  268. if metadata.OnGCE() {
  269. email, err := metadata.Email("default")
  270. if err == nil && email != "" {
  271. return email, nil
  272. } else if err != nil {
  273. returnErr = err
  274. } else {
  275. returnErr = errors.New("empty email from GCE metadata service")
  276. }
  277. }
  278. 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)
  279. }
  280. func (b *BucketHandle) defaultSignBytesFunc(email string) func([]byte) ([]byte, error) {
  281. return func(in []byte) ([]byte, error) {
  282. ctx := context.Background()
  283. // It's ok to recreate this service per call since we pass in the http client,
  284. // circumventing the cost of recreating the auth/transport layer
  285. svc, err := iamcredentials.NewService(ctx, option.WithHTTPClient(b.c.hc))
  286. if err != nil {
  287. return nil, fmt.Errorf("unable to create iamcredentials client: %w", err)
  288. }
  289. resp, err := svc.Projects.ServiceAccounts.SignBlob(fmt.Sprintf("projects/-/serviceAccounts/%s", email), &iamcredentials.SignBlobRequest{
  290. Payload: base64.StdEncoding.EncodeToString(in),
  291. }).Do()
  292. if err != nil {
  293. return nil, fmt.Errorf("unable to sign bytes: %w", err)
  294. }
  295. out, err := base64.StdEncoding.DecodeString(resp.SignedBlob)
  296. if err != nil {
  297. return nil, fmt.Errorf("unable to base64 decode response: %w", err)
  298. }
  299. return out, nil
  300. }
  301. }
  302. // BucketAttrs represents the metadata for a Google Cloud Storage bucket.
  303. // Read-only fields are ignored by BucketHandle.Create.
  304. type BucketAttrs struct {
  305. // Name is the name of the bucket.
  306. // This field is read-only.
  307. Name string
  308. // ACL is the list of access control rules on the bucket.
  309. ACL []ACLRule
  310. // BucketPolicyOnly is an alias for UniformBucketLevelAccess. Use of
  311. // UniformBucketLevelAccess is recommended above the use of this field.
  312. // Setting BucketPolicyOnly.Enabled OR UniformBucketLevelAccess.Enabled to
  313. // true, will enable UniformBucketLevelAccess.
  314. BucketPolicyOnly BucketPolicyOnly
  315. // UniformBucketLevelAccess configures access checks to use only bucket-level IAM
  316. // policies and ignore any ACL rules for the bucket.
  317. // See https://cloud.google.com/storage/docs/uniform-bucket-level-access
  318. // for more information.
  319. UniformBucketLevelAccess UniformBucketLevelAccess
  320. // PublicAccessPrevention is the setting for the bucket's
  321. // PublicAccessPrevention policy, which can be used to prevent public access
  322. // of data in the bucket. See
  323. // https://cloud.google.com/storage/docs/public-access-prevention for more
  324. // information.
  325. PublicAccessPrevention PublicAccessPrevention
  326. // DefaultObjectACL is the list of access controls to
  327. // apply to new objects when no object ACL is provided.
  328. DefaultObjectACL []ACLRule
  329. // DefaultEventBasedHold is the default value for event-based hold on
  330. // newly created objects in this bucket. It defaults to false.
  331. DefaultEventBasedHold bool
  332. // If not empty, applies a predefined set of access controls. It should be set
  333. // only when creating a bucket.
  334. // It is always empty for BucketAttrs returned from the service.
  335. // See https://cloud.google.com/storage/docs/json_api/v1/buckets/insert
  336. // for valid values.
  337. PredefinedACL string
  338. // If not empty, applies a predefined set of default object access controls.
  339. // It should be set only when creating a bucket.
  340. // It is always empty for BucketAttrs returned from the service.
  341. // See https://cloud.google.com/storage/docs/json_api/v1/buckets/insert
  342. // for valid values.
  343. PredefinedDefaultObjectACL string
  344. // Location is the location of the bucket. It defaults to "US".
  345. // If specifying a dual-region, CustomPlacementConfig should be set in conjunction.
  346. Location string
  347. // The bucket's custom placement configuration that holds a list of
  348. // regional locations for custom dual regions.
  349. CustomPlacementConfig *CustomPlacementConfig
  350. // MetaGeneration is the metadata generation of the bucket.
  351. // This field is read-only.
  352. MetaGeneration int64
  353. // StorageClass is the default storage class of the bucket. This defines
  354. // how objects in the bucket are stored and determines the SLA
  355. // and the cost of storage. Typical values are "STANDARD", "NEARLINE",
  356. // "COLDLINE" and "ARCHIVE". Defaults to "STANDARD".
  357. // See https://cloud.google.com/storage/docs/storage-classes for all
  358. // valid values.
  359. StorageClass string
  360. // Created is the creation time of the bucket.
  361. // This field is read-only.
  362. Created time.Time
  363. // VersioningEnabled reports whether this bucket has versioning enabled.
  364. VersioningEnabled bool
  365. // Labels are the bucket's labels.
  366. Labels map[string]string
  367. // RequesterPays reports whether the bucket is a Requester Pays bucket.
  368. // Clients performing operations on Requester Pays buckets must provide
  369. // a user project (see BucketHandle.UserProject), which will be billed
  370. // for the operations.
  371. RequesterPays bool
  372. // Lifecycle is the lifecycle configuration for objects in the bucket.
  373. Lifecycle Lifecycle
  374. // Retention policy enforces a minimum retention time for all objects
  375. // contained in the bucket. A RetentionPolicy of nil implies the bucket
  376. // has no minimum data retention.
  377. //
  378. // This feature is in private alpha release. It is not currently available to
  379. // most customers. It might be changed in backwards-incompatible ways and is not
  380. // subject to any SLA or deprecation policy.
  381. RetentionPolicy *RetentionPolicy
  382. // The bucket's Cross-Origin Resource Sharing (CORS) configuration.
  383. CORS []CORS
  384. // The encryption configuration used by default for newly inserted objects.
  385. Encryption *BucketEncryption
  386. // The logging configuration.
  387. Logging *BucketLogging
  388. // The website configuration.
  389. Website *BucketWebsite
  390. // Etag is the HTTP/1.1 Entity tag for the bucket.
  391. // This field is read-only.
  392. Etag string
  393. // LocationType describes how data is stored and replicated.
  394. // Typical values are "multi-region", "region" and "dual-region".
  395. // This field is read-only.
  396. LocationType string
  397. // The project number of the project the bucket belongs to.
  398. // This field is read-only.
  399. ProjectNumber uint64
  400. // RPO configures the Recovery Point Objective (RPO) policy of the bucket.
  401. // Set to RPOAsyncTurbo to turn on Turbo Replication for a bucket.
  402. // See https://cloud.google.com/storage/docs/managing-turbo-replication for
  403. // more information.
  404. RPO RPO
  405. // Autoclass holds the bucket's autoclass configuration. If enabled,
  406. // allows for the automatic selection of the best storage class
  407. // based on object access patterns.
  408. Autoclass *Autoclass
  409. // ObjectRetentionMode reports whether individual objects in the bucket can
  410. // be configured with a retention policy. An empty value means that object
  411. // retention is disabled.
  412. // This field is read-only. Object retention can be enabled only by creating
  413. // a bucket with SetObjectRetention set to true on the BucketHandle. It
  414. // cannot be modified once the bucket is created.
  415. // ObjectRetention cannot be configured or reported through the gRPC API.
  416. ObjectRetentionMode string
  417. }
  418. // BucketPolicyOnly is an alias for UniformBucketLevelAccess.
  419. // Use of UniformBucketLevelAccess is preferred above BucketPolicyOnly.
  420. type BucketPolicyOnly struct {
  421. // Enabled specifies whether access checks use only bucket-level IAM
  422. // policies. Enabled may be disabled until the locked time.
  423. Enabled bool
  424. // LockedTime specifies the deadline for changing Enabled from true to
  425. // false.
  426. LockedTime time.Time
  427. }
  428. // UniformBucketLevelAccess configures access checks to use only bucket-level IAM
  429. // policies.
  430. type UniformBucketLevelAccess struct {
  431. // Enabled specifies whether access checks use only bucket-level IAM
  432. // policies. Enabled may be disabled until the locked time.
  433. Enabled bool
  434. // LockedTime specifies the deadline for changing Enabled from true to
  435. // false.
  436. LockedTime time.Time
  437. }
  438. // PublicAccessPrevention configures the Public Access Prevention feature, which
  439. // can be used to disallow public access to any data in a bucket. See
  440. // https://cloud.google.com/storage/docs/public-access-prevention for more
  441. // information.
  442. type PublicAccessPrevention int
  443. const (
  444. // PublicAccessPreventionUnknown is a zero value, used only if this field is
  445. // not set in a call to GCS.
  446. PublicAccessPreventionUnknown PublicAccessPrevention = iota
  447. // PublicAccessPreventionUnspecified corresponds to a value of "unspecified".
  448. // Deprecated: use PublicAccessPreventionInherited
  449. PublicAccessPreventionUnspecified
  450. // PublicAccessPreventionEnforced corresponds to a value of "enforced". This
  451. // enforces Public Access Prevention on the bucket.
  452. PublicAccessPreventionEnforced
  453. // PublicAccessPreventionInherited corresponds to a value of "inherited"
  454. // and is the default for buckets.
  455. PublicAccessPreventionInherited
  456. publicAccessPreventionUnknown string = ""
  457. // TODO: remove unspecified when change is fully completed
  458. publicAccessPreventionUnspecified = "unspecified"
  459. publicAccessPreventionEnforced = "enforced"
  460. publicAccessPreventionInherited = "inherited"
  461. )
  462. func (p PublicAccessPrevention) String() string {
  463. switch p {
  464. case PublicAccessPreventionInherited, PublicAccessPreventionUnspecified:
  465. return publicAccessPreventionInherited
  466. case PublicAccessPreventionEnforced:
  467. return publicAccessPreventionEnforced
  468. default:
  469. return publicAccessPreventionUnknown
  470. }
  471. }
  472. // Lifecycle is the lifecycle configuration for objects in the bucket.
  473. type Lifecycle struct {
  474. Rules []LifecycleRule
  475. }
  476. // RetentionPolicy enforces a minimum retention time for all objects
  477. // contained in the bucket.
  478. //
  479. // Any attempt to overwrite or delete objects younger than the retention
  480. // period will result in an error. An unlocked retention policy can be
  481. // modified or removed from the bucket via the Update method. A
  482. // locked retention policy cannot be removed or shortened in duration
  483. // for the lifetime of the bucket.
  484. //
  485. // This feature is in private alpha release. It is not currently available to
  486. // most customers. It might be changed in backwards-incompatible ways and is not
  487. // subject to any SLA or deprecation policy.
  488. type RetentionPolicy struct {
  489. // RetentionPeriod specifies the duration that objects need to be
  490. // retained. Retention duration must be greater than zero and less than
  491. // 100 years. Note that enforcement of retention periods less than a day
  492. // is not guaranteed. Such periods should only be used for testing
  493. // purposes.
  494. RetentionPeriod time.Duration
  495. // EffectiveTime is the time from which the policy was enforced and
  496. // effective. This field is read-only.
  497. EffectiveTime time.Time
  498. // IsLocked describes whether the bucket is locked. Once locked, an
  499. // object retention policy cannot be modified.
  500. // This field is read-only.
  501. IsLocked bool
  502. }
  503. const (
  504. // RFC3339 timestamp with only the date segment, used for CreatedBefore,
  505. // CustomTimeBefore, and NoncurrentTimeBefore in LifecycleRule.
  506. rfc3339Date = "2006-01-02"
  507. // DeleteAction is a lifecycle action that deletes a live and/or archived
  508. // objects. Takes precedence over SetStorageClass actions.
  509. DeleteAction = "Delete"
  510. // SetStorageClassAction changes the storage class of live and/or archived
  511. // objects.
  512. SetStorageClassAction = "SetStorageClass"
  513. // AbortIncompleteMPUAction is a lifecycle action that aborts an incomplete
  514. // multipart upload when the multipart upload meets the conditions specified
  515. // in the lifecycle rule. The AgeInDays condition is the only allowed
  516. // condition for this action. AgeInDays is measured from the time the
  517. // multipart upload was created.
  518. AbortIncompleteMPUAction = "AbortIncompleteMultipartUpload"
  519. )
  520. // LifecycleRule is a lifecycle configuration rule.
  521. //
  522. // When all the configured conditions are met by an object in the bucket, the
  523. // configured action will automatically be taken on that object.
  524. type LifecycleRule struct {
  525. // Action is the action to take when all of the associated conditions are
  526. // met.
  527. Action LifecycleAction
  528. // Condition is the set of conditions that must be met for the associated
  529. // action to be taken.
  530. Condition LifecycleCondition
  531. }
  532. // LifecycleAction is a lifecycle configuration action.
  533. type LifecycleAction struct {
  534. // Type is the type of action to take on matching objects.
  535. //
  536. // Acceptable values are storage.DeleteAction, storage.SetStorageClassAction,
  537. // and storage.AbortIncompleteMPUAction.
  538. Type string
  539. // StorageClass is the storage class to set on matching objects if the Action
  540. // is "SetStorageClass".
  541. StorageClass string
  542. }
  543. // Liveness specifies whether the object is live or not.
  544. type Liveness int
  545. const (
  546. // LiveAndArchived includes both live and archived objects.
  547. LiveAndArchived Liveness = iota
  548. // Live specifies that the object is still live.
  549. Live
  550. // Archived specifies that the object is archived.
  551. Archived
  552. )
  553. // LifecycleCondition is a set of conditions used to match objects and take an
  554. // action automatically.
  555. //
  556. // All configured conditions must be met for the associated action to be taken.
  557. type LifecycleCondition struct {
  558. // AllObjects is used to select all objects in a bucket by
  559. // setting AgeInDays to 0.
  560. AllObjects bool
  561. // AgeInDays is the age of the object in days.
  562. // If you want to set AgeInDays to `0` use AllObjects set to `true`.
  563. AgeInDays int64
  564. // CreatedBefore is the time the object was created.
  565. //
  566. // This condition is satisfied when an object is created before midnight of
  567. // the specified date in UTC.
  568. CreatedBefore time.Time
  569. // CustomTimeBefore is the CustomTime metadata field of the object. This
  570. // condition is satisfied when an object's CustomTime timestamp is before
  571. // midnight of the specified date in UTC.
  572. //
  573. // This condition can only be satisfied if CustomTime has been set.
  574. CustomTimeBefore time.Time
  575. // DaysSinceCustomTime is the days elapsed since the CustomTime date of the
  576. // object. This condition can only be satisfied if CustomTime has been set.
  577. // Note: Using `0` as the value will be ignored by the library and not sent to the API.
  578. DaysSinceCustomTime int64
  579. // DaysSinceNoncurrentTime is the days elapsed since the noncurrent timestamp
  580. // of the object. This condition is relevant only for versioned objects.
  581. // Note: Using `0` as the value will be ignored by the library and not sent to the API.
  582. DaysSinceNoncurrentTime int64
  583. // Liveness specifies the object's liveness. Relevant only for versioned objects
  584. Liveness Liveness
  585. // MatchesPrefix is the condition matching an object if any of the
  586. // matches_prefix strings are an exact prefix of the object's name.
  587. MatchesPrefix []string
  588. // MatchesStorageClasses is the condition matching the object's storage
  589. // class.
  590. //
  591. // Values include "STANDARD", "NEARLINE", "COLDLINE" and "ARCHIVE".
  592. MatchesStorageClasses []string
  593. // MatchesSuffix is the condition matching an object if any of the
  594. // matches_suffix strings are an exact suffix of the object's name.
  595. MatchesSuffix []string
  596. // NoncurrentTimeBefore is the noncurrent timestamp of the object. This
  597. // condition is satisfied when an object's noncurrent timestamp is before
  598. // midnight of the specified date in UTC.
  599. //
  600. // This condition is relevant only for versioned objects.
  601. NoncurrentTimeBefore time.Time
  602. // NumNewerVersions is the condition matching objects with a number of newer versions.
  603. //
  604. // If the value is N, this condition is satisfied when there are at least N
  605. // versions (including the live version) newer than this version of the
  606. // object.
  607. // Note: Using `0` as the value will be ignored by the library and not sent to the API.
  608. NumNewerVersions int64
  609. }
  610. // BucketLogging holds the bucket's logging configuration, which defines the
  611. // destination bucket and optional name prefix for the current bucket's
  612. // logs.
  613. type BucketLogging struct {
  614. // The destination bucket where the current bucket's logs
  615. // should be placed.
  616. LogBucket string
  617. // A prefix for log object names.
  618. LogObjectPrefix string
  619. }
  620. // BucketWebsite holds the bucket's website configuration, controlling how the
  621. // service behaves when accessing bucket contents as a web site. See
  622. // https://cloud.google.com/storage/docs/static-website for more information.
  623. type BucketWebsite struct {
  624. // If the requested object path is missing, the service will ensure the path has
  625. // a trailing '/', append this suffix, and attempt to retrieve the resulting
  626. // object. This allows the creation of index.html objects to represent directory
  627. // pages.
  628. MainPageSuffix string
  629. // If the requested object path is missing, and any mainPageSuffix object is
  630. // missing, if applicable, the service will return the named object from this
  631. // bucket as the content for a 404 Not Found result.
  632. NotFoundPage string
  633. }
  634. // CustomPlacementConfig holds the bucket's custom placement
  635. // configuration for Custom Dual Regions. See
  636. // https://cloud.google.com/storage/docs/locations#location-dr for more information.
  637. type CustomPlacementConfig struct {
  638. // The list of regional locations in which data is placed.
  639. // Custom Dual Regions require exactly 2 regional locations.
  640. DataLocations []string
  641. }
  642. // Autoclass holds the bucket's autoclass configuration. If enabled,
  643. // allows for the automatic selection of the best storage class
  644. // based on object access patterns. See
  645. // https://cloud.google.com/storage/docs/using-autoclass for more information.
  646. type Autoclass struct {
  647. // Enabled specifies whether the autoclass feature is enabled
  648. // on the bucket.
  649. Enabled bool
  650. // ToggleTime is the time from which Autoclass was last toggled.
  651. // If Autoclass is enabled when the bucket is created, the ToggleTime
  652. // is set to the bucket creation time. This field is read-only.
  653. ToggleTime time.Time
  654. // TerminalStorageClass: The storage class that objects in the bucket
  655. // eventually transition to if they are not read for a certain length of
  656. // time. Valid values are NEARLINE and ARCHIVE.
  657. TerminalStorageClass string
  658. // TerminalStorageClassUpdateTime represents the time of the most recent
  659. // update to "TerminalStorageClass".
  660. TerminalStorageClassUpdateTime time.Time
  661. }
  662. func newBucket(b *raw.Bucket) (*BucketAttrs, error) {
  663. if b == nil {
  664. return nil, nil
  665. }
  666. rp, err := toRetentionPolicy(b.RetentionPolicy)
  667. if err != nil {
  668. return nil, err
  669. }
  670. return &BucketAttrs{
  671. Name: b.Name,
  672. Location: b.Location,
  673. MetaGeneration: b.Metageneration,
  674. DefaultEventBasedHold: b.DefaultEventBasedHold,
  675. StorageClass: b.StorageClass,
  676. Created: convertTime(b.TimeCreated),
  677. VersioningEnabled: b.Versioning != nil && b.Versioning.Enabled,
  678. ACL: toBucketACLRules(b.Acl),
  679. DefaultObjectACL: toObjectACLRules(b.DefaultObjectAcl),
  680. Labels: b.Labels,
  681. RequesterPays: b.Billing != nil && b.Billing.RequesterPays,
  682. Lifecycle: toLifecycle(b.Lifecycle),
  683. RetentionPolicy: rp,
  684. ObjectRetentionMode: toBucketObjectRetention(b.ObjectRetention),
  685. CORS: toCORS(b.Cors),
  686. Encryption: toBucketEncryption(b.Encryption),
  687. Logging: toBucketLogging(b.Logging),
  688. Website: toBucketWebsite(b.Website),
  689. BucketPolicyOnly: toBucketPolicyOnly(b.IamConfiguration),
  690. UniformBucketLevelAccess: toUniformBucketLevelAccess(b.IamConfiguration),
  691. PublicAccessPrevention: toPublicAccessPrevention(b.IamConfiguration),
  692. Etag: b.Etag,
  693. LocationType: b.LocationType,
  694. ProjectNumber: b.ProjectNumber,
  695. RPO: toRPO(b),
  696. CustomPlacementConfig: customPlacementFromRaw(b.CustomPlacementConfig),
  697. Autoclass: toAutoclassFromRaw(b.Autoclass),
  698. }, nil
  699. }
  700. func newBucketFromProto(b *storagepb.Bucket) *BucketAttrs {
  701. if b == nil {
  702. return nil
  703. }
  704. return &BucketAttrs{
  705. Name: parseBucketName(b.GetName()),
  706. Location: b.GetLocation(),
  707. MetaGeneration: b.GetMetageneration(),
  708. DefaultEventBasedHold: b.GetDefaultEventBasedHold(),
  709. StorageClass: b.GetStorageClass(),
  710. Created: b.GetCreateTime().AsTime(),
  711. VersioningEnabled: b.GetVersioning().GetEnabled(),
  712. ACL: toBucketACLRulesFromProto(b.GetAcl()),
  713. DefaultObjectACL: toObjectACLRulesFromProto(b.GetDefaultObjectAcl()),
  714. Labels: b.GetLabels(),
  715. RequesterPays: b.GetBilling().GetRequesterPays(),
  716. Lifecycle: toLifecycleFromProto(b.GetLifecycle()),
  717. RetentionPolicy: toRetentionPolicyFromProto(b.GetRetentionPolicy()),
  718. CORS: toCORSFromProto(b.GetCors()),
  719. Encryption: toBucketEncryptionFromProto(b.GetEncryption()),
  720. Logging: toBucketLoggingFromProto(b.GetLogging()),
  721. Website: toBucketWebsiteFromProto(b.GetWebsite()),
  722. BucketPolicyOnly: toBucketPolicyOnlyFromProto(b.GetIamConfig()),
  723. UniformBucketLevelAccess: toUniformBucketLevelAccessFromProto(b.GetIamConfig()),
  724. PublicAccessPrevention: toPublicAccessPreventionFromProto(b.GetIamConfig()),
  725. LocationType: b.GetLocationType(),
  726. RPO: toRPOFromProto(b),
  727. CustomPlacementConfig: customPlacementFromProto(b.GetCustomPlacementConfig()),
  728. ProjectNumber: parseProjectNumber(b.GetProject()), // this can return 0 the project resource name is ID based
  729. Autoclass: toAutoclassFromProto(b.GetAutoclass()),
  730. }
  731. }
  732. // toRawBucket copies the editable attribute from b to the raw library's Bucket type.
  733. func (b *BucketAttrs) toRawBucket() *raw.Bucket {
  734. // Copy label map.
  735. var labels map[string]string
  736. if len(b.Labels) > 0 {
  737. labels = make(map[string]string, len(b.Labels))
  738. for k, v := range b.Labels {
  739. labels[k] = v
  740. }
  741. }
  742. // Ignore VersioningEnabled if it is false. This is OK because
  743. // we only call this method when creating a bucket, and by default
  744. // new buckets have versioning off.
  745. var v *raw.BucketVersioning
  746. if b.VersioningEnabled {
  747. v = &raw.BucketVersioning{Enabled: true}
  748. }
  749. var bb *raw.BucketBilling
  750. if b.RequesterPays {
  751. bb = &raw.BucketBilling{RequesterPays: true}
  752. }
  753. var bktIAM *raw.BucketIamConfiguration
  754. if b.UniformBucketLevelAccess.Enabled || b.BucketPolicyOnly.Enabled || b.PublicAccessPrevention != PublicAccessPreventionUnknown {
  755. bktIAM = &raw.BucketIamConfiguration{}
  756. if b.UniformBucketLevelAccess.Enabled || b.BucketPolicyOnly.Enabled {
  757. bktIAM.UniformBucketLevelAccess = &raw.BucketIamConfigurationUniformBucketLevelAccess{
  758. Enabled: true,
  759. }
  760. }
  761. if b.PublicAccessPrevention != PublicAccessPreventionUnknown {
  762. bktIAM.PublicAccessPrevention = b.PublicAccessPrevention.String()
  763. }
  764. }
  765. return &raw.Bucket{
  766. Name: b.Name,
  767. Location: b.Location,
  768. StorageClass: b.StorageClass,
  769. Acl: toRawBucketACL(b.ACL),
  770. DefaultObjectAcl: toRawObjectACL(b.DefaultObjectACL),
  771. Versioning: v,
  772. Labels: labels,
  773. Billing: bb,
  774. Lifecycle: toRawLifecycle(b.Lifecycle),
  775. RetentionPolicy: b.RetentionPolicy.toRawRetentionPolicy(),
  776. Cors: toRawCORS(b.CORS),
  777. Encryption: b.Encryption.toRawBucketEncryption(),
  778. Logging: b.Logging.toRawBucketLogging(),
  779. Website: b.Website.toRawBucketWebsite(),
  780. IamConfiguration: bktIAM,
  781. Rpo: b.RPO.String(),
  782. CustomPlacementConfig: b.CustomPlacementConfig.toRawCustomPlacement(),
  783. Autoclass: b.Autoclass.toRawAutoclass(),
  784. }
  785. }
  786. func (b *BucketAttrs) toProtoBucket() *storagepb.Bucket {
  787. if b == nil {
  788. return &storagepb.Bucket{}
  789. }
  790. // Copy label map.
  791. var labels map[string]string
  792. if len(b.Labels) > 0 {
  793. labels = make(map[string]string, len(b.Labels))
  794. for k, v := range b.Labels {
  795. labels[k] = v
  796. }
  797. }
  798. // Ignore VersioningEnabled if it is false. This is OK because
  799. // we only call this method when creating a bucket, and by default
  800. // new buckets have versioning off.
  801. var v *storagepb.Bucket_Versioning
  802. if b.VersioningEnabled {
  803. v = &storagepb.Bucket_Versioning{Enabled: true}
  804. }
  805. var bb *storagepb.Bucket_Billing
  806. if b.RequesterPays {
  807. bb = &storagepb.Bucket_Billing{RequesterPays: true}
  808. }
  809. var bktIAM *storagepb.Bucket_IamConfig
  810. if b.UniformBucketLevelAccess.Enabled || b.BucketPolicyOnly.Enabled || b.PublicAccessPrevention != PublicAccessPreventionUnknown {
  811. bktIAM = &storagepb.Bucket_IamConfig{}
  812. if b.UniformBucketLevelAccess.Enabled || b.BucketPolicyOnly.Enabled {
  813. bktIAM.UniformBucketLevelAccess = &storagepb.Bucket_IamConfig_UniformBucketLevelAccess{
  814. Enabled: true,
  815. }
  816. }
  817. if b.PublicAccessPrevention != PublicAccessPreventionUnknown {
  818. bktIAM.PublicAccessPrevention = b.PublicAccessPrevention.String()
  819. }
  820. }
  821. return &storagepb.Bucket{
  822. Name: b.Name,
  823. Location: b.Location,
  824. StorageClass: b.StorageClass,
  825. Acl: toProtoBucketACL(b.ACL),
  826. DefaultObjectAcl: toProtoObjectACL(b.DefaultObjectACL),
  827. Versioning: v,
  828. Labels: labels,
  829. Billing: bb,
  830. Lifecycle: toProtoLifecycle(b.Lifecycle),
  831. RetentionPolicy: b.RetentionPolicy.toProtoRetentionPolicy(),
  832. Cors: toProtoCORS(b.CORS),
  833. Encryption: b.Encryption.toProtoBucketEncryption(),
  834. Logging: b.Logging.toProtoBucketLogging(),
  835. Website: b.Website.toProtoBucketWebsite(),
  836. IamConfig: bktIAM,
  837. Rpo: b.RPO.String(),
  838. CustomPlacementConfig: b.CustomPlacementConfig.toProtoCustomPlacement(),
  839. Autoclass: b.Autoclass.toProtoAutoclass(),
  840. }
  841. }
  842. func (ua *BucketAttrsToUpdate) toProtoBucket() *storagepb.Bucket {
  843. if ua == nil {
  844. return &storagepb.Bucket{}
  845. }
  846. var v *storagepb.Bucket_Versioning
  847. if ua.VersioningEnabled != nil {
  848. v = &storagepb.Bucket_Versioning{Enabled: optional.ToBool(ua.VersioningEnabled)}
  849. }
  850. var bb *storagepb.Bucket_Billing
  851. if ua.RequesterPays != nil {
  852. bb = &storagepb.Bucket_Billing{RequesterPays: optional.ToBool(ua.RequesterPays)}
  853. }
  854. var bktIAM *storagepb.Bucket_IamConfig
  855. if ua.UniformBucketLevelAccess != nil || ua.BucketPolicyOnly != nil || ua.PublicAccessPrevention != PublicAccessPreventionUnknown {
  856. bktIAM = &storagepb.Bucket_IamConfig{}
  857. if ua.BucketPolicyOnly != nil {
  858. bktIAM.UniformBucketLevelAccess = &storagepb.Bucket_IamConfig_UniformBucketLevelAccess{
  859. Enabled: optional.ToBool(ua.BucketPolicyOnly.Enabled),
  860. }
  861. }
  862. if ua.UniformBucketLevelAccess != nil {
  863. // UniformBucketLevelAccess takes precedence over BucketPolicyOnly,
  864. // so Enabled will be overriden here if both are set
  865. bktIAM.UniformBucketLevelAccess = &storagepb.Bucket_IamConfig_UniformBucketLevelAccess{
  866. Enabled: optional.ToBool(ua.UniformBucketLevelAccess.Enabled),
  867. }
  868. }
  869. if ua.PublicAccessPrevention != PublicAccessPreventionUnknown {
  870. bktIAM.PublicAccessPrevention = ua.PublicAccessPrevention.String()
  871. }
  872. }
  873. var defaultHold bool
  874. if ua.DefaultEventBasedHold != nil {
  875. defaultHold = optional.ToBool(ua.DefaultEventBasedHold)
  876. }
  877. var lifecycle Lifecycle
  878. if ua.Lifecycle != nil {
  879. lifecycle = *ua.Lifecycle
  880. }
  881. var bktACL []*storagepb.BucketAccessControl
  882. if ua.acl != nil {
  883. bktACL = toProtoBucketACL(ua.acl)
  884. }
  885. if ua.PredefinedACL != "" {
  886. // Clear ACL or the call will fail.
  887. bktACL = nil
  888. }
  889. var bktDefaultObjectACL []*storagepb.ObjectAccessControl
  890. if ua.defaultObjectACL != nil {
  891. bktDefaultObjectACL = toProtoObjectACL(ua.defaultObjectACL)
  892. }
  893. if ua.PredefinedDefaultObjectACL != "" {
  894. // Clear ACLs or the call will fail.
  895. bktDefaultObjectACL = nil
  896. }
  897. return &storagepb.Bucket{
  898. StorageClass: ua.StorageClass,
  899. Acl: bktACL,
  900. DefaultObjectAcl: bktDefaultObjectACL,
  901. DefaultEventBasedHold: defaultHold,
  902. Versioning: v,
  903. Billing: bb,
  904. Lifecycle: toProtoLifecycle(lifecycle),
  905. RetentionPolicy: ua.RetentionPolicy.toProtoRetentionPolicy(),
  906. Cors: toProtoCORS(ua.CORS),
  907. Encryption: ua.Encryption.toProtoBucketEncryption(),
  908. Logging: ua.Logging.toProtoBucketLogging(),
  909. Website: ua.Website.toProtoBucketWebsite(),
  910. IamConfig: bktIAM,
  911. Rpo: ua.RPO.String(),
  912. Autoclass: ua.Autoclass.toProtoAutoclass(),
  913. Labels: ua.setLabels,
  914. }
  915. }
  916. // CORS is the bucket's Cross-Origin Resource Sharing (CORS) configuration.
  917. type CORS struct {
  918. // MaxAge is the value to return in the Access-Control-Max-Age
  919. // header used in preflight responses.
  920. MaxAge time.Duration
  921. // Methods is the list of HTTP methods on which to include CORS response
  922. // headers, (GET, OPTIONS, POST, etc) Note: "*" is permitted in the list
  923. // of methods, and means "any method".
  924. Methods []string
  925. // Origins is the list of Origins eligible to receive CORS response
  926. // headers. Note: "*" is permitted in the list of origins, and means
  927. // "any Origin".
  928. Origins []string
  929. // ResponseHeaders is the list of HTTP headers other than the simple
  930. // response headers to give permission for the user-agent to share
  931. // across domains.
  932. ResponseHeaders []string
  933. }
  934. // BucketEncryption is a bucket's encryption configuration.
  935. type BucketEncryption struct {
  936. // A Cloud KMS key name, in the form
  937. // projects/P/locations/L/keyRings/R/cryptoKeys/K, that will be used to encrypt
  938. // objects inserted into this bucket, if no encryption method is specified.
  939. // The key's location must be the same as the bucket's.
  940. DefaultKMSKeyName string
  941. }
  942. // BucketAttrsToUpdate define the attributes to update during an Update call.
  943. type BucketAttrsToUpdate struct {
  944. // If set, updates whether the bucket uses versioning.
  945. VersioningEnabled optional.Bool
  946. // If set, updates whether the bucket is a Requester Pays bucket.
  947. RequesterPays optional.Bool
  948. // DefaultEventBasedHold is the default value for event-based hold on
  949. // newly created objects in this bucket.
  950. DefaultEventBasedHold optional.Bool
  951. // BucketPolicyOnly is an alias for UniformBucketLevelAccess. Use of
  952. // UniformBucketLevelAccess is recommended above the use of this field.
  953. // Setting BucketPolicyOnly.Enabled OR UniformBucketLevelAccess.Enabled to
  954. // true, will enable UniformBucketLevelAccess. If both BucketPolicyOnly and
  955. // UniformBucketLevelAccess are set, the value of UniformBucketLevelAccess
  956. // will take precedence.
  957. BucketPolicyOnly *BucketPolicyOnly
  958. // UniformBucketLevelAccess configures access checks to use only bucket-level IAM
  959. // policies and ignore any ACL rules for the bucket.
  960. // See https://cloud.google.com/storage/docs/uniform-bucket-level-access
  961. // for more information.
  962. UniformBucketLevelAccess *UniformBucketLevelAccess
  963. // PublicAccessPrevention is the setting for the bucket's
  964. // PublicAccessPrevention policy, which can be used to prevent public access
  965. // of data in the bucket. See
  966. // https://cloud.google.com/storage/docs/public-access-prevention for more
  967. // information.
  968. PublicAccessPrevention PublicAccessPrevention
  969. // StorageClass is the default storage class of the bucket. This defines
  970. // how objects in the bucket are stored and determines the SLA
  971. // and the cost of storage. Typical values are "STANDARD", "NEARLINE",
  972. // "COLDLINE" and "ARCHIVE". Defaults to "STANDARD".
  973. // See https://cloud.google.com/storage/docs/storage-classes for all
  974. // valid values.
  975. StorageClass string
  976. // If set, updates the retention policy of the bucket. Using
  977. // RetentionPolicy.RetentionPeriod = 0 will delete the existing policy.
  978. //
  979. // This feature is in private alpha release. It is not currently available to
  980. // most customers. It might be changed in backwards-incompatible ways and is not
  981. // subject to any SLA or deprecation policy.
  982. RetentionPolicy *RetentionPolicy
  983. // If set, replaces the CORS configuration with a new configuration.
  984. // An empty (rather than nil) slice causes all CORS policies to be removed.
  985. CORS []CORS
  986. // If set, replaces the encryption configuration of the bucket. Using
  987. // BucketEncryption.DefaultKMSKeyName = "" will delete the existing
  988. // configuration.
  989. Encryption *BucketEncryption
  990. // If set, replaces the lifecycle configuration of the bucket.
  991. Lifecycle *Lifecycle
  992. // If set, replaces the logging configuration of the bucket.
  993. Logging *BucketLogging
  994. // If set, replaces the website configuration of the bucket.
  995. Website *BucketWebsite
  996. // If not empty, applies a predefined set of access controls.
  997. // See https://cloud.google.com/storage/docs/json_api/v1/buckets/patch.
  998. PredefinedACL string
  999. // If not empty, applies a predefined set of default object access controls.
  1000. // See https://cloud.google.com/storage/docs/json_api/v1/buckets/patch.
  1001. PredefinedDefaultObjectACL string
  1002. // RPO configures the Recovery Point Objective (RPO) policy of the bucket.
  1003. // Set to RPOAsyncTurbo to turn on Turbo Replication for a bucket.
  1004. // See https://cloud.google.com/storage/docs/managing-turbo-replication for
  1005. // more information.
  1006. RPO RPO
  1007. // If set, updates the autoclass configuration of the bucket.
  1008. // See https://cloud.google.com/storage/docs/using-autoclass for more information.
  1009. Autoclass *Autoclass
  1010. // acl is the list of access control rules on the bucket.
  1011. // It is unexported and only used internally by the gRPC client.
  1012. // Library users should use ACLHandle methods directly.
  1013. acl []ACLRule
  1014. // defaultObjectACL is the list of access controls to
  1015. // apply to new objects when no object ACL is provided.
  1016. // It is unexported and only used internally by the gRPC client.
  1017. // Library users should use ACLHandle methods directly.
  1018. defaultObjectACL []ACLRule
  1019. setLabels map[string]string
  1020. deleteLabels map[string]bool
  1021. }
  1022. // SetLabel causes a label to be added or modified when ua is used
  1023. // in a call to Bucket.Update.
  1024. func (ua *BucketAttrsToUpdate) SetLabel(name, value string) {
  1025. if ua.setLabels == nil {
  1026. ua.setLabels = map[string]string{}
  1027. }
  1028. ua.setLabels[name] = value
  1029. }
  1030. // DeleteLabel causes a label to be deleted when ua is used in a
  1031. // call to Bucket.Update.
  1032. func (ua *BucketAttrsToUpdate) DeleteLabel(name string) {
  1033. if ua.deleteLabels == nil {
  1034. ua.deleteLabels = map[string]bool{}
  1035. }
  1036. ua.deleteLabels[name] = true
  1037. }
  1038. func (ua *BucketAttrsToUpdate) toRawBucket() *raw.Bucket {
  1039. rb := &raw.Bucket{}
  1040. if ua.CORS != nil {
  1041. rb.Cors = toRawCORS(ua.CORS)
  1042. rb.ForceSendFields = append(rb.ForceSendFields, "Cors")
  1043. }
  1044. if ua.DefaultEventBasedHold != nil {
  1045. rb.DefaultEventBasedHold = optional.ToBool(ua.DefaultEventBasedHold)
  1046. rb.ForceSendFields = append(rb.ForceSendFields, "DefaultEventBasedHold")
  1047. }
  1048. if ua.RetentionPolicy != nil {
  1049. if ua.RetentionPolicy.RetentionPeriod == 0 {
  1050. rb.NullFields = append(rb.NullFields, "RetentionPolicy")
  1051. rb.RetentionPolicy = nil
  1052. } else {
  1053. rb.RetentionPolicy = ua.RetentionPolicy.toRawRetentionPolicy()
  1054. }
  1055. }
  1056. if ua.VersioningEnabled != nil {
  1057. rb.Versioning = &raw.BucketVersioning{
  1058. Enabled: optional.ToBool(ua.VersioningEnabled),
  1059. ForceSendFields: []string{"Enabled"},
  1060. }
  1061. }
  1062. if ua.RequesterPays != nil {
  1063. rb.Billing = &raw.BucketBilling{
  1064. RequesterPays: optional.ToBool(ua.RequesterPays),
  1065. ForceSendFields: []string{"RequesterPays"},
  1066. }
  1067. }
  1068. if ua.BucketPolicyOnly != nil {
  1069. rb.IamConfiguration = &raw.BucketIamConfiguration{
  1070. UniformBucketLevelAccess: &raw.BucketIamConfigurationUniformBucketLevelAccess{
  1071. Enabled: ua.BucketPolicyOnly.Enabled,
  1072. ForceSendFields: []string{"Enabled"},
  1073. },
  1074. }
  1075. }
  1076. if ua.UniformBucketLevelAccess != nil {
  1077. rb.IamConfiguration = &raw.BucketIamConfiguration{
  1078. UniformBucketLevelAccess: &raw.BucketIamConfigurationUniformBucketLevelAccess{
  1079. Enabled: ua.UniformBucketLevelAccess.Enabled,
  1080. ForceSendFields: []string{"Enabled"},
  1081. },
  1082. }
  1083. }
  1084. if ua.PublicAccessPrevention != PublicAccessPreventionUnknown {
  1085. if rb.IamConfiguration == nil {
  1086. rb.IamConfiguration = &raw.BucketIamConfiguration{}
  1087. }
  1088. rb.IamConfiguration.PublicAccessPrevention = ua.PublicAccessPrevention.String()
  1089. }
  1090. if ua.Encryption != nil {
  1091. if ua.Encryption.DefaultKMSKeyName == "" {
  1092. rb.NullFields = append(rb.NullFields, "Encryption")
  1093. rb.Encryption = nil
  1094. } else {
  1095. rb.Encryption = ua.Encryption.toRawBucketEncryption()
  1096. }
  1097. }
  1098. if ua.Lifecycle != nil {
  1099. rb.Lifecycle = toRawLifecycle(*ua.Lifecycle)
  1100. rb.ForceSendFields = append(rb.ForceSendFields, "Lifecycle")
  1101. }
  1102. if ua.Logging != nil {
  1103. if *ua.Logging == (BucketLogging{}) {
  1104. rb.NullFields = append(rb.NullFields, "Logging")
  1105. rb.Logging = nil
  1106. } else {
  1107. rb.Logging = ua.Logging.toRawBucketLogging()
  1108. }
  1109. }
  1110. if ua.Website != nil {
  1111. if *ua.Website == (BucketWebsite{}) {
  1112. rb.NullFields = append(rb.NullFields, "Website")
  1113. rb.Website = nil
  1114. } else {
  1115. rb.Website = ua.Website.toRawBucketWebsite()
  1116. }
  1117. }
  1118. if ua.Autoclass != nil {
  1119. rb.Autoclass = &raw.BucketAutoclass{
  1120. Enabled: ua.Autoclass.Enabled,
  1121. TerminalStorageClass: ua.Autoclass.TerminalStorageClass,
  1122. ForceSendFields: []string{"Enabled"},
  1123. }
  1124. rb.ForceSendFields = append(rb.ForceSendFields, "Autoclass")
  1125. }
  1126. if ua.PredefinedACL != "" {
  1127. // Clear ACL or the call will fail.
  1128. rb.Acl = nil
  1129. rb.ForceSendFields = append(rb.ForceSendFields, "Acl")
  1130. }
  1131. if ua.PredefinedDefaultObjectACL != "" {
  1132. // Clear ACLs or the call will fail.
  1133. rb.DefaultObjectAcl = nil
  1134. rb.ForceSendFields = append(rb.ForceSendFields, "DefaultObjectAcl")
  1135. }
  1136. rb.StorageClass = ua.StorageClass
  1137. rb.Rpo = ua.RPO.String()
  1138. if ua.setLabels != nil || ua.deleteLabels != nil {
  1139. rb.Labels = map[string]string{}
  1140. for k, v := range ua.setLabels {
  1141. rb.Labels[k] = v
  1142. }
  1143. if len(rb.Labels) == 0 && len(ua.deleteLabels) > 0 {
  1144. rb.ForceSendFields = append(rb.ForceSendFields, "Labels")
  1145. }
  1146. for l := range ua.deleteLabels {
  1147. rb.NullFields = append(rb.NullFields, "Labels."+l)
  1148. }
  1149. }
  1150. return rb
  1151. }
  1152. // If returns a new BucketHandle that applies a set of preconditions.
  1153. // Preconditions already set on the BucketHandle are ignored. The supplied
  1154. // BucketConditions must have exactly one field set to a non-zero value;
  1155. // otherwise an error will be returned from any operation on the BucketHandle.
  1156. // Operations on the new handle will return an error if the preconditions are not
  1157. // satisfied. The only valid preconditions for buckets are MetagenerationMatch
  1158. // and MetagenerationNotMatch.
  1159. func (b *BucketHandle) If(conds BucketConditions) *BucketHandle {
  1160. b2 := *b
  1161. b2.conds = &conds
  1162. return &b2
  1163. }
  1164. // BucketConditions constrain bucket methods to act on specific metagenerations.
  1165. //
  1166. // The zero value is an empty set of constraints.
  1167. type BucketConditions struct {
  1168. // MetagenerationMatch specifies that the bucket must have the given
  1169. // metageneration for the operation to occur.
  1170. // If MetagenerationMatch is zero, it has no effect.
  1171. MetagenerationMatch int64
  1172. // MetagenerationNotMatch specifies that the bucket must not have the given
  1173. // metageneration for the operation to occur.
  1174. // If MetagenerationNotMatch is zero, it has no effect.
  1175. MetagenerationNotMatch int64
  1176. }
  1177. func (c *BucketConditions) validate(method string) error {
  1178. if *c == (BucketConditions{}) {
  1179. return fmt.Errorf("storage: %s: empty conditions", method)
  1180. }
  1181. if c.MetagenerationMatch != 0 && c.MetagenerationNotMatch != 0 {
  1182. return fmt.Errorf("storage: %s: multiple conditions specified for metageneration", method)
  1183. }
  1184. return nil
  1185. }
  1186. // UserProject returns a new BucketHandle that passes the project ID as the user
  1187. // project for all subsequent calls. Calls with a user project will be billed to that
  1188. // project rather than to the bucket's owning project.
  1189. //
  1190. // A user project is required for all operations on Requester Pays buckets.
  1191. func (b *BucketHandle) UserProject(projectID string) *BucketHandle {
  1192. b2 := *b
  1193. b2.userProject = projectID
  1194. b2.acl.userProject = projectID
  1195. b2.defaultObjectACL.userProject = projectID
  1196. return &b2
  1197. }
  1198. // LockRetentionPolicy locks a bucket's retention policy until a previously-configured
  1199. // RetentionPeriod past the EffectiveTime. Note that if RetentionPeriod is set to less
  1200. // than a day, the retention policy is treated as a development configuration and locking
  1201. // will have no effect. The BucketHandle must have a metageneration condition that
  1202. // matches the bucket's metageneration. See BucketHandle.If.
  1203. //
  1204. // This feature is in private alpha release. It is not currently available to
  1205. // most customers. It might be changed in backwards-incompatible ways and is not
  1206. // subject to any SLA or deprecation policy.
  1207. func (b *BucketHandle) LockRetentionPolicy(ctx context.Context) error {
  1208. o := makeStorageOpts(true, b.retry, b.userProject)
  1209. return b.c.tc.LockBucketRetentionPolicy(ctx, b.name, b.conds, o...)
  1210. }
  1211. // SetObjectRetention returns a new BucketHandle that will enable object retention
  1212. // on bucket creation. To enable object retention, you must use the returned
  1213. // handle to create the bucket. This has no effect on an already existing bucket.
  1214. // ObjectRetention is not enabled by default.
  1215. // ObjectRetention cannot be configured through the gRPC API.
  1216. func (b *BucketHandle) SetObjectRetention(enable bool) *BucketHandle {
  1217. b2 := *b
  1218. b2.enableObjectRetention = &enable
  1219. return &b2
  1220. }
  1221. // applyBucketConds modifies the provided call using the conditions in conds.
  1222. // call is something that quacks like a *raw.WhateverCall.
  1223. func applyBucketConds(method string, conds *BucketConditions, call interface{}) error {
  1224. if conds == nil {
  1225. return nil
  1226. }
  1227. if err := conds.validate(method); err != nil {
  1228. return err
  1229. }
  1230. cval := reflect.ValueOf(call)
  1231. switch {
  1232. case conds.MetagenerationMatch != 0:
  1233. if !setIfMetagenerationMatch(cval, conds.MetagenerationMatch) {
  1234. return fmt.Errorf("storage: %s: ifMetagenerationMatch not supported", method)
  1235. }
  1236. case conds.MetagenerationNotMatch != 0:
  1237. if !setIfMetagenerationNotMatch(cval, conds.MetagenerationNotMatch) {
  1238. return fmt.Errorf("storage: %s: ifMetagenerationNotMatch not supported", method)
  1239. }
  1240. }
  1241. return nil
  1242. }
  1243. // applyBucketConds modifies the provided request message using the conditions
  1244. // in conds. msg is a protobuf Message that has fields if_metageneration_match
  1245. // and if_metageneration_not_match.
  1246. func applyBucketCondsProto(method string, conds *BucketConditions, msg proto.Message) error {
  1247. rmsg := msg.ProtoReflect()
  1248. if conds == nil {
  1249. return nil
  1250. }
  1251. if err := conds.validate(method); err != nil {
  1252. return err
  1253. }
  1254. switch {
  1255. case conds.MetagenerationMatch != 0:
  1256. if !setConditionProtoField(rmsg, "if_metageneration_match", conds.MetagenerationMatch) {
  1257. return fmt.Errorf("storage: %s: ifMetagenerationMatch not supported", method)
  1258. }
  1259. case conds.MetagenerationNotMatch != 0:
  1260. if !setConditionProtoField(rmsg, "if_metageneration_not_match", conds.MetagenerationNotMatch) {
  1261. return fmt.Errorf("storage: %s: ifMetagenerationNotMatch not supported", method)
  1262. }
  1263. }
  1264. return nil
  1265. }
  1266. func (rp *RetentionPolicy) toRawRetentionPolicy() *raw.BucketRetentionPolicy {
  1267. if rp == nil {
  1268. return nil
  1269. }
  1270. return &raw.BucketRetentionPolicy{
  1271. RetentionPeriod: int64(rp.RetentionPeriod / time.Second),
  1272. }
  1273. }
  1274. func (rp *RetentionPolicy) toProtoRetentionPolicy() *storagepb.Bucket_RetentionPolicy {
  1275. if rp == nil {
  1276. return nil
  1277. }
  1278. // RetentionPeriod must be greater than 0, so if it is 0, the user left it
  1279. // unset, and so we should not send it in the request i.e. nil is sent.
  1280. var dur *durationpb.Duration
  1281. if rp.RetentionPeriod != 0 {
  1282. dur = durationpb.New(rp.RetentionPeriod)
  1283. }
  1284. return &storagepb.Bucket_RetentionPolicy{
  1285. RetentionDuration: dur,
  1286. }
  1287. }
  1288. func toRetentionPolicy(rp *raw.BucketRetentionPolicy) (*RetentionPolicy, error) {
  1289. if rp == nil || rp.EffectiveTime == "" {
  1290. return nil, nil
  1291. }
  1292. t, err := time.Parse(time.RFC3339, rp.EffectiveTime)
  1293. if err != nil {
  1294. return nil, err
  1295. }
  1296. return &RetentionPolicy{
  1297. RetentionPeriod: time.Duration(rp.RetentionPeriod) * time.Second,
  1298. EffectiveTime: t,
  1299. IsLocked: rp.IsLocked,
  1300. }, nil
  1301. }
  1302. func toRetentionPolicyFromProto(rp *storagepb.Bucket_RetentionPolicy) *RetentionPolicy {
  1303. if rp == nil || rp.GetEffectiveTime().AsTime().Unix() == 0 {
  1304. return nil
  1305. }
  1306. return &RetentionPolicy{
  1307. RetentionPeriod: rp.GetRetentionDuration().AsDuration(),
  1308. EffectiveTime: rp.GetEffectiveTime().AsTime(),
  1309. IsLocked: rp.GetIsLocked(),
  1310. }
  1311. }
  1312. func toBucketObjectRetention(or *raw.BucketObjectRetention) string {
  1313. if or == nil {
  1314. return ""
  1315. }
  1316. return or.Mode
  1317. }
  1318. func toRawCORS(c []CORS) []*raw.BucketCors {
  1319. var out []*raw.BucketCors
  1320. for _, v := range c {
  1321. out = append(out, &raw.BucketCors{
  1322. MaxAgeSeconds: int64(v.MaxAge / time.Second),
  1323. Method: v.Methods,
  1324. Origin: v.Origins,
  1325. ResponseHeader: v.ResponseHeaders,
  1326. })
  1327. }
  1328. return out
  1329. }
  1330. func toProtoCORS(c []CORS) []*storagepb.Bucket_Cors {
  1331. var out []*storagepb.Bucket_Cors
  1332. for _, v := range c {
  1333. out = append(out, &storagepb.Bucket_Cors{
  1334. MaxAgeSeconds: int32(v.MaxAge / time.Second),
  1335. Method: v.Methods,
  1336. Origin: v.Origins,
  1337. ResponseHeader: v.ResponseHeaders,
  1338. })
  1339. }
  1340. return out
  1341. }
  1342. func toCORS(rc []*raw.BucketCors) []CORS {
  1343. var out []CORS
  1344. for _, v := range rc {
  1345. out = append(out, CORS{
  1346. MaxAge: time.Duration(v.MaxAgeSeconds) * time.Second,
  1347. Methods: v.Method,
  1348. Origins: v.Origin,
  1349. ResponseHeaders: v.ResponseHeader,
  1350. })
  1351. }
  1352. return out
  1353. }
  1354. func toCORSFromProto(rc []*storagepb.Bucket_Cors) []CORS {
  1355. var out []CORS
  1356. for _, v := range rc {
  1357. out = append(out, CORS{
  1358. MaxAge: time.Duration(v.GetMaxAgeSeconds()) * time.Second,
  1359. Methods: v.GetMethod(),
  1360. Origins: v.GetOrigin(),
  1361. ResponseHeaders: v.GetResponseHeader(),
  1362. })
  1363. }
  1364. return out
  1365. }
  1366. func toRawLifecycle(l Lifecycle) *raw.BucketLifecycle {
  1367. var rl raw.BucketLifecycle
  1368. if len(l.Rules) == 0 {
  1369. rl.ForceSendFields = []string{"Rule"}
  1370. }
  1371. for _, r := range l.Rules {
  1372. rr := &raw.BucketLifecycleRule{
  1373. Action: &raw.BucketLifecycleRuleAction{
  1374. Type: r.Action.Type,
  1375. StorageClass: r.Action.StorageClass,
  1376. },
  1377. Condition: &raw.BucketLifecycleRuleCondition{
  1378. DaysSinceCustomTime: r.Condition.DaysSinceCustomTime,
  1379. DaysSinceNoncurrentTime: r.Condition.DaysSinceNoncurrentTime,
  1380. MatchesPrefix: r.Condition.MatchesPrefix,
  1381. MatchesStorageClass: r.Condition.MatchesStorageClasses,
  1382. MatchesSuffix: r.Condition.MatchesSuffix,
  1383. NumNewerVersions: r.Condition.NumNewerVersions,
  1384. },
  1385. }
  1386. // AllObjects takes precedent when both AllObjects and AgeInDays are set
  1387. // Rationale: If you've opted into using AllObjects, it makes sense that you
  1388. // understand the implications of how this option works with AgeInDays.
  1389. if r.Condition.AllObjects {
  1390. rr.Condition.Age = googleapi.Int64(0)
  1391. rr.Condition.ForceSendFields = []string{"Age"}
  1392. } else if r.Condition.AgeInDays > 0 {
  1393. rr.Condition.Age = googleapi.Int64(r.Condition.AgeInDays)
  1394. }
  1395. switch r.Condition.Liveness {
  1396. case LiveAndArchived:
  1397. rr.Condition.IsLive = nil
  1398. case Live:
  1399. rr.Condition.IsLive = googleapi.Bool(true)
  1400. case Archived:
  1401. rr.Condition.IsLive = googleapi.Bool(false)
  1402. }
  1403. if !r.Condition.CreatedBefore.IsZero() {
  1404. rr.Condition.CreatedBefore = r.Condition.CreatedBefore.Format(rfc3339Date)
  1405. }
  1406. if !r.Condition.CustomTimeBefore.IsZero() {
  1407. rr.Condition.CustomTimeBefore = r.Condition.CustomTimeBefore.Format(rfc3339Date)
  1408. }
  1409. if !r.Condition.NoncurrentTimeBefore.IsZero() {
  1410. rr.Condition.NoncurrentTimeBefore = r.Condition.NoncurrentTimeBefore.Format(rfc3339Date)
  1411. }
  1412. rl.Rule = append(rl.Rule, rr)
  1413. }
  1414. return &rl
  1415. }
  1416. func toProtoLifecycle(l Lifecycle) *storagepb.Bucket_Lifecycle {
  1417. var rl storagepb.Bucket_Lifecycle
  1418. for _, r := range l.Rules {
  1419. rr := &storagepb.Bucket_Lifecycle_Rule{
  1420. Action: &storagepb.Bucket_Lifecycle_Rule_Action{
  1421. Type: r.Action.Type,
  1422. StorageClass: r.Action.StorageClass,
  1423. },
  1424. Condition: &storagepb.Bucket_Lifecycle_Rule_Condition{
  1425. // Note: The Apiary types use int64 (even though the Discovery
  1426. // doc states "format: int32"), so the client types used int64,
  1427. // but the proto uses int32 so we have a potentially lossy
  1428. // conversion.
  1429. DaysSinceCustomTime: proto.Int32(int32(r.Condition.DaysSinceCustomTime)),
  1430. DaysSinceNoncurrentTime: proto.Int32(int32(r.Condition.DaysSinceNoncurrentTime)),
  1431. MatchesPrefix: r.Condition.MatchesPrefix,
  1432. MatchesStorageClass: r.Condition.MatchesStorageClasses,
  1433. MatchesSuffix: r.Condition.MatchesSuffix,
  1434. NumNewerVersions: proto.Int32(int32(r.Condition.NumNewerVersions)),
  1435. },
  1436. }
  1437. // Only set AgeDays in the proto if it is non-zero, or if the user has set
  1438. // Condition.AllObjects.
  1439. if r.Condition.AgeInDays != 0 {
  1440. rr.Condition.AgeDays = proto.Int32(int32(r.Condition.AgeInDays))
  1441. }
  1442. if r.Condition.AllObjects {
  1443. rr.Condition.AgeDays = proto.Int32(0)
  1444. }
  1445. switch r.Condition.Liveness {
  1446. case LiveAndArchived:
  1447. rr.Condition.IsLive = nil
  1448. case Live:
  1449. rr.Condition.IsLive = proto.Bool(true)
  1450. case Archived:
  1451. rr.Condition.IsLive = proto.Bool(false)
  1452. }
  1453. if !r.Condition.CreatedBefore.IsZero() {
  1454. rr.Condition.CreatedBefore = timeToProtoDate(r.Condition.CreatedBefore)
  1455. }
  1456. if !r.Condition.CustomTimeBefore.IsZero() {
  1457. rr.Condition.CustomTimeBefore = timeToProtoDate(r.Condition.CustomTimeBefore)
  1458. }
  1459. if !r.Condition.NoncurrentTimeBefore.IsZero() {
  1460. rr.Condition.NoncurrentTimeBefore = timeToProtoDate(r.Condition.NoncurrentTimeBefore)
  1461. }
  1462. rl.Rule = append(rl.Rule, rr)
  1463. }
  1464. return &rl
  1465. }
  1466. func toLifecycle(rl *raw.BucketLifecycle) Lifecycle {
  1467. var l Lifecycle
  1468. if rl == nil {
  1469. return l
  1470. }
  1471. for _, rr := range rl.Rule {
  1472. r := LifecycleRule{
  1473. Action: LifecycleAction{
  1474. Type: rr.Action.Type,
  1475. StorageClass: rr.Action.StorageClass,
  1476. },
  1477. Condition: LifecycleCondition{
  1478. DaysSinceCustomTime: rr.Condition.DaysSinceCustomTime,
  1479. DaysSinceNoncurrentTime: rr.Condition.DaysSinceNoncurrentTime,
  1480. MatchesPrefix: rr.Condition.MatchesPrefix,
  1481. MatchesStorageClasses: rr.Condition.MatchesStorageClass,
  1482. MatchesSuffix: rr.Condition.MatchesSuffix,
  1483. NumNewerVersions: rr.Condition.NumNewerVersions,
  1484. },
  1485. }
  1486. if rr.Condition.Age != nil {
  1487. r.Condition.AgeInDays = *rr.Condition.Age
  1488. if *rr.Condition.Age == 0 {
  1489. r.Condition.AllObjects = true
  1490. }
  1491. }
  1492. if rr.Condition.IsLive == nil {
  1493. r.Condition.Liveness = LiveAndArchived
  1494. } else if *rr.Condition.IsLive {
  1495. r.Condition.Liveness = Live
  1496. } else {
  1497. r.Condition.Liveness = Archived
  1498. }
  1499. if rr.Condition.CreatedBefore != "" {
  1500. r.Condition.CreatedBefore, _ = time.Parse(rfc3339Date, rr.Condition.CreatedBefore)
  1501. }
  1502. if rr.Condition.CustomTimeBefore != "" {
  1503. r.Condition.CustomTimeBefore, _ = time.Parse(rfc3339Date, rr.Condition.CustomTimeBefore)
  1504. }
  1505. if rr.Condition.NoncurrentTimeBefore != "" {
  1506. r.Condition.NoncurrentTimeBefore, _ = time.Parse(rfc3339Date, rr.Condition.NoncurrentTimeBefore)
  1507. }
  1508. l.Rules = append(l.Rules, r)
  1509. }
  1510. return l
  1511. }
  1512. func toLifecycleFromProto(rl *storagepb.Bucket_Lifecycle) Lifecycle {
  1513. var l Lifecycle
  1514. if rl == nil {
  1515. return l
  1516. }
  1517. for _, rr := range rl.GetRule() {
  1518. r := LifecycleRule{
  1519. Action: LifecycleAction{
  1520. Type: rr.GetAction().GetType(),
  1521. StorageClass: rr.GetAction().GetStorageClass(),
  1522. },
  1523. Condition: LifecycleCondition{
  1524. AgeInDays: int64(rr.GetCondition().GetAgeDays()),
  1525. DaysSinceCustomTime: int64(rr.GetCondition().GetDaysSinceCustomTime()),
  1526. DaysSinceNoncurrentTime: int64(rr.GetCondition().GetDaysSinceNoncurrentTime()),
  1527. MatchesPrefix: rr.GetCondition().GetMatchesPrefix(),
  1528. MatchesStorageClasses: rr.GetCondition().GetMatchesStorageClass(),
  1529. MatchesSuffix: rr.GetCondition().GetMatchesSuffix(),
  1530. NumNewerVersions: int64(rr.GetCondition().GetNumNewerVersions()),
  1531. },
  1532. }
  1533. // Only set Condition.AllObjects if AgeDays is zero, not if it is nil.
  1534. if rr.GetCondition().AgeDays != nil && rr.GetCondition().GetAgeDays() == 0 {
  1535. r.Condition.AllObjects = true
  1536. }
  1537. if rr.GetCondition().IsLive == nil {
  1538. r.Condition.Liveness = LiveAndArchived
  1539. } else if rr.GetCondition().GetIsLive() {
  1540. r.Condition.Liveness = Live
  1541. } else {
  1542. r.Condition.Liveness = Archived
  1543. }
  1544. if rr.GetCondition().GetCreatedBefore() != nil {
  1545. r.Condition.CreatedBefore = protoDateToUTCTime(rr.GetCondition().GetCreatedBefore())
  1546. }
  1547. if rr.GetCondition().GetCustomTimeBefore() != nil {
  1548. r.Condition.CustomTimeBefore = protoDateToUTCTime(rr.GetCondition().GetCustomTimeBefore())
  1549. }
  1550. if rr.GetCondition().GetNoncurrentTimeBefore() != nil {
  1551. r.Condition.NoncurrentTimeBefore = protoDateToUTCTime(rr.GetCondition().GetNoncurrentTimeBefore())
  1552. }
  1553. l.Rules = append(l.Rules, r)
  1554. }
  1555. return l
  1556. }
  1557. func (e *BucketEncryption) toRawBucketEncryption() *raw.BucketEncryption {
  1558. if e == nil {
  1559. return nil
  1560. }
  1561. return &raw.BucketEncryption{
  1562. DefaultKmsKeyName: e.DefaultKMSKeyName,
  1563. }
  1564. }
  1565. func (e *BucketEncryption) toProtoBucketEncryption() *storagepb.Bucket_Encryption {
  1566. if e == nil {
  1567. return nil
  1568. }
  1569. return &storagepb.Bucket_Encryption{
  1570. DefaultKmsKey: e.DefaultKMSKeyName,
  1571. }
  1572. }
  1573. func toBucketEncryption(e *raw.BucketEncryption) *BucketEncryption {
  1574. if e == nil {
  1575. return nil
  1576. }
  1577. return &BucketEncryption{DefaultKMSKeyName: e.DefaultKmsKeyName}
  1578. }
  1579. func toBucketEncryptionFromProto(e *storagepb.Bucket_Encryption) *BucketEncryption {
  1580. if e == nil {
  1581. return nil
  1582. }
  1583. return &BucketEncryption{DefaultKMSKeyName: e.GetDefaultKmsKey()}
  1584. }
  1585. func (b *BucketLogging) toRawBucketLogging() *raw.BucketLogging {
  1586. if b == nil {
  1587. return nil
  1588. }
  1589. return &raw.BucketLogging{
  1590. LogBucket: b.LogBucket,
  1591. LogObjectPrefix: b.LogObjectPrefix,
  1592. }
  1593. }
  1594. func (b *BucketLogging) toProtoBucketLogging() *storagepb.Bucket_Logging {
  1595. if b == nil {
  1596. return nil
  1597. }
  1598. return &storagepb.Bucket_Logging{
  1599. LogBucket: bucketResourceName(globalProjectAlias, b.LogBucket),
  1600. LogObjectPrefix: b.LogObjectPrefix,
  1601. }
  1602. }
  1603. func toBucketLogging(b *raw.BucketLogging) *BucketLogging {
  1604. if b == nil {
  1605. return nil
  1606. }
  1607. return &BucketLogging{
  1608. LogBucket: b.LogBucket,
  1609. LogObjectPrefix: b.LogObjectPrefix,
  1610. }
  1611. }
  1612. func toBucketLoggingFromProto(b *storagepb.Bucket_Logging) *BucketLogging {
  1613. if b == nil {
  1614. return nil
  1615. }
  1616. lb := parseBucketName(b.GetLogBucket())
  1617. return &BucketLogging{
  1618. LogBucket: lb,
  1619. LogObjectPrefix: b.GetLogObjectPrefix(),
  1620. }
  1621. }
  1622. func (w *BucketWebsite) toRawBucketWebsite() *raw.BucketWebsite {
  1623. if w == nil {
  1624. return nil
  1625. }
  1626. return &raw.BucketWebsite{
  1627. MainPageSuffix: w.MainPageSuffix,
  1628. NotFoundPage: w.NotFoundPage,
  1629. }
  1630. }
  1631. func (w *BucketWebsite) toProtoBucketWebsite() *storagepb.Bucket_Website {
  1632. if w == nil {
  1633. return nil
  1634. }
  1635. return &storagepb.Bucket_Website{
  1636. MainPageSuffix: w.MainPageSuffix,
  1637. NotFoundPage: w.NotFoundPage,
  1638. }
  1639. }
  1640. func toBucketWebsite(w *raw.BucketWebsite) *BucketWebsite {
  1641. if w == nil {
  1642. return nil
  1643. }
  1644. return &BucketWebsite{
  1645. MainPageSuffix: w.MainPageSuffix,
  1646. NotFoundPage: w.NotFoundPage,
  1647. }
  1648. }
  1649. func toBucketWebsiteFromProto(w *storagepb.Bucket_Website) *BucketWebsite {
  1650. if w == nil {
  1651. return nil
  1652. }
  1653. return &BucketWebsite{
  1654. MainPageSuffix: w.GetMainPageSuffix(),
  1655. NotFoundPage: w.GetNotFoundPage(),
  1656. }
  1657. }
  1658. func toBucketPolicyOnly(b *raw.BucketIamConfiguration) BucketPolicyOnly {
  1659. if b == nil || b.BucketPolicyOnly == nil || !b.BucketPolicyOnly.Enabled {
  1660. return BucketPolicyOnly{}
  1661. }
  1662. lt, err := time.Parse(time.RFC3339, b.BucketPolicyOnly.LockedTime)
  1663. if err != nil {
  1664. return BucketPolicyOnly{
  1665. Enabled: true,
  1666. }
  1667. }
  1668. return BucketPolicyOnly{
  1669. Enabled: true,
  1670. LockedTime: lt,
  1671. }
  1672. }
  1673. func toBucketPolicyOnlyFromProto(b *storagepb.Bucket_IamConfig) BucketPolicyOnly {
  1674. if b == nil || !b.GetUniformBucketLevelAccess().GetEnabled() {
  1675. return BucketPolicyOnly{}
  1676. }
  1677. return BucketPolicyOnly{
  1678. Enabled: true,
  1679. LockedTime: b.GetUniformBucketLevelAccess().GetLockTime().AsTime(),
  1680. }
  1681. }
  1682. func toUniformBucketLevelAccess(b *raw.BucketIamConfiguration) UniformBucketLevelAccess {
  1683. if b == nil || b.UniformBucketLevelAccess == nil || !b.UniformBucketLevelAccess.Enabled {
  1684. return UniformBucketLevelAccess{}
  1685. }
  1686. lt, err := time.Parse(time.RFC3339, b.UniformBucketLevelAccess.LockedTime)
  1687. if err != nil {
  1688. return UniformBucketLevelAccess{
  1689. Enabled: true,
  1690. }
  1691. }
  1692. return UniformBucketLevelAccess{
  1693. Enabled: true,
  1694. LockedTime: lt,
  1695. }
  1696. }
  1697. func toUniformBucketLevelAccessFromProto(b *storagepb.Bucket_IamConfig) UniformBucketLevelAccess {
  1698. if b == nil || !b.GetUniformBucketLevelAccess().GetEnabled() {
  1699. return UniformBucketLevelAccess{}
  1700. }
  1701. return UniformBucketLevelAccess{
  1702. Enabled: true,
  1703. LockedTime: b.GetUniformBucketLevelAccess().GetLockTime().AsTime(),
  1704. }
  1705. }
  1706. func toPublicAccessPrevention(b *raw.BucketIamConfiguration) PublicAccessPrevention {
  1707. if b == nil {
  1708. return PublicAccessPreventionUnknown
  1709. }
  1710. switch b.PublicAccessPrevention {
  1711. case publicAccessPreventionInherited, publicAccessPreventionUnspecified:
  1712. return PublicAccessPreventionInherited
  1713. case publicAccessPreventionEnforced:
  1714. return PublicAccessPreventionEnforced
  1715. default:
  1716. return PublicAccessPreventionUnknown
  1717. }
  1718. }
  1719. func toPublicAccessPreventionFromProto(b *storagepb.Bucket_IamConfig) PublicAccessPrevention {
  1720. if b == nil {
  1721. return PublicAccessPreventionUnknown
  1722. }
  1723. switch b.GetPublicAccessPrevention() {
  1724. case publicAccessPreventionInherited, publicAccessPreventionUnspecified:
  1725. return PublicAccessPreventionInherited
  1726. case publicAccessPreventionEnforced:
  1727. return PublicAccessPreventionEnforced
  1728. default:
  1729. return PublicAccessPreventionUnknown
  1730. }
  1731. }
  1732. func toRPO(b *raw.Bucket) RPO {
  1733. if b == nil {
  1734. return RPOUnknown
  1735. }
  1736. switch b.Rpo {
  1737. case rpoDefault:
  1738. return RPODefault
  1739. case rpoAsyncTurbo:
  1740. return RPOAsyncTurbo
  1741. default:
  1742. return RPOUnknown
  1743. }
  1744. }
  1745. func toRPOFromProto(b *storagepb.Bucket) RPO {
  1746. if b == nil {
  1747. return RPOUnknown
  1748. }
  1749. switch b.GetRpo() {
  1750. case rpoDefault:
  1751. return RPODefault
  1752. case rpoAsyncTurbo:
  1753. return RPOAsyncTurbo
  1754. default:
  1755. return RPOUnknown
  1756. }
  1757. }
  1758. func customPlacementFromRaw(c *raw.BucketCustomPlacementConfig) *CustomPlacementConfig {
  1759. if c == nil {
  1760. return nil
  1761. }
  1762. return &CustomPlacementConfig{DataLocations: c.DataLocations}
  1763. }
  1764. func (c *CustomPlacementConfig) toRawCustomPlacement() *raw.BucketCustomPlacementConfig {
  1765. if c == nil {
  1766. return nil
  1767. }
  1768. return &raw.BucketCustomPlacementConfig{
  1769. DataLocations: c.DataLocations,
  1770. }
  1771. }
  1772. func (c *CustomPlacementConfig) toProtoCustomPlacement() *storagepb.Bucket_CustomPlacementConfig {
  1773. if c == nil {
  1774. return nil
  1775. }
  1776. return &storagepb.Bucket_CustomPlacementConfig{
  1777. DataLocations: c.DataLocations,
  1778. }
  1779. }
  1780. func customPlacementFromProto(c *storagepb.Bucket_CustomPlacementConfig) *CustomPlacementConfig {
  1781. if c == nil {
  1782. return nil
  1783. }
  1784. return &CustomPlacementConfig{DataLocations: c.GetDataLocations()}
  1785. }
  1786. func (a *Autoclass) toRawAutoclass() *raw.BucketAutoclass {
  1787. if a == nil {
  1788. return nil
  1789. }
  1790. // Excluding read only fields ToggleTime and TerminalStorageClassUpdateTime.
  1791. return &raw.BucketAutoclass{
  1792. Enabled: a.Enabled,
  1793. TerminalStorageClass: a.TerminalStorageClass,
  1794. }
  1795. }
  1796. func (a *Autoclass) toProtoAutoclass() *storagepb.Bucket_Autoclass {
  1797. if a == nil {
  1798. return nil
  1799. }
  1800. // Excluding read only fields ToggleTime and TerminalStorageClassUpdateTime.
  1801. ba := &storagepb.Bucket_Autoclass{
  1802. Enabled: a.Enabled,
  1803. }
  1804. if a.TerminalStorageClass != "" {
  1805. ba.TerminalStorageClass = &a.TerminalStorageClass
  1806. }
  1807. return ba
  1808. }
  1809. func toAutoclassFromRaw(a *raw.BucketAutoclass) *Autoclass {
  1810. if a == nil || a.ToggleTime == "" {
  1811. return nil
  1812. }
  1813. ac := &Autoclass{
  1814. Enabled: a.Enabled,
  1815. TerminalStorageClass: a.TerminalStorageClass,
  1816. }
  1817. // Return ToggleTime and TSCUpdateTime only if parsed with valid values.
  1818. t, err := time.Parse(time.RFC3339, a.ToggleTime)
  1819. if err == nil {
  1820. ac.ToggleTime = t
  1821. }
  1822. ut, err := time.Parse(time.RFC3339, a.TerminalStorageClassUpdateTime)
  1823. if err == nil {
  1824. ac.TerminalStorageClassUpdateTime = ut
  1825. }
  1826. return ac
  1827. }
  1828. func toAutoclassFromProto(a *storagepb.Bucket_Autoclass) *Autoclass {
  1829. if a == nil || a.GetToggleTime().AsTime().Unix() == 0 {
  1830. return nil
  1831. }
  1832. return &Autoclass{
  1833. Enabled: a.GetEnabled(),
  1834. ToggleTime: a.GetToggleTime().AsTime(),
  1835. TerminalStorageClass: a.GetTerminalStorageClass(),
  1836. TerminalStorageClassUpdateTime: a.GetTerminalStorageClassUpdateTime().AsTime(),
  1837. }
  1838. }
  1839. // Objects returns an iterator over the objects in the bucket that match the
  1840. // Query q. If q is nil, no filtering is done. Objects will be iterated over
  1841. // lexicographically by name.
  1842. //
  1843. // Note: The returned iterator is not safe for concurrent operations without explicit synchronization.
  1844. func (b *BucketHandle) Objects(ctx context.Context, q *Query) *ObjectIterator {
  1845. o := makeStorageOpts(true, b.retry, b.userProject)
  1846. return b.c.tc.ListObjects(ctx, b.name, q, o...)
  1847. }
  1848. // Retryer returns a bucket handle that is configured with custom retry
  1849. // behavior as specified by the options that are passed to it. All operations
  1850. // on the new handle will use the customized retry configuration.
  1851. // Retry options set on a object handle will take precedence over options set on
  1852. // the bucket handle.
  1853. // These retry options will merge with the client's retry configuration (if set)
  1854. // for the returned handle. Options passed into this method will take precedence
  1855. // over retry options on the client. Note that you must explicitly pass in each
  1856. // option you want to override.
  1857. func (b *BucketHandle) Retryer(opts ...RetryOption) *BucketHandle {
  1858. b2 := *b
  1859. var retry *retryConfig
  1860. if b.retry != nil {
  1861. // merge the options with the existing retry
  1862. retry = b.retry
  1863. } else {
  1864. retry = &retryConfig{}
  1865. }
  1866. for _, opt := range opts {
  1867. opt.apply(retry)
  1868. }
  1869. b2.retry = retry
  1870. b2.acl.retry = retry
  1871. b2.defaultObjectACL.retry = retry
  1872. return &b2
  1873. }
  1874. // An ObjectIterator is an iterator over ObjectAttrs.
  1875. //
  1876. // Note: This iterator is not safe for concurrent operations without explicit synchronization.
  1877. type ObjectIterator struct {
  1878. ctx context.Context
  1879. query Query
  1880. pageInfo *iterator.PageInfo
  1881. nextFunc func() error
  1882. items []*ObjectAttrs
  1883. }
  1884. // PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
  1885. //
  1886. // Note: This method is not safe for concurrent operations without explicit synchronization.
  1887. func (it *ObjectIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }
  1888. // Next returns the next result. Its second return value is iterator.Done if
  1889. // there are no more results. Once Next returns iterator.Done, all subsequent
  1890. // calls will return iterator.Done.
  1891. //
  1892. // In addition, if Next returns an error other than iterator.Done, all
  1893. // subsequent calls will return the same error. To continue iteration, a new
  1894. // `ObjectIterator` must be created. Since objects are ordered lexicographically
  1895. // by name, `Query.StartOffset` can be used to create a new iterator which will
  1896. // start at the desired place. See
  1897. // https://pkg.go.dev/cloud.google.com/go/storage?tab=doc#hdr-Listing_objects.
  1898. //
  1899. // If Query.Delimiter is non-empty, some of the ObjectAttrs returned by Next will
  1900. // have a non-empty Prefix field, and a zero value for all other fields. These
  1901. // represent prefixes.
  1902. //
  1903. // Note: This method is not safe for concurrent operations without explicit synchronization.
  1904. func (it *ObjectIterator) Next() (*ObjectAttrs, error) {
  1905. if err := it.nextFunc(); err != nil {
  1906. return nil, err
  1907. }
  1908. item := it.items[0]
  1909. it.items = it.items[1:]
  1910. return item, nil
  1911. }
  1912. // Buckets returns an iterator over the buckets in the project. You may
  1913. // optionally set the iterator's Prefix field to restrict the list to buckets
  1914. // whose names begin with the prefix. By default, all buckets in the project
  1915. // are returned.
  1916. //
  1917. // Note: The returned iterator is not safe for concurrent operations without explicit synchronization.
  1918. func (c *Client) Buckets(ctx context.Context, projectID string) *BucketIterator {
  1919. o := makeStorageOpts(true, c.retry, "")
  1920. return c.tc.ListBuckets(ctx, projectID, o...)
  1921. }
  1922. // A BucketIterator is an iterator over BucketAttrs.
  1923. //
  1924. // Note: This iterator is not safe for concurrent operations without explicit synchronization.
  1925. type BucketIterator struct {
  1926. // Prefix restricts the iterator to buckets whose names begin with it.
  1927. Prefix string
  1928. ctx context.Context
  1929. projectID string
  1930. buckets []*BucketAttrs
  1931. pageInfo *iterator.PageInfo
  1932. nextFunc func() error
  1933. }
  1934. // Next returns the next result. Its second return value is iterator.Done if
  1935. // there are no more results. Once Next returns iterator.Done, all subsequent
  1936. // calls will return iterator.Done.
  1937. //
  1938. // Note: This method is not safe for concurrent operations without explicit synchronization.
  1939. func (it *BucketIterator) Next() (*BucketAttrs, error) {
  1940. if err := it.nextFunc(); err != nil {
  1941. return nil, err
  1942. }
  1943. b := it.buckets[0]
  1944. it.buckets = it.buckets[1:]
  1945. return b, nil
  1946. }
  1947. // PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
  1948. //
  1949. // Note: This method is not safe for concurrent operations without explicit synchronization.
  1950. func (it *BucketIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }
  1951. // RPO (Recovery Point Objective) configures the turbo replication feature. See
  1952. // https://cloud.google.com/storage/docs/managing-turbo-replication for more information.
  1953. type RPO int
  1954. const (
  1955. // RPOUnknown is a zero value. It may be returned from bucket.Attrs() if RPO
  1956. // is not present in the bucket metadata, that is, the bucket is not dual-region.
  1957. // This value is also used if the RPO field is not set in a call to GCS.
  1958. RPOUnknown RPO = iota
  1959. // RPODefault represents default replication. It is used to reset RPO on an
  1960. // existing bucket that has this field set to RPOAsyncTurbo. Otherwise it
  1961. // is equivalent to RPOUnknown, and is always ignored. This value is valid
  1962. // for dual- or multi-region buckets.
  1963. RPODefault
  1964. // RPOAsyncTurbo represents turbo replication and is used to enable Turbo
  1965. // Replication on a bucket. This value is only valid for dual-region buckets.
  1966. RPOAsyncTurbo
  1967. rpoUnknown string = ""
  1968. rpoDefault = "DEFAULT"
  1969. rpoAsyncTurbo = "ASYNC_TURBO"
  1970. )
  1971. func (rpo RPO) String() string {
  1972. switch rpo {
  1973. case RPODefault:
  1974. return rpoDefault
  1975. case RPOAsyncTurbo:
  1976. return rpoAsyncTurbo
  1977. default:
  1978. return rpoUnknown
  1979. }
  1980. }
  1981. // protoDateToUTCTime returns a new Time based on the google.type.Date, in UTC.
  1982. //
  1983. // Hours, minutes, seconds, and nanoseconds are set to 0.
  1984. func protoDateToUTCTime(d *dpb.Date) time.Time {
  1985. return protoDateToTime(d, time.UTC)
  1986. }
  1987. // protoDateToTime returns a new Time based on the google.type.Date and provided
  1988. // *time.Location.
  1989. //
  1990. // Hours, minutes, seconds, and nanoseconds are set to 0.
  1991. func protoDateToTime(d *dpb.Date, l *time.Location) time.Time {
  1992. return time.Date(int(d.GetYear()), time.Month(d.GetMonth()), int(d.GetDay()), 0, 0, 0, 0, l)
  1993. }
  1994. // timeToProtoDate returns a new google.type.Date based on the provided time.Time.
  1995. // The location is ignored, as is anything more precise than the day.
  1996. func timeToProtoDate(t time.Time) *dpb.Date {
  1997. return &dpb.Date{
  1998. Year: int32(t.Year()),
  1999. Month: int32(t.Month()),
  2000. Day: int32(t.Day()),
  2001. }
  2002. }