diff options
Diffstat (limited to 'vendor/github.com/minio/minio-go/v7/pkg/notification/notification.go')
-rw-r--r-- | vendor/github.com/minio/minio-go/v7/pkg/notification/notification.go | 440 |
1 files changed, 0 insertions, 440 deletions
diff --git a/vendor/github.com/minio/minio-go/v7/pkg/notification/notification.go b/vendor/github.com/minio/minio-go/v7/pkg/notification/notification.go deleted file mode 100644 index a44799d..0000000 --- a/vendor/github.com/minio/minio-go/v7/pkg/notification/notification.go +++ /dev/null | |||
@@ -1,440 +0,0 @@ | |||
1 | /* | ||
2 | * MinIO Go Library for Amazon S3 Compatible Cloud Storage | ||
3 | * Copyright 2020 MinIO, Inc. | ||
4 | * | ||
5 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | * you may not use this file except in compliance with the License. | ||
7 | * You may obtain a copy of the License at | ||
8 | * | ||
9 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | * | ||
11 | * Unless required by applicable law or agreed to in writing, software | ||
12 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | * See the License for the specific language governing permissions and | ||
15 | * limitations under the License. | ||
16 | */ | ||
17 | |||
18 | package notification | ||
19 | |||
20 | import ( | ||
21 | "encoding/xml" | ||
22 | "errors" | ||
23 | "fmt" | ||
24 | "strings" | ||
25 | |||
26 | "github.com/minio/minio-go/v7/pkg/set" | ||
27 | ) | ||
28 | |||
29 | // EventType is a S3 notification event associated to the bucket notification configuration | ||
30 | type EventType string | ||
31 | |||
32 | // The role of all event types are described in : | ||
33 | // | ||
34 | // http://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html#notification-how-to-event-types-and-destinations | ||
35 | const ( | ||
36 | ObjectCreatedAll EventType = "s3:ObjectCreated:*" | ||
37 | ObjectCreatedPut EventType = "s3:ObjectCreated:Put" | ||
38 | ObjectCreatedPost EventType = "s3:ObjectCreated:Post" | ||
39 | ObjectCreatedCopy EventType = "s3:ObjectCreated:Copy" | ||
40 | ObjectCreatedDeleteTagging EventType = "s3:ObjectCreated:DeleteTagging" | ||
41 | ObjectCreatedCompleteMultipartUpload EventType = "s3:ObjectCreated:CompleteMultipartUpload" | ||
42 | ObjectCreatedPutLegalHold EventType = "s3:ObjectCreated:PutLegalHold" | ||
43 | ObjectCreatedPutRetention EventType = "s3:ObjectCreated:PutRetention" | ||
44 | ObjectCreatedPutTagging EventType = "s3:ObjectCreated:PutTagging" | ||
45 | ObjectAccessedGet EventType = "s3:ObjectAccessed:Get" | ||
46 | ObjectAccessedHead EventType = "s3:ObjectAccessed:Head" | ||
47 | ObjectAccessedGetRetention EventType = "s3:ObjectAccessed:GetRetention" | ||
48 | ObjectAccessedGetLegalHold EventType = "s3:ObjectAccessed:GetLegalHold" | ||
49 | ObjectAccessedAll EventType = "s3:ObjectAccessed:*" | ||
50 | ObjectRemovedAll EventType = "s3:ObjectRemoved:*" | ||
51 | ObjectRemovedDelete EventType = "s3:ObjectRemoved:Delete" | ||
52 | ObjectRemovedDeleteMarkerCreated EventType = "s3:ObjectRemoved:DeleteMarkerCreated" | ||
53 | ObjectReducedRedundancyLostObject EventType = "s3:ReducedRedundancyLostObject" | ||
54 | ObjectTransitionAll EventType = "s3:ObjectTransition:*" | ||
55 | ObjectTransitionFailed EventType = "s3:ObjectTransition:Failed" | ||
56 | ObjectTransitionComplete EventType = "s3:ObjectTransition:Complete" | ||
57 | ObjectTransitionPost EventType = "s3:ObjectRestore:Post" | ||
58 | ObjectTransitionCompleted EventType = "s3:ObjectRestore:Completed" | ||
59 | ObjectReplicationAll EventType = "s3:Replication:*" | ||
60 | ObjectReplicationOperationCompletedReplication EventType = "s3:Replication:OperationCompletedReplication" | ||
61 | ObjectReplicationOperationFailedReplication EventType = "s3:Replication:OperationFailedReplication" | ||
62 | ObjectReplicationOperationMissedThreshold EventType = "s3:Replication:OperationMissedThreshold" | ||
63 | ObjectReplicationOperationNotTracked EventType = "s3:Replication:OperationNotTracked" | ||
64 | ObjectReplicationOperationReplicatedAfterThreshold EventType = "s3:Replication:OperationReplicatedAfterThreshold" | ||
65 | ObjectScannerManyVersions EventType = "s3:Scanner:ManyVersions" | ||
66 | ObjectScannerBigPrefix EventType = "s3:Scanner:BigPrefix" | ||
67 | ObjectScannerAll EventType = "s3:Scanner:*" | ||
68 | BucketCreatedAll EventType = "s3:BucketCreated:*" | ||
69 | BucketRemovedAll EventType = "s3:BucketRemoved:*" | ||
70 | ) | ||
71 | |||
72 | // FilterRule - child of S3Key, a tag in the notification xml which | ||
73 | // carries suffix/prefix filters | ||
74 | type FilterRule struct { | ||
75 | Name string `xml:"Name"` | ||
76 | Value string `xml:"Value"` | ||
77 | } | ||
78 | |||
79 | // S3Key - child of Filter, a tag in the notification xml which | ||
80 | // carries suffix/prefix filters | ||
81 | type S3Key struct { | ||
82 | FilterRules []FilterRule `xml:"FilterRule,omitempty"` | ||
83 | } | ||
84 | |||
85 | // Filter - a tag in the notification xml structure which carries | ||
86 | // suffix/prefix filters | ||
87 | type Filter struct { | ||
88 | S3Key S3Key `xml:"S3Key,omitempty"` | ||
89 | } | ||
90 | |||
91 | // Arn - holds ARN information that will be sent to the web service, | ||
92 | // ARN desciption can be found in http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html | ||
93 | type Arn struct { | ||
94 | Partition string | ||
95 | Service string | ||
96 | Region string | ||
97 | AccountID string | ||
98 | Resource string | ||
99 | } | ||
100 | |||
101 | // NewArn creates new ARN based on the given partition, service, region, account id and resource | ||
102 | func NewArn(partition, service, region, accountID, resource string) Arn { | ||
103 | return Arn{ | ||
104 | Partition: partition, | ||
105 | Service: service, | ||
106 | Region: region, | ||
107 | AccountID: accountID, | ||
108 | Resource: resource, | ||
109 | } | ||
110 | } | ||
111 | |||
112 | var ( | ||
113 | // ErrInvalidArnPrefix is returned when ARN string format does not start with 'arn' | ||
114 | ErrInvalidArnPrefix = errors.New("invalid ARN format, must start with 'arn:'") | ||
115 | // ErrInvalidArnFormat is returned when ARN string format is not valid | ||
116 | ErrInvalidArnFormat = errors.New("invalid ARN format, must be 'arn:<partition>:<service>:<region>:<accountID>:<resource>'") | ||
117 | ) | ||
118 | |||
119 | // NewArnFromString parses string representation of ARN into Arn object. | ||
120 | // Returns an error if the string format is incorrect. | ||
121 | func NewArnFromString(arn string) (Arn, error) { | ||
122 | parts := strings.Split(arn, ":") | ||
123 | if len(parts) != 6 { | ||
124 | return Arn{}, ErrInvalidArnFormat | ||
125 | } | ||
126 | if parts[0] != "arn" { | ||
127 | return Arn{}, ErrInvalidArnPrefix | ||
128 | } | ||
129 | |||
130 | return NewArn(parts[1], parts[2], parts[3], parts[4], parts[5]), nil | ||
131 | } | ||
132 | |||
133 | // String returns the string format of the ARN | ||
134 | func (arn Arn) String() string { | ||
135 | return "arn:" + arn.Partition + ":" + arn.Service + ":" + arn.Region + ":" + arn.AccountID + ":" + arn.Resource | ||
136 | } | ||
137 | |||
138 | // Config - represents one single notification configuration | ||
139 | // such as topic, queue or lambda configuration. | ||
140 | type Config struct { | ||
141 | ID string `xml:"Id,omitempty"` | ||
142 | Arn Arn `xml:"-"` | ||
143 | Events []EventType `xml:"Event"` | ||
144 | Filter *Filter `xml:"Filter,omitempty"` | ||
145 | } | ||
146 | |||
147 | // NewConfig creates one notification config and sets the given ARN | ||
148 | func NewConfig(arn Arn) Config { | ||
149 | return Config{Arn: arn, Filter: &Filter{}} | ||
150 | } | ||
151 | |||
152 | // AddEvents adds one event to the current notification config | ||
153 | func (t *Config) AddEvents(events ...EventType) { | ||
154 | t.Events = append(t.Events, events...) | ||
155 | } | ||
156 | |||
157 | // AddFilterSuffix sets the suffix configuration to the current notification config | ||
158 | func (t *Config) AddFilterSuffix(suffix string) { | ||
159 | if t.Filter == nil { | ||
160 | t.Filter = &Filter{} | ||
161 | } | ||
162 | newFilterRule := FilterRule{Name: "suffix", Value: suffix} | ||
163 | // Replace any suffix rule if existing and add to the list otherwise | ||
164 | for index := range t.Filter.S3Key.FilterRules { | ||
165 | if t.Filter.S3Key.FilterRules[index].Name == "suffix" { | ||
166 | t.Filter.S3Key.FilterRules[index] = newFilterRule | ||
167 | return | ||
168 | } | ||
169 | } | ||
170 | t.Filter.S3Key.FilterRules = append(t.Filter.S3Key.FilterRules, newFilterRule) | ||
171 | } | ||
172 | |||
173 | // AddFilterPrefix sets the prefix configuration to the current notification config | ||
174 | func (t *Config) AddFilterPrefix(prefix string) { | ||
175 | if t.Filter == nil { | ||
176 | t.Filter = &Filter{} | ||
177 | } | ||
178 | newFilterRule := FilterRule{Name: "prefix", Value: prefix} | ||
179 | // Replace any prefix rule if existing and add to the list otherwise | ||
180 | for index := range t.Filter.S3Key.FilterRules { | ||
181 | if t.Filter.S3Key.FilterRules[index].Name == "prefix" { | ||
182 | t.Filter.S3Key.FilterRules[index] = newFilterRule | ||
183 | return | ||
184 | } | ||
185 | } | ||
186 | t.Filter.S3Key.FilterRules = append(t.Filter.S3Key.FilterRules, newFilterRule) | ||
187 | } | ||
188 | |||
189 | // EqualEventTypeList tells whether a and b contain the same events | ||
190 | func EqualEventTypeList(a, b []EventType) bool { | ||
191 | if len(a) != len(b) { | ||
192 | return false | ||
193 | } | ||
194 | setA := set.NewStringSet() | ||
195 | for _, i := range a { | ||
196 | setA.Add(string(i)) | ||
197 | } | ||
198 | |||
199 | setB := set.NewStringSet() | ||
200 | for _, i := range b { | ||
201 | setB.Add(string(i)) | ||
202 | } | ||
203 | |||
204 | return setA.Difference(setB).IsEmpty() | ||
205 | } | ||
206 | |||
207 | // EqualFilterRuleList tells whether a and b contain the same filters | ||
208 | func EqualFilterRuleList(a, b []FilterRule) bool { | ||
209 | if len(a) != len(b) { | ||
210 | return false | ||
211 | } | ||
212 | |||
213 | setA := set.NewStringSet() | ||
214 | for _, i := range a { | ||
215 | setA.Add(fmt.Sprintf("%s-%s", i.Name, i.Value)) | ||
216 | } | ||
217 | |||
218 | setB := set.NewStringSet() | ||
219 | for _, i := range b { | ||
220 | setB.Add(fmt.Sprintf("%s-%s", i.Name, i.Value)) | ||
221 | } | ||
222 | |||
223 | return setA.Difference(setB).IsEmpty() | ||
224 | } | ||
225 | |||
226 | // Equal returns whether this `Config` is equal to another defined by the passed parameters | ||
227 | func (t *Config) Equal(events []EventType, prefix, suffix string) bool { | ||
228 | if t == nil { | ||
229 | return false | ||
230 | } | ||
231 | |||
232 | // Compare events | ||
233 | passEvents := EqualEventTypeList(t.Events, events) | ||
234 | |||
235 | // Compare filters | ||
236 | var newFilterRules []FilterRule | ||
237 | if prefix != "" { | ||
238 | newFilterRules = append(newFilterRules, FilterRule{Name: "prefix", Value: prefix}) | ||
239 | } | ||
240 | if suffix != "" { | ||
241 | newFilterRules = append(newFilterRules, FilterRule{Name: "suffix", Value: suffix}) | ||
242 | } | ||
243 | |||
244 | var currentFilterRules []FilterRule | ||
245 | if t.Filter != nil { | ||
246 | currentFilterRules = t.Filter.S3Key.FilterRules | ||
247 | } | ||
248 | |||
249 | passFilters := EqualFilterRuleList(currentFilterRules, newFilterRules) | ||
250 | return passEvents && passFilters | ||
251 | } | ||
252 | |||
253 | // TopicConfig carries one single topic notification configuration | ||
254 | type TopicConfig struct { | ||
255 | Config | ||
256 | Topic string `xml:"Topic"` | ||
257 | } | ||
258 | |||
259 | // QueueConfig carries one single queue notification configuration | ||
260 | type QueueConfig struct { | ||
261 | Config | ||
262 | Queue string `xml:"Queue"` | ||
263 | } | ||
264 | |||
265 | // LambdaConfig carries one single cloudfunction notification configuration | ||
266 | type LambdaConfig struct { | ||
267 | Config | ||
268 | Lambda string `xml:"CloudFunction"` | ||
269 | } | ||
270 | |||
271 | // Configuration - the struct that represents the whole XML to be sent to the web service | ||
272 | type Configuration struct { | ||
273 | XMLName xml.Name `xml:"NotificationConfiguration"` | ||
274 | LambdaConfigs []LambdaConfig `xml:"CloudFunctionConfiguration"` | ||
275 | TopicConfigs []TopicConfig `xml:"TopicConfiguration"` | ||
276 | QueueConfigs []QueueConfig `xml:"QueueConfiguration"` | ||
277 | } | ||
278 | |||
279 | // AddTopic adds a given topic config to the general bucket notification config | ||
280 | func (b *Configuration) AddTopic(topicConfig Config) bool { | ||
281 | newTopicConfig := TopicConfig{Config: topicConfig, Topic: topicConfig.Arn.String()} | ||
282 | for _, n := range b.TopicConfigs { | ||
283 | // If new config matches existing one | ||
284 | if n.Topic == newTopicConfig.Arn.String() && newTopicConfig.Filter == n.Filter { | ||
285 | |||
286 | existingConfig := set.NewStringSet() | ||
287 | for _, v := range n.Events { | ||
288 | existingConfig.Add(string(v)) | ||
289 | } | ||
290 | |||
291 | newConfig := set.NewStringSet() | ||
292 | for _, v := range topicConfig.Events { | ||
293 | newConfig.Add(string(v)) | ||
294 | } | ||
295 | |||
296 | if !newConfig.Intersection(existingConfig).IsEmpty() { | ||
297 | return false | ||
298 | } | ||
299 | } | ||
300 | } | ||
301 | b.TopicConfigs = append(b.TopicConfigs, newTopicConfig) | ||
302 | return true | ||
303 | } | ||
304 | |||
305 | // AddQueue adds a given queue config to the general bucket notification config | ||
306 | func (b *Configuration) AddQueue(queueConfig Config) bool { | ||
307 | newQueueConfig := QueueConfig{Config: queueConfig, Queue: queueConfig.Arn.String()} | ||
308 | for _, n := range b.QueueConfigs { | ||
309 | if n.Queue == newQueueConfig.Arn.String() && newQueueConfig.Filter == n.Filter { | ||
310 | |||
311 | existingConfig := set.NewStringSet() | ||
312 | for _, v := range n.Events { | ||
313 | existingConfig.Add(string(v)) | ||
314 | } | ||
315 | |||
316 | newConfig := set.NewStringSet() | ||
317 | for _, v := range queueConfig.Events { | ||
318 | newConfig.Add(string(v)) | ||
319 | } | ||
320 | |||
321 | if !newConfig.Intersection(existingConfig).IsEmpty() { | ||
322 | return false | ||
323 | } | ||
324 | } | ||
325 | } | ||
326 | b.QueueConfigs = append(b.QueueConfigs, newQueueConfig) | ||
327 | return true | ||
328 | } | ||
329 | |||
330 | // AddLambda adds a given lambda config to the general bucket notification config | ||
331 | func (b *Configuration) AddLambda(lambdaConfig Config) bool { | ||
332 | newLambdaConfig := LambdaConfig{Config: lambdaConfig, Lambda: lambdaConfig.Arn.String()} | ||
333 | for _, n := range b.LambdaConfigs { | ||
334 | if n.Lambda == newLambdaConfig.Arn.String() && newLambdaConfig.Filter == n.Filter { | ||
335 | |||
336 | existingConfig := set.NewStringSet() | ||
337 | for _, v := range n.Events { | ||
338 | existingConfig.Add(string(v)) | ||
339 | } | ||
340 | |||
341 | newConfig := set.NewStringSet() | ||
342 | for _, v := range lambdaConfig.Events { | ||
343 | newConfig.Add(string(v)) | ||
344 | } | ||
345 | |||
346 | if !newConfig.Intersection(existingConfig).IsEmpty() { | ||
347 | return false | ||
348 | } | ||
349 | } | ||
350 | } | ||
351 | b.LambdaConfigs = append(b.LambdaConfigs, newLambdaConfig) | ||
352 | return true | ||
353 | } | ||
354 | |||
355 | // RemoveTopicByArn removes all topic configurations that match the exact specified ARN | ||
356 | func (b *Configuration) RemoveTopicByArn(arn Arn) { | ||
357 | var topics []TopicConfig | ||
358 | for _, topic := range b.TopicConfigs { | ||
359 | if topic.Topic != arn.String() { | ||
360 | topics = append(topics, topic) | ||
361 | } | ||
362 | } | ||
363 | b.TopicConfigs = topics | ||
364 | } | ||
365 | |||
366 | // ErrNoConfigMatch is returned when a notification configuration (sqs,sns,lambda) is not found when trying to delete | ||
367 | var ErrNoConfigMatch = errors.New("no notification configuration matched") | ||
368 | |||
369 | // RemoveTopicByArnEventsPrefixSuffix removes a topic configuration that match the exact specified ARN, events, prefix and suffix | ||
370 | func (b *Configuration) RemoveTopicByArnEventsPrefixSuffix(arn Arn, events []EventType, prefix, suffix string) error { | ||
371 | removeIndex := -1 | ||
372 | for i, v := range b.TopicConfigs { | ||
373 | // if it matches events and filters, mark the index for deletion | ||
374 | if v.Topic == arn.String() && v.Config.Equal(events, prefix, suffix) { | ||
375 | removeIndex = i | ||
376 | break // since we have at most one matching config | ||
377 | } | ||
378 | } | ||
379 | if removeIndex >= 0 { | ||
380 | b.TopicConfigs = append(b.TopicConfigs[:removeIndex], b.TopicConfigs[removeIndex+1:]...) | ||
381 | return nil | ||
382 | } | ||
383 | return ErrNoConfigMatch | ||
384 | } | ||
385 | |||
386 | // RemoveQueueByArn removes all queue configurations that match the exact specified ARN | ||
387 | func (b *Configuration) RemoveQueueByArn(arn Arn) { | ||
388 | var queues []QueueConfig | ||
389 | for _, queue := range b.QueueConfigs { | ||
390 | if queue.Queue != arn.String() { | ||
391 | queues = append(queues, queue) | ||
392 | } | ||
393 | } | ||
394 | b.QueueConfigs = queues | ||
395 | } | ||
396 | |||
397 | // RemoveQueueByArnEventsPrefixSuffix removes a queue configuration that match the exact specified ARN, events, prefix and suffix | ||
398 | func (b *Configuration) RemoveQueueByArnEventsPrefixSuffix(arn Arn, events []EventType, prefix, suffix string) error { | ||
399 | removeIndex := -1 | ||
400 | for i, v := range b.QueueConfigs { | ||
401 | // if it matches events and filters, mark the index for deletion | ||
402 | if v.Queue == arn.String() && v.Config.Equal(events, prefix, suffix) { | ||
403 | removeIndex = i | ||
404 | break // since we have at most one matching config | ||
405 | } | ||
406 | } | ||
407 | if removeIndex >= 0 { | ||
408 | b.QueueConfigs = append(b.QueueConfigs[:removeIndex], b.QueueConfigs[removeIndex+1:]...) | ||
409 | return nil | ||
410 | } | ||
411 | return ErrNoConfigMatch | ||
412 | } | ||
413 | |||
414 | // RemoveLambdaByArn removes all lambda configurations that match the exact specified ARN | ||
415 | func (b *Configuration) RemoveLambdaByArn(arn Arn) { | ||
416 | var lambdas []LambdaConfig | ||
417 | for _, lambda := range b.LambdaConfigs { | ||
418 | if lambda.Lambda != arn.String() { | ||
419 | lambdas = append(lambdas, lambda) | ||
420 | } | ||
421 | } | ||
422 | b.LambdaConfigs = lambdas | ||
423 | } | ||
424 | |||
425 | // RemoveLambdaByArnEventsPrefixSuffix removes a topic configuration that match the exact specified ARN, events, prefix and suffix | ||
426 | func (b *Configuration) RemoveLambdaByArnEventsPrefixSuffix(arn Arn, events []EventType, prefix, suffix string) error { | ||
427 | removeIndex := -1 | ||
428 | for i, v := range b.LambdaConfigs { | ||
429 | // if it matches events and filters, mark the index for deletion | ||
430 | if v.Lambda == arn.String() && v.Config.Equal(events, prefix, suffix) { | ||
431 | removeIndex = i | ||
432 | break // since we have at most one matching config | ||
433 | } | ||
434 | } | ||
435 | if removeIndex >= 0 { | ||
436 | b.LambdaConfigs = append(b.LambdaConfigs[:removeIndex], b.LambdaConfigs[removeIndex+1:]...) | ||
437 | return nil | ||
438 | } | ||
439 | return ErrNoConfigMatch | ||
440 | } | ||