Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(158)

Side by Side Diff: third_party/gsutil/gslib/commands/notification.py

Issue 1377933002: [catapult] - Copy Telemetry's gsutilz over to third_party. (Closed) Base URL: https://github.com/catapult-project/catapult.git@master
Patch Set: Rename to gsutil. Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/gsutil/gslib/commands/mv.py ('k') | third_party/gsutil/gslib/commands/perfdiag.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # -*- coding: utf-8 -*-
2 # Copyright 2013 Google Inc. All Rights Reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 """This module provides the notification command to gsutil."""
16
17 from __future__ import absolute_import
18
19 import getopt
20 import uuid
21
22 from gslib.cloud_api import AccessDeniedException
23 from gslib.command import Command
24 from gslib.command import NO_MAX
25 from gslib.command_argument import CommandArgument
26 from gslib.cs_api_map import ApiSelector
27 from gslib.exception import CommandException
28 from gslib.help_provider import CreateHelpText
29 from gslib.storage_url import StorageUrlFromString
30
31
32 _WATCHBUCKET_SYNOPSIS = """
33 gsutil notification watchbucket [-i id] [-t token] app_url bucket_url...
34 """
35
36 _STOPCHANNEL_SYNOPSIS = """
37 gsutil notification stopchannel channel_id resource_id
38 """
39
40 _SYNOPSIS = _WATCHBUCKET_SYNOPSIS + _STOPCHANNEL_SYNOPSIS.lstrip('\n')
41
42 _WATCHBUCKET_DESCRIPTION = """
43 <B>WATCHBUCKET</B>
44 The watchbucket sub-command can be used to watch a bucket for object changes.
45 A service account must be used when running this command.
46
47 The app_url parameter must be an HTTPS URL to an application that will be
48 notified of changes to any object in the bucket. The URL endpoint must be
49 a verified domain on your project. See
50 `Notification Authorization <https://developers.google.com/storage/docs/object -change-notification#_Authorization>`_
51 for details.
52
53 The optional id parameter can be used to assign a unique identifier to the
54 created notification channel. If not provided, a random UUID string will be
55 generated.
56
57 The optional token parameter can be used to validate notifications events.
58 To do this, set this custom token and store it to later verify that
59 notification events contain the client token you expect.
60
61 """
62
63 _STOPCHANNEL_DESCRIPTION = """
64 <B>STOPCHANNEL</B>
65 The stopchannel sub-command can be used to stop sending change events to a
66 notification channel.
67
68 The channel_id and resource_id parameters should match the values from the
69 response of a bucket watch request.
70
71 """
72
73 _DESCRIPTION = """
74 The notification command can be used to configure notifications.
75 For more information on the Object Change Notification feature, please see:
76 https://developers.google.com/storage/docs/object-change-notification
77
78 The notification command has two sub-commands:
79 """ + _WATCHBUCKET_DESCRIPTION + _STOPCHANNEL_DESCRIPTION + """
80
81 <B>EXAMPLES</B>
82
83 Watch the bucket example-bucket for changes and send notifications to an
84 application server running at example.com:
85
86 gsutil notification watchbucket https://example.com/notify \\
87 gs://example-bucket
88
89 Assign identifier my-channel-id to the created notification channel:
90
91 gsutil notification watchbucket -i my-channel-id \\
92 https://example.com/notify gs://example-bucket
93
94 Set a custom client token that will be included with each notification event:
95
96 gsutil notification watchbucket -t my-client-token \\
97 https://example.com/notify gs://example-bucket
98
99 Stop the notification event channel with channel identifier channel1 and
100 resource identifier SoGqan08XDIFWr1Fv_nGpRJBHh8:
101
102 gsutil notification stopchannel channel1 SoGqan08XDIFWr1Fv_nGpRJBHh8
103
104 <B>NOTIFICATIONS AND PARALLEL COMPOSITE UPLOADS</B>
105
106 By default, gsutil enables parallel composite uploads for large files (see
107 "gsutil help cp"), which means that an upload of a large object can result
108 in multiple temporary component objects being uploaded before the actual
109 intended object is created. Any subscriber to notifications for this bucket
110 will then see a notification for each of these components being created and
111 deleted. If this is a concern for you, note that parallel composite uploads
112 can be disabled by setting "parallel_composite_upload_threshold = 0" in your
113 boto config file.
114
115 """
116
117 NOTIFICATION_AUTHORIZATION_FAILED_MESSAGE = """
118 Watch bucket attempt failed:
119 {watch_error}
120
121 You attempted to watch a bucket with an application URL of:
122
123 {watch_url}
124
125 which is not authorized for your project. Please ensure that you are using
126 Service Account authentication and that the Service Account's project is
127 authorized for the application URL. Notification endpoint URLs must also be
128 whitelisted in your Cloud Console project. To do that, the domain must also be
129 verified using Google Webmaster Tools. For instructions, please see:
130
131 https://developers.google.com/storage/docs/object-change-notification#_Authori zation
132 """
133
134 _DETAILED_HELP_TEXT = CreateHelpText(_SYNOPSIS, _DESCRIPTION)
135
136 _watchbucket_help_text = (
137 CreateHelpText(_WATCHBUCKET_SYNOPSIS, _WATCHBUCKET_DESCRIPTION))
138 _stopchannel_help_text = (
139 CreateHelpText(_STOPCHANNEL_SYNOPSIS, _STOPCHANNEL_DESCRIPTION))
140
141
142 class NotificationCommand(Command):
143 """Implementation of gsutil notification command."""
144
145 # Command specification. See base class for documentation.
146 command_spec = Command.CreateCommandSpec(
147 'notification',
148 command_name_aliases=[
149 'notify', 'notifyconfig', 'notifications', 'notif'],
150 usage_synopsis=_SYNOPSIS,
151 min_args=3,
152 max_args=NO_MAX,
153 supported_sub_args='i:t:',
154 file_url_ok=False,
155 provider_url_ok=False,
156 urls_start_arg=1,
157 gs_api_support=[ApiSelector.JSON],
158 gs_default_api=ApiSelector.JSON,
159 argparse_arguments={
160 'watchbucket': [
161 CommandArgument.MakeFreeTextArgument(),
162 CommandArgument.MakeZeroOrMoreCloudBucketURLsArgument()
163 ],
164 'stopchannel': []
165 }
166 )
167 # Help specification. See help_provider.py for documentation.
168 help_spec = Command.HelpSpec(
169 help_name='notification',
170 help_name_aliases=['watchbucket', 'stopchannel', 'notifyconfig'],
171 help_type='command_help',
172 help_one_line_summary='Configure object change notification',
173 help_text=_DETAILED_HELP_TEXT,
174 subcommand_help_text={'watchbucket': _watchbucket_help_text,
175 'stopchannel': _stopchannel_help_text},
176 )
177
178 def _WatchBucket(self):
179 """Creates a watch on a bucket given in self.args."""
180 self.CheckArguments()
181 identifier = None
182 client_token = None
183 if self.sub_opts:
184 for o, a in self.sub_opts:
185 if o == '-i':
186 identifier = a
187 if o == '-t':
188 client_token = a
189
190 identifier = identifier or str(uuid.uuid4())
191 watch_url = self.args[0]
192 bucket_arg = self.args[-1]
193
194 if not watch_url.lower().startswith('https://'):
195 raise CommandException('The application URL must be an https:// URL.')
196
197 bucket_url = StorageUrlFromString(bucket_arg)
198 if not (bucket_url.IsBucket() and bucket_url.scheme == 'gs'):
199 raise CommandException(
200 'The %s command can only be used with gs:// bucket URLs.' %
201 self.command_name)
202 if not bucket_url.IsBucket():
203 raise CommandException('URL must name a bucket for the %s command.' %
204 self.command_name)
205
206 self.logger.info('Watching bucket %s with application URL %s ...',
207 bucket_url, watch_url)
208
209 try:
210 channel = self.gsutil_api.WatchBucket(
211 bucket_url.bucket_name, watch_url, identifier, token=client_token,
212 provider=bucket_url.scheme)
213 except AccessDeniedException, e:
214 self.logger.warn(NOTIFICATION_AUTHORIZATION_FAILED_MESSAGE.format(
215 watch_error=str(e), watch_url=watch_url))
216 raise
217
218 channel_id = channel.id
219 resource_id = channel.resourceId
220 client_token = channel.token
221 self.logger.info('Successfully created watch notification channel.')
222 self.logger.info('Watch channel identifier: %s', channel_id)
223 self.logger.info('Canonicalized resource identifier: %s', resource_id)
224 self.logger.info('Client state token: %s', client_token)
225
226 return 0
227
228 def _StopChannel(self):
229 channel_id = self.args[0]
230 resource_id = self.args[1]
231
232 self.logger.info('Removing channel %s with resource identifier %s ...',
233 channel_id, resource_id)
234 self.gsutil_api.StopChannel(channel_id, resource_id, provider='gs')
235 self.logger.info('Succesfully removed channel.')
236
237 return 0
238
239 def _RunSubCommand(self, func):
240 try:
241 (self.sub_opts, self.args) = getopt.getopt(
242 self.args, self.command_spec.supported_sub_args)
243 return func()
244 except getopt.GetoptError, e:
245 self.RaiseInvalidArgumentException()
246
247 def RunCommand(self):
248 """Command entry point for the notification command."""
249 subcommand = self.args.pop(0)
250
251 if subcommand == 'watchbucket':
252 return self._RunSubCommand(self._WatchBucket)
253 elif subcommand == 'stopchannel':
254 return self._RunSubCommand(self._StopChannel)
255 else:
256 raise CommandException('Invalid subcommand "%s" for the %s command.' %
257 (subcommand, self.command_name))
OLDNEW
« no previous file with comments | « third_party/gsutil/gslib/commands/mv.py ('k') | third_party/gsutil/gslib/commands/perfdiag.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698