notifications.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. // Copyright 2017 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. "errors"
  18. "fmt"
  19. "regexp"
  20. "cloud.google.com/go/internal/trace"
  21. "cloud.google.com/go/storage/internal/apiv2/storagepb"
  22. raw "google.golang.org/api/storage/v1"
  23. )
  24. // A Notification describes how to send Cloud PubSub messages when certain
  25. // events occur in a bucket.
  26. type Notification struct {
  27. //The ID of the notification.
  28. ID string
  29. // The ID of the topic to which this subscription publishes.
  30. TopicID string
  31. // The ID of the project to which the topic belongs.
  32. TopicProjectID string
  33. // Only send notifications about listed event types. If empty, send notifications
  34. // for all event types.
  35. // See https://cloud.google.com/storage/docs/pubsub-notifications#events.
  36. EventTypes []string
  37. // If present, only apply this notification configuration to object names that
  38. // begin with this prefix.
  39. ObjectNamePrefix string
  40. // An optional list of additional attributes to attach to each Cloud PubSub
  41. // message published for this notification subscription.
  42. CustomAttributes map[string]string
  43. // The contents of the message payload.
  44. // See https://cloud.google.com/storage/docs/pubsub-notifications#payload.
  45. PayloadFormat string
  46. }
  47. // Values for Notification.PayloadFormat.
  48. const (
  49. // Send no payload with notification messages.
  50. NoPayload = "NONE"
  51. // Send object metadata as JSON with notification messages.
  52. JSONPayload = "JSON_API_V1"
  53. )
  54. // Values for Notification.EventTypes.
  55. const (
  56. // Event that occurs when an object is successfully created.
  57. ObjectFinalizeEvent = "OBJECT_FINALIZE"
  58. // Event that occurs when the metadata of an existing object changes.
  59. ObjectMetadataUpdateEvent = "OBJECT_METADATA_UPDATE"
  60. // Event that occurs when an object is permanently deleted.
  61. ObjectDeleteEvent = "OBJECT_DELETE"
  62. // Event that occurs when the live version of an object becomes an
  63. // archived version.
  64. ObjectArchiveEvent = "OBJECT_ARCHIVE"
  65. )
  66. func toNotification(rn *raw.Notification) *Notification {
  67. n := &Notification{
  68. ID: rn.Id,
  69. EventTypes: rn.EventTypes,
  70. ObjectNamePrefix: rn.ObjectNamePrefix,
  71. CustomAttributes: rn.CustomAttributes,
  72. PayloadFormat: rn.PayloadFormat,
  73. }
  74. n.TopicProjectID, n.TopicID = parseNotificationTopic(rn.Topic)
  75. return n
  76. }
  77. func toNotificationFromProto(pbn *storagepb.NotificationConfig) *Notification {
  78. n := &Notification{
  79. ID: pbn.GetName(),
  80. EventTypes: pbn.GetEventTypes(),
  81. ObjectNamePrefix: pbn.GetObjectNamePrefix(),
  82. CustomAttributes: pbn.GetCustomAttributes(),
  83. PayloadFormat: pbn.GetPayloadFormat(),
  84. }
  85. n.TopicProjectID, n.TopicID = parseNotificationTopic(pbn.Topic)
  86. return n
  87. }
  88. func toProtoNotification(n *Notification) *storagepb.NotificationConfig {
  89. return &storagepb.NotificationConfig{
  90. Name: n.ID,
  91. Topic: fmt.Sprintf("//pubsub.googleapis.com/projects/%s/topics/%s",
  92. n.TopicProjectID, n.TopicID),
  93. EventTypes: n.EventTypes,
  94. ObjectNamePrefix: n.ObjectNamePrefix,
  95. CustomAttributes: n.CustomAttributes,
  96. PayloadFormat: n.PayloadFormat,
  97. }
  98. }
  99. var topicRE = regexp.MustCompile("^//pubsub.googleapis.com/projects/([^/]+)/topics/([^/]+)")
  100. // parseNotificationTopic extracts the project and topic IDs from from the full
  101. // resource name returned by the service. If the name is malformed, it returns
  102. // "?" for both IDs.
  103. func parseNotificationTopic(nt string) (projectID, topicID string) {
  104. matches := topicRE.FindStringSubmatch(nt)
  105. if matches == nil {
  106. return "?", "?"
  107. }
  108. return matches[1], matches[2]
  109. }
  110. func toRawNotification(n *Notification) *raw.Notification {
  111. return &raw.Notification{
  112. Id: n.ID,
  113. Topic: fmt.Sprintf("//pubsub.googleapis.com/projects/%s/topics/%s",
  114. n.TopicProjectID, n.TopicID),
  115. EventTypes: n.EventTypes,
  116. ObjectNamePrefix: n.ObjectNamePrefix,
  117. CustomAttributes: n.CustomAttributes,
  118. PayloadFormat: string(n.PayloadFormat),
  119. }
  120. }
  121. // AddNotification adds a notification to b. You must set n's TopicProjectID, TopicID
  122. // and PayloadFormat, and must not set its ID. The other fields are all optional. The
  123. // returned Notification's ID can be used to refer to it.
  124. func (b *BucketHandle) AddNotification(ctx context.Context, n *Notification) (ret *Notification, err error) {
  125. ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.AddNotification")
  126. defer func() { trace.EndSpan(ctx, err) }()
  127. if n.ID != "" {
  128. return nil, errors.New("storage: AddNotification: ID must not be set")
  129. }
  130. if n.TopicProjectID == "" {
  131. return nil, errors.New("storage: AddNotification: missing TopicProjectID")
  132. }
  133. if n.TopicID == "" {
  134. return nil, errors.New("storage: AddNotification: missing TopicID")
  135. }
  136. opts := makeStorageOpts(false, b.retry, b.userProject)
  137. ret, err = b.c.tc.CreateNotification(ctx, b.name, n, opts...)
  138. return ret, err
  139. }
  140. // Notifications returns all the Notifications configured for this bucket, as a map
  141. // indexed by notification ID.
  142. func (b *BucketHandle) Notifications(ctx context.Context) (n map[string]*Notification, err error) {
  143. ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.Notifications")
  144. defer func() { trace.EndSpan(ctx, err) }()
  145. opts := makeStorageOpts(true, b.retry, b.userProject)
  146. n, err = b.c.tc.ListNotifications(ctx, b.name, opts...)
  147. return n, err
  148. }
  149. func notificationsToMap(rns []*raw.Notification) map[string]*Notification {
  150. m := map[string]*Notification{}
  151. for _, rn := range rns {
  152. m[rn.Id] = toNotification(rn)
  153. }
  154. return m
  155. }
  156. func notificationsToMapFromProto(ns []*storagepb.NotificationConfig) map[string]*Notification {
  157. m := map[string]*Notification{}
  158. for _, n := range ns {
  159. m[n.Name] = toNotificationFromProto(n)
  160. }
  161. return m
  162. }
  163. // DeleteNotification deletes the notification with the given ID.
  164. func (b *BucketHandle) DeleteNotification(ctx context.Context, id string) (err error) {
  165. ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.DeleteNotification")
  166. defer func() { trace.EndSpan(ctx, err) }()
  167. opts := makeStorageOpts(true, b.retry, b.userProject)
  168. return b.c.tc.DeleteNotification(ctx, b.name, id, opts...)
  169. }