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

Side by Side Diff: gslib/commands/config.py

Issue 698893003: Update checked in version of gsutil to version 4.6 (Closed) Base URL: http://dart.googlecode.com/svn/third_party/gsutil/
Patch Set: Created 6 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « gslib/commands/compose.py ('k') | gslib/commands/cors.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # -*- coding: utf-8 -*-
1 # Copyright 2011 Google Inc. All Rights Reserved. 2 # Copyright 2011 Google Inc. All Rights Reserved.
2 # 3 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # 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 not use this file except in compliance with the License.
5 # You may obtain a copy of the License at 6 # You may obtain a copy of the License at
6 # 7 #
7 # http://www.apache.org/licenses/LICENSE-2.0 8 # http://www.apache.org/licenses/LICENSE-2.0
8 # 9 #
9 # Unless required by applicable law or agreed to in writing, software 10 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and 13 # See the License for the specific language governing permissions and
13 # limitations under the License. 14 # limitations under the License.
15 """Implementation of config command for creating a gsutil configuration file."""
14 16
15 from __future__ import absolute_import 17 from __future__ import absolute_import
16 18
17 import datetime 19 import datetime
20 from httplib import ResponseNotReady
18 import multiprocessing 21 import multiprocessing
19 import os 22 import os
20 import platform 23 import platform
21 import signal 24 import signal
25 import socket
22 import stat 26 import stat
23 import sys 27 import sys
28 import textwrap
24 import time 29 import time
25 import webbrowser 30 import webbrowser
26 31
27 import boto 32 import boto
28 from boto.provider import Provider 33 from boto.provider import Provider
34 from httplib2 import ServerNotFoundError
35 from oauth2client.client import HAS_CRYPTO
36
29 import gslib 37 import gslib
30 from gslib.command import Command 38 from gslib.command import Command
31 from gslib.command import COMMAND_NAME
32 from gslib.command import COMMAND_NAME_ALIASES
33 from gslib.command import FILE_URIS_OK
34 from gslib.command import MAX_ARGS
35 from gslib.command import MIN_ARGS
36 from gslib.command import PROVIDER_URIS_OK
37 from gslib.command import SUPPORTED_SUB_ARGS
38 from gslib.command import URIS_START_ARG
39 from gslib.commands.compose import MAX_COMPONENT_COUNT 39 from gslib.commands.compose import MAX_COMPONENT_COUNT
40 from gslib.cred_types import CredTypes 40 from gslib.cred_types import CredTypes
41 from gslib.exception import AbortException 41 from gslib.exception import AbortException
42 from gslib.exception import CommandException 42 from gslib.exception import CommandException
43 from gslib.help_provider import HELP_NAME
44 from gslib.help_provider import HELP_NAME_ALIASES
45 from gslib.help_provider import HELP_ONE_LINE_SUMMARY
46 from gslib.help_provider import HELP_TEXT
47 from gslib.help_provider import HELP_TYPE
48 from gslib.help_provider import HelpType
49 from gslib.util import IS_WINDOWS 43 from gslib.util import IS_WINDOWS
50 from gslib.util import TWO_MB 44 from gslib.util import TWO_MB
51 from httplib import ResponseNotReady
52 from httplib2 import ServerNotFoundError
53 from oauth2client.client import HAS_CRYPTO
54 import textwrap
55 from textwrap import TextWrapper
56 45
57 _detailed_help_text = (""" 46
47 _DETAILED_HELP_TEXT = ("""
58 <B>SYNOPSIS</B> 48 <B>SYNOPSIS</B>
59 gsutil [-D] config [-a] [-b] [-e] [-f] [-o <file>] [-r] [-s <scope>] [-w] 49 gsutil [-D] config [-a] [-b] [-e] [-f] [-o <file>] [-r] [-s <scope>] [-w]
60 50
61 51
62 <B>DESCRIPTION</B> 52 <B>DESCRIPTION</B>
63 The gsutil config command obtains access credentials for Google Cloud 53 The gsutil config command obtains access credentials for Google Cloud
64 Storage and writes a boto/gsutil configuration file containing the obtained 54 Storage and writes a boto/gsutil configuration file containing the obtained
65 credentials along with a number of other configuration-controllable values. 55 credentials along with a number of other configuration-controllable values.
66 56
67 Unless specified otherwise (see OPTIONS), the configuration file is written 57 Unless specified otherwise (see OPTIONS), the configuration file is written
(...skipping 19 matching lines...) Expand all
87 77
88 If you want to use credentials based on access key and secret (the older 78 If you want to use credentials based on access key and secret (the older
89 authentication method before OAuth2 was supported) instead of OAuth2, 79 authentication method before OAuth2 was supported) instead of OAuth2,
90 see help about the -a option in the OPTIONS section. 80 see help about the -a option in the OPTIONS section.
91 81
92 If you wish to use gsutil with other providers (or to copy data back and 82 If you wish to use gsutil with other providers (or to copy data back and
93 forth between multiple providers) you can edit their credentials into the 83 forth between multiple providers) you can edit their credentials into the
94 [Credentials] section after creating the initial configuration file. 84 [Credentials] section after creating the initial configuration file.
95 85
96 86
97
98 <B>CONFIGURING SERVICE ACCOUNT CREDENTIALS</B> 87 <B>CONFIGURING SERVICE ACCOUNT CREDENTIALS</B>
99 You can configure credentials for service accounts using the gsutil config -e 88 You can configure credentials for service accounts using the gsutil config -e
100 option. Service accounts are useful for authenticating on behalf of a service 89 option. Service accounts are useful for authenticating on behalf of a service
101 or application (as opposed to a user). 90 or application (as opposed to a user).
102 91
103 When you run gsutil config -e, you will be prompted for your service account 92 When you run gsutil config -e, you will be prompted for your service account
104 email address and the path to your private key file. To get these data, visit 93 email address and the path to your private key file. To get these data, visit
105 the `Google Cloud Console <https://cloud.google.com/console#/project>`_, click 94 the `Google Developers Console <https://cloud.google.com/console#/project>`_,
106 on the project you are using, then click "APIs & auth", then click "Registered 95 click on the project you are using, then click "APIs & auth", then click
107 apps", then click on the name of the registered app. (Note: for service 96 "Credentials", then click "CREATE NEW CLIENT ID"; on the pop-up dialog box
108 accounts created via the older API Developer's Console, the name will be 97 select "Service account" and click "Create Client ID". This will download
109 something like "Service Account-<service account id>".) This page lists 98 a private key file, which you should move to somewhere
110 the email address of your service account. From this page you can also click 99 accessible from the machine where you run gsutil. Make sure to set its
111 Generate New Key, to generate and download the private key file. Save this 100 protection so only the users you want to be able to authenticate have
112 file somewhere accessible from the machine where you run gsutil. Make sure 101 access.
113 to set its protection so only the users you want to be able to authenticate
114 as have access.
115 102
116 Note that your service account will NOT be considered an Owner for the 103 Note that your service account will NOT be considered an Owner for the
117 purposes of API access (see "gsutil help creds" for more information about 104 purposes of API access (see "gsutil help creds" for more information about
118 this). See https://developers.google.com/accounts/docs/OAuth2ServiceAccount 105 this). See https://developers.google.com/accounts/docs/OAuth2ServiceAccount
119 for further information on service account authentication. 106 for further information on service account authentication.
120 107
121 108
122 <B>CONFIGURATION FILE SELECTION PROCEDURE</B> 109 <B>CONFIGURATION FILE SELECTION PROCEDURE</B>
123 By default, gsutil will look for the configuration file in /etc/boto.cfg and 110 By default, gsutil will look for the configuration file in /etc/boto.cfg and
124 ~/.boto. You can override this choice by setting the BOTO_CONFIG environment 111 ~/.boto. You can override this choice by setting the BOTO_CONFIG environment
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 option-controllable features. 144 option-controllable features.
158 145
159 The following are the currently defined configuration settings, broken 146 The following are the currently defined configuration settings, broken
160 down by section. Their use is documented in comments preceding each, in 147 down by section. Their use is documented in comments preceding each, in
161 the configuration file. If you see a setting you want to change that's not 148 the configuration file. If you see a setting you want to change that's not
162 listed in your current file, see the section below on Updating to the Latest 149 listed in your current file, see the section below on Updating to the Latest
163 Configuration File. 150 Configuration File.
164 151
165 The currently supported settings, are, by section: 152 The currently supported settings, are, by section:
166 153
154 [Credentials]
155 aws_access_key_id
156 aws_secret_access_key
157 gs_access_key_id
158 gs_host
159 gs_json_host
160 gs_json_port
161 gs_oauth2_refresh_token
162 gs_port
163 gs_secret_access_key
164 s3_host
165 s3_port
166
167 [Boto] 167 [Boto]
168 proxy 168 proxy
169 proxy_port 169 proxy_port
170 proxy_user 170 proxy_user
171 proxy_pass 171 proxy_pass
172 proxy_rdns
172 http_socket_timeout 173 http_socket_timeout
173 is_secure
174 https_validate_certificates 174 https_validate_certificates
175 debug 175 debug
176 max_retry_delay
176 num_retries 177 num_retries
177 178
178 [GSUtil] 179 [GSUtil]
179 resumable_threshold 180 check_hashes
180 resumable_tracker_dir 181 content_language
181 software_update_check_period 182 default_api_version
183 default_project_id
184 json_api_version
185 parallel_composite_upload_component_size
186 parallel_composite_upload_threshold
182 parallel_process_count 187 parallel_process_count
183 parallel_thread_count 188 parallel_thread_count
184 parallel_composite_upload_threshold 189 prefer_api
185 parallel_composite_upload_component_size 190 resumable_threshold
191 resumable_tracker_dir (deprecated in 4.6, use state_dir)
192 rsync_buffer_lines
193 software_update_check_period
194 state_dir
186 use_magicfile 195 use_magicfile
187 content_language
188 check_hashes
189 default_api_version
190 default_project_id
191 discovery_service_url
192 json_api_version
193 196
194 [OAuth2] 197 [OAuth2]
195 token_cache
196 token_cache
197 client_id 198 client_id
198 client_secret 199 client_secret
200 oauth2_refresh_retries
201 provider_authorization_uri
199 provider_label 202 provider_label
200 provider_authorization_uri
201 provider_token_uri 203 provider_token_uri
202 oauth2_refresh_retries 204 token_cache
203 205
204 206
205 <B>UPDATING TO THE LATEST CONFIGURATION FILE</B> 207 <B>UPDATING TO THE LATEST CONFIGURATION FILE</B>
206 We add new configuration controllable features to the boto configuration file 208 We add new configuration controllable features to the boto configuration file
207 over time, but most gsutil users create a configuration file once and then 209 over time, but most gsutil users create a configuration file once and then
208 keep it for a long time, so new features aren't apparent when you update 210 keep it for a long time, so new features aren't apparent when you update
209 to a newer version of gsutil. If you want to get the latest configuration 211 to a newer version of gsutil. If you want to get the latest configuration
210 file (which includes all the latest settings and documentation about each) 212 file (which includes all the latest settings and documentation about each)
211 you can rename your current file (e.g., to '.boto_old'), run gsutil config, 213 you can rename your current file (e.g., to '.boto_old'), run gsutil config,
212 and then edit any configuration settings you wanted from your old file 214 and then edit any configuration settings you wanted from your old file
(...skipping 25 matching lines...) Expand all
238 240
239 -r Request token restricted to read-only access. 241 -r Request token restricted to read-only access.
240 242
241 -s <scope> Request additional OAuth2 <scope>. 243 -s <scope> Request additional OAuth2 <scope>.
242 244
243 -w Request token restricted to read-write access. 245 -w Request token restricted to read-write access.
244 """) 246 """)
245 247
246 248
247 try: 249 try:
248 from gslib.third_party.oauth2_plugin import oauth2_helper 250 from gcs_oauth2_boto_plugin import oauth2_helper # pylint: disable=g-import-n ot-at-top
249 except ImportError: 251 except ImportError:
250 pass 252 pass
251 253
252 GOOG_CLOUD_CONSOLE_URI = 'https://cloud.google.com/console#/project' 254 GOOG_CLOUD_CONSOLE_URI = 'https://cloud.google.com/console#/project'
253 255
254 SCOPE_FULL_CONTROL = 'https://www.googleapis.com/auth/devstorage.full_control' 256 SCOPE_FULL_CONTROL = 'https://www.googleapis.com/auth/devstorage.full_control'
255 SCOPE_READ_WRITE = 'https://www.googleapis.com/auth/devstorage.read_write' 257 SCOPE_READ_WRITE = 'https://www.googleapis.com/auth/devstorage.read_write'
256 SCOPE_READ_ONLY = 'https://www.googleapis.com/auth/devstorage.read_only' 258 SCOPE_READ_ONLY = 'https://www.googleapis.com/auth/devstorage.read_only'
257 259
258 CONFIG_PRELUDE_CONTENT = """ 260 CONFIG_PRELUDE_CONTENT = """
(...skipping 14 matching lines...) Expand all
273 # On Windows and Mac systems parallel multi-processing and multi-threading 275 # On Windows and Mac systems parallel multi-processing and multi-threading
274 # in Python presents various challenges so we retain compatibility with 276 # in Python presents various challenges so we retain compatibility with
275 # the established parallel mode operation, i.e. one process and 24 threads. 277 # the established parallel mode operation, i.e. one process and 24 threads.
276 if platform.system() == 'Linux': 278 if platform.system() == 'Linux':
277 DEFAULT_PARALLEL_PROCESS_COUNT = multiprocessing.cpu_count() 279 DEFAULT_PARALLEL_PROCESS_COUNT = multiprocessing.cpu_count()
278 DEFAULT_PARALLEL_THREAD_COUNT = 10 280 DEFAULT_PARALLEL_THREAD_COUNT = 10
279 else: 281 else:
280 DEFAULT_PARALLEL_PROCESS_COUNT = 1 282 DEFAULT_PARALLEL_PROCESS_COUNT = 1
281 DEFAULT_PARALLEL_THREAD_COUNT = 24 283 DEFAULT_PARALLEL_THREAD_COUNT = 24
282 284
283 DEFAULT_PARALLEL_COMPOSITE_UPLOAD_THRESHOLD = '150M' 285 # TODO: Once compiled crcmod is being distributed by major Linux distributions
286 # revert DEFAULT_PARALLEL_COMPOSITE_UPLOAD_THRESHOLD value to '150M'.
287 DEFAULT_PARALLEL_COMPOSITE_UPLOAD_THRESHOLD = '0'
284 DEFAULT_PARALLEL_COMPOSITE_UPLOAD_COMPONENT_SIZE = '50M' 288 DEFAULT_PARALLEL_COMPOSITE_UPLOAD_COMPONENT_SIZE = '50M'
285 289
290 CHECK_HASH_IF_FAST_ELSE_FAIL = 'if_fast_else_fail'
291 CHECK_HASH_IF_FAST_ELSE_SKIP = 'if_fast_else_skip'
292 CHECK_HASH_ALWAYS = 'always'
293 CHECK_HASH_NEVER = 'never'
294
286 CONFIG_BOTO_SECTION_CONTENT = """ 295 CONFIG_BOTO_SECTION_CONTENT = """
287 [Boto] 296 [Boto]
288 297
289 # http_socket_timeout specifies the timeout (in seconds) used to tell httplib 298 # http_socket_timeout specifies the timeout (in seconds) used to tell httplib
290 # how long to wait for socket timeouts. The default is 70 seconds. Note that 299 # how long to wait for socket timeouts. The default is 70 seconds. Note that
291 # this timeout only applies to httplib, not to httplib2 (which is used for 300 # this timeout only applies to httplib, not to httplib2 (which is used for
292 # OAuth2 refresh/access token exchanges). 301 # OAuth2 refresh/access token exchanges).
293 #http_socket_timeout = 70 302 #http_socket_timeout = 70
294 303
295 # The following two options control the use of a secure transport for requests 304 # The following two options control the use of a secure transport for requests
296 # to S3 and Google Cloud Storage. It is highly recommended to set both options 305 # to S3 and Google Cloud Storage. It is highly recommended to set both options
297 # to True in production environments, especially when using OAuth2 bearer token 306 # to True in production environments, especially when using OAuth2 bearer token
298 # authentication with Google Cloud Storage. 307 # authentication with Google Cloud Storage.
299 308
300 # Set 'is_secure' to False to cause boto to connect using HTTP instead of the
301 # default HTTPS. This is useful if you want to capture/analyze traffic
302 # (e.g., with tcpdump).
303 # WARNING: This option should always be set to True (the default value) in
304 # production environments, for several reasons:
305 # 1. OAuth2 refresh and access tokens are bearer tokens, so must be
306 # protected from exposure on the wire.
307 # 2. Resumable upload IDs are bearer tokens, so similarly must be protected.
308 # 3. The gsutil update command needs to run over HTTPS to guard against
309 # man-in-the-middle attacks on code updates.
310 # 4. User data shouldn't be sent in the clear.
311 #is_secure = True
312
313 # Set 'https_validate_certificates' to False to disable server certificate 309 # Set 'https_validate_certificates' to False to disable server certificate
314 # checking. The default for this option in the boto library is currently 310 # checking. The default for this option in the boto library is currently
315 # 'False' (to avoid breaking apps that depend on invalid certificates); it is 311 # 'False' (to avoid breaking apps that depend on invalid certificates); it is
316 # therefore strongly recommended to always set this option explicitly to True 312 # therefore strongly recommended to always set this option explicitly to True
317 # in configuration files, to protect against "man-in-the-middle" attacks. 313 # in configuration files, to protect against "man-in-the-middle" attacks.
318 https_validate_certificates = True 314 https_validate_certificates = True
319 315
320 # 'debug' controls the level of debug messages printed: 0 for none, 1 316 # 'debug' controls the level of debug messages printed: 0 for none, 1
321 # for basic boto debug, 2 for all boto debug plus HTTP requests/responses. 317 # for basic boto debug, 2 for all boto debug plus HTTP requests/responses.
322 # Note: 'gsutil -d' sets debug to 2 for that one command run. 318 # Note: 'gsutil -d' sets debug to 2 for that one command run.
323 #debug = <0, 1, or 2> 319 #debug = <0, 1, or 2>
324 320
325 # 'num_retries' controls the number of retry attempts made when errors occur 321 # 'num_retries' controls the number of retry attempts made when errors occur
326 # during data transfers. The default is 6. Note: don't set this value to 0, as 322 # during data transfers. The default is 6.
327 # it will cause boto to fail when reusing HTTP connections. 323 # Note 1: You can cause gsutil to retry failures effectively infinitely by
324 # setting this value to a large number (like 10000). Doing that could be useful
325 # in cases where your network connection occasionally fails and is down for an
326 # extended period of time, because when it comes back up gsutil will continue
327 # retrying. However, in general we recommend not setting the value above 10,
328 # because otherwise gsutil could appear to "hang" due to excessive retries
329 # (since unless you run gsutil -D you won't see any logged evidence that gsutil
330 # is retrying).
331 # Note 2: Don't set this value to 0, as it will cause boto to fail when reusing
332 # HTTP connections.
328 #num_retries = <integer value> 333 #num_retries = <integer value>
334
335 # 'max_retry_delay' controls the max delay (in seconds) between retries. The
336 # default value is 60, so the backoff sequence will be 1 seconds, 2 seconds, 4,
337 # 8, 16, 32, and then 60 for all subsequent retries for a given HTTP request.
338 # Note: At present this value only impacts the XML API and the JSON API uses a
339 # fixed value of 60.
340 #max_retry_delay = <integer value>
329 """ 341 """
330 342
331 CONFIG_INPUTLESS_GSUTIL_SECTION_CONTENT = """ 343 CONFIG_INPUTLESS_GSUTIL_SECTION_CONTENT = """
332 [GSUtil] 344 [GSUtil]
333 345
334 # 'resumable_threshold' specifies the smallest file size [bytes] for which 346 # 'resumable_threshold' specifies the smallest file size [bytes] for which
335 # resumable Google Cloud Storage transfers are attempted. The default is 2097152 347 # resumable Google Cloud Storage transfers are attempted. The default is 2097152
336 # (2 MiB). 348 # (2 MiB).
337 #resumable_threshold = %(resumable_threshold)d 349 #resumable_threshold = %(resumable_threshold)d
338 350
339 # 'resumable_tracker_dir' specifies the base location where resumable 351 # 'rsync_buffer_lines' specifies the number of lines of bucket or directory
340 # transfer tracker files are saved. By default they're in ~/.gsutil 352 # listings saved in each temp file during sorting. (The complete set is
341 #resumable_tracker_dir = <file path> 353 # split across temp files and separately sorted/merged, to avoid needing to
342 # gsutil also saves a file called .last_software_update_check in this directory, 354 # fit everything in memory at once.) If you are trying to synchronize very
343 # that tracks the last time a check was made whether a new version of the gsutil 355 # large directories/buckets (e.g., containing millions or more objects),
344 # software is available. 'software_update_check_period' specifies the number of 356 # having too small a value here can cause gsutil to run out of open file
345 # days between such checks. The default is 30. Setting the value to 0 disables 357 # handles. If that happens, you can try to increase the number of open file
358 # handles your system allows (e.g., see 'man ulimit' on Linux; see also
359 # http://docs.python.org/2/library/resource.html). If you can't do that (or
360 # if you're already at the upper limit), increasing rsync_buffer_lines will
361 # cause gsutil to use fewer file handles, but at the cost of more memory. With
362 # rsync_buffer_lines set to 32000 and assuming a typical URL is 100 bytes
363 # long, gsutil will require approximately 10MB of memory while building
364 # the synchronization state, and will require approximately 60 open file
365 # descriptors to build the synchronization state over all 1M source and 1M
366 # destination URLs. Memory and file descriptors are only consumed while
367 # building the state; once the state is built, it resides in two temp files that
368 # are read and processed incrementally during the actual copy/delete
369 # operations.
370 #rsync_buffer_lines = 32000
371
372 # 'state_dir' specifies the base location where files that
373 # need a static location are stored, such as pointers to credentials,
374 # resumable transfer tracker files, and the last software update check.
375 # By default these files are stored in ~/.gsutil
376 #state_dir = <file_path>
377 # gsutil periodically checks whether a new version of the gsutil software is
378 # available. 'software_update_check_period' specifies the number of days
379 # between such checks. The default is 30. Setting the value to 0 disables
346 # periodic software update checks. 380 # periodic software update checks.
347 #software_update_check_period = 30 381 #software_update_check_period = 30
348 382
349 # 'parallel_process_count' and 'parallel_thread_count' specify the number 383 # 'parallel_process_count' and 'parallel_thread_count' specify the number
350 # of OS processes and Python threads, respectively, to use when executing 384 # of OS processes and Python threads, respectively, to use when executing
351 # operations in parallel. The default settings should work well as configured, 385 # operations in parallel. The default settings should work well as configured,
352 # however, to enhance performance for transfers involving large numbers of 386 # however, to enhance performance for transfers involving large numbers of
353 # files, you may experiment with hand tuning these values to optimize 387 # files, you may experiment with hand tuning these values to optimize
354 # performance for your particular system configuration. 388 # performance for your particular system configuration.
355 # MacOS and Windows users should see 389 # MacOS and Windows users should see
356 # https://github.com/GoogleCloudPlatform/gsutil/issues/77 before attempting 390 # https://github.com/GoogleCloudPlatform/gsutil/issues/77 before attempting
357 # to experiment with these values. 391 # to experiment with these values.
358 #parallel_process_count = %(parallel_process_count)d 392 #parallel_process_count = %(parallel_process_count)d
359 #parallel_thread_count = %(parallel_thread_count)d 393 #parallel_thread_count = %(parallel_thread_count)d
360 394
361 # 'parallel_composite_upload_threshold' specifies the maximum size of a file to 395 # 'parallel_composite_upload_threshold' specifies the maximum size of a file to
362 # upload in a single stream. Files larger than this threshold will be 396 # upload in a single stream. Files larger than this threshold will be
363 # partitioned into component parts and uploaded in parallel and then composed 397 # partitioned into component parts and uploaded in parallel and then composed
364 # into a single object. 398 # into a single object.
365 # The number of components will be the smaller of 399 # The number of components will be the smaller of
366 # ceil(file_size / parallel_composite_upload_component_size) and 400 # ceil(file_size / parallel_composite_upload_component_size) and
367 # MAX_COMPONENT_COUNT. The current value of MAX_COMPONENT_COUNT is 401 # MAX_COMPONENT_COUNT. The current value of MAX_COMPONENT_COUNT is
368 # %(max_component_count)d. 402 # %(max_component_count)d.
369 # If 'parallel_composite_upload_threshold' is set to 0, then automatic parallel 403 # If 'parallel_composite_upload_threshold' is set to 0, then automatic parallel
370 # uploads will never occur. 404 # uploads will never occur.
405 # Setting an extremely low threshold is unadvisable. The vast majority of
406 # environments will see degraded performance for thresholds below 80M, and it
407 # is almost never advantageous to have a threshold below 20M.
371 # 'parallel_composite_upload_component_size' specifies the ideal size of a 408 # 'parallel_composite_upload_component_size' specifies the ideal size of a
372 # component in bytes, which will act as an upper bound to the size of the 409 # component in bytes, which will act as an upper bound to the size of the
373 # components if ceil(file_size / parallel_composite_upload_component_size) is 410 # components if ceil(file_size / parallel_composite_upload_component_size) is
374 # less than MAX_COMPONENT_COUNT. 411 # less than MAX_COMPONENT_COUNT.
375 # Values can be provided either in bytes or as human-readable values 412 # Values can be provided either in bytes or as human-readable values
376 # (e.g., "150M" to represent 150 megabytes) 413 # (e.g., "150M" to represent 150 megabytes)
414 #
415 # Note: At present parallel composite uploads are disabled by default, because
416 # using composite objects requires a compiled crcmod (see "gsutil help crcmod"),
417 # and for operating systems that don't already have this package installed this
418 # makes gsutil harder to use. Google is actively working with a number of the
419 # Linux distributions to get crcmod included with the stock distribution. Once
420 # that is done we will re-enable parallel composite uploads by default in
421 # gsutil.
377 #parallel_composite_upload_threshold = %(parallel_composite_upload_threshold)s 422 #parallel_composite_upload_threshold = %(parallel_composite_upload_threshold)s
378 #parallel_composite_upload_component_size = %(parallel_composite_upload_componen t_size)s 423 #parallel_composite_upload_component_size = %(parallel_composite_upload_componen t_size)s
379 424
380 # 'use_magicfile' specifies if the 'file --mime-type <filename>' command should 425 # 'use_magicfile' specifies if the 'file --mime-type <filename>' command should
381 # be used to guess content types instead of the default filename extension-based 426 # be used to guess content types instead of the default filename extension-based
382 # mechanism. Available on UNIX and MacOS (and possibly on Windows, if you're 427 # mechanism. Available on UNIX and MacOS (and possibly on Windows, if you're
383 # running Cygwin or some other package that provides implementations of 428 # running Cygwin or some other package that provides implementations of
384 # UNIX-like commands). When available and enabled use_magicfile should be more 429 # UNIX-like commands). When available and enabled use_magicfile should be more
385 # robust because it analyzes file contents in addition to extensions. 430 # robust because it analyzes file contents in addition to extensions.
386 #use_magicfile = False 431 #use_magicfile = False
387 432
388 # 'content_language' specifies the ISO 639-1 language code of the content, to be 433 # 'content_language' specifies the ISO 639-1 language code of the content, to be
389 # passed in the Content-Language header. By default no Content-Language is sent. 434 # passed in the Content-Language header. By default no Content-Language is sent.
390 # See the ISO 639-1 column of 435 # See the ISO 639-1 column of
391 # http://www.loc.gov/standards/iso639-2/php/code_list.php for a list of 436 # http://www.loc.gov/standards/iso639-2/php/code_list.php for a list of
392 # language codes. 437 # language codes.
393 content_language = en 438 content_language = en
394 439
395 # 'check_hashes' specifies how strictly to require integrity checking for 440 # 'check_hashes' specifies how strictly to require integrity checking for
396 # downloaded data. Legal values are: 441 # downloaded data. Legal values are:
397 # 'if_fast_else_fail' - (default) Only integrity check if the digest will run 442 # '%(hash_fast_else_fail)s' - (default) Only integrity check if the digest
398 # efficiently (using compiled code), else fail the download. 443 # will run efficiently (using compiled code), else fail the download.
399 # 'if_fast_else_skip' - Only integrity check if the server supplies a hash and 444 # '%(hash_fast_else_skip)s' - Only integrity check if the server supplies a
400 # the local digest computation will run quickly, else skip the check. 445 # hash and the local digest computation will run quickly, else skip the
401 # 'always' - Always check download integrity regardless of possible 446 # check.
447 # '%(hash_always)s' - Always check download integrity regardless of possible
402 # performance costs. 448 # performance costs.
403 # 'never' - Don't perform download integrity checks. This settings is not 449 # '%(hash_never)s' - Don't perform download integrity checks. This setting is
404 # recommended except for special cases such as measuring download 450 # not recommended except for special cases such as measuring download
405 # performance excluding time for integrity checking. 451 # performance excluding time for integrity checking.
406 # This option exists to assist users who wish to download a GCS composite object 452 # This option exists to assist users who wish to download a GCS composite object
407 # and are unable to install crcmod with the C-extension. CRC32c is the only 453 # and are unable to install crcmod with the C-extension. CRC32c is the only
408 # available integrity check for composite objects, and without the C-extension, 454 # available integrity check for composite objects, and without the C-extension,
409 # download performance can be significantly degraded by the digest computation. 455 # download performance can be significantly degraded by the digest computation.
410 #check_hashes = if_fast_else_fail 456 #check_hashes = if_fast_else_fail
411 457
412 # The ability to specify an alternative discovery service URL is primarily for
413 # cloud storage service developers.
414 #discovery_service_url = https://www.googleapis.com/discovery/v1/apis/{api}/{api Version}/rest
415 # The ability to specify an alternative JSON API version is primarily for cloud 458 # The ability to specify an alternative JSON API version is primarily for cloud
416 # storage service developers. 459 # storage service developers.
417 #json_api_version = v1beta2 460 #json_api_version = v1
418 461
419 """ % {'resumable_threshold': TWO_MB, 462 # Specifies the API to use when interacting with cloud storage providers. If
463 # the gsutil command supports this API for the provider, it will be used
464 # instead of the default.
465 # Commands typically default to XML for S3 and JSON for GCS.
466 #prefer_api = json
467 #prefer_api = xml
468
469 """ % {'hash_fast_else_fail': CHECK_HASH_IF_FAST_ELSE_FAIL,
470 'hash_fast_else_skip': CHECK_HASH_IF_FAST_ELSE_SKIP,
471 'hash_always': CHECK_HASH_ALWAYS,
472 'hash_never': CHECK_HASH_NEVER,
473 'resumable_threshold': TWO_MB,
420 'parallel_process_count': DEFAULT_PARALLEL_PROCESS_COUNT, 474 'parallel_process_count': DEFAULT_PARALLEL_PROCESS_COUNT,
421 'parallel_thread_count': DEFAULT_PARALLEL_THREAD_COUNT, 475 'parallel_thread_count': DEFAULT_PARALLEL_THREAD_COUNT,
422 'parallel_composite_upload_threshold': ( 476 'parallel_composite_upload_threshold': (
423 DEFAULT_PARALLEL_COMPOSITE_UPLOAD_THRESHOLD), 477 DEFAULT_PARALLEL_COMPOSITE_UPLOAD_THRESHOLD),
424 'parallel_composite_upload_component_size': ( 478 'parallel_composite_upload_component_size': (
425 DEFAULT_PARALLEL_COMPOSITE_UPLOAD_COMPONENT_SIZE), 479 DEFAULT_PARALLEL_COMPOSITE_UPLOAD_COMPONENT_SIZE),
426 'max_component_count': MAX_COMPONENT_COUNT} 480 'max_component_count': MAX_COMPONENT_COUNT}
427 481
428 CONFIG_OAUTH2_CONFIG_CONTENT = """ 482 CONFIG_OAUTH2_CONFIG_CONTENT = """
429 [OAuth2] 483 [OAuth2]
430 # This section specifies options used with OAuth2 authentication. 484 # This section specifies options used with OAuth2 authentication.
431 485
432 # 'token_cache' specifies how the OAuth2 client should cache access tokens. 486 # 'token_cache' specifies how the OAuth2 client should cache access tokens.
433 # Valid values are: 487 # Valid values are:
434 # 'in_memory': an in-memory cache is used. This is only useful if the boto 488 # 'in_memory': an in-memory cache is used. This is only useful if the boto
435 # client instance (and with it the OAuth2 plugin instance) persists 489 # client instance (and with it the OAuth2 plugin instance) persists
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 # 'oauth2_refresh_retries' controls the number of retry attempts made when 525 # 'oauth2_refresh_retries' controls the number of retry attempts made when
472 # rate limiting errors occur for OAuth2 requests to retrieve an access token. 526 # rate limiting errors occur for OAuth2 requests to retrieve an access token.
473 # The default value is 6. 527 # The default value is 6.
474 #oauth2_refresh_retries = <integer value> 528 #oauth2_refresh_retries = <integer value>
475 """ 529 """
476 530
477 531
478 class ConfigCommand(Command): 532 class ConfigCommand(Command):
479 """Implementation of gsutil config command.""" 533 """Implementation of gsutil config command."""
480 534
481 # Command specification (processed by parent class). 535 # Command specification. See base class for documentation.
482 command_spec = { 536 command_spec = Command.CreateCommandSpec(
483 # Name of command. 537 'config',
484 COMMAND_NAME: 'config', 538 command_name_aliases=['cfg', 'conf', 'configure'],
485 # List of command name aliases. 539 min_args=0,
486 COMMAND_NAME_ALIASES: ['cfg', 'conf', 'configure'], 540 max_args=0,
487 # Min number of args required by this command. 541 supported_sub_args='habefwrs:o:',
488 MIN_ARGS: 0, 542 file_url_ok=False,
489 # Max number of args required by this command, or NO_MAX. 543 provider_url_ok=False,
490 MAX_ARGS: 0, 544 urls_start_arg=0,
491 # Getopt-style string specifying acceptable sub args. 545 )
492 SUPPORTED_SUB_ARGS: 'habefwrs:o:', 546 # Help specification. See help_provider.py for documentation.
493 # True if file URIs acceptable for this command. 547 help_spec = Command.HelpSpec(
494 FILE_URIS_OK: False, 548 help_name='config',
495 # True if provider-only URIs acceptable for this command. 549 help_name_aliases=['cfg', 'conf', 'configure', 'proxy', 'aws', 's3'],
496 PROVIDER_URIS_OK: False, 550 help_type='command_help',
497 # Index in args of first URI arg. 551 help_one_line_summary=(
498 URIS_START_ARG: 0, 552 'Obtain credentials and create configuration file'),
499 } 553 help_text=_DETAILED_HELP_TEXT,
500 help_spec = { 554 subcommand_help_text={},
501 # Name of command or auxiliary help info for which this help applies. 555 )
502 HELP_NAME: 'config',
503 # List of help name aliases.
504 HELP_NAME_ALIASES: ['cfg', 'conf', 'configure', 'proxy', 'aws', 's3'],
505 # Type of help:
506 HELP_TYPE: HelpType.COMMAND_HELP,
507 # One line summary of this help.
508 HELP_ONE_LINE_SUMMARY: 'Obtain credentials and create configuration file',
509 # The full help text.
510 HELP_TEXT: _detailed_help_text,
511 }
512 556
513 def _OpenConfigFile(self, file_path): 557 def _OpenConfigFile(self, file_path):
514 """Creates and opens a configuration file for writing. 558 """Creates and opens a configuration file for writing.
515 559
516 The file is created with mode 0600, and attempts to open existing files will 560 The file is created with mode 0600, and attempts to open existing files will
517 fail (the latter is important to prevent symlink attacks). 561 fail (the latter is important to prevent symlink attacks).
518 562
519 It is the caller's responsibility to close the file. 563 It is the caller's responsibility to close the file.
520 564
521 Args: 565 Args:
522 file_path: Path of the file to be created. 566 file_path: Path of the file to be created.
523 567
524 Returns: 568 Returns:
525 A writable file object for the opened file. 569 A writable file object for the opened file.
526 570
527 Raises: 571 Raises:
528 CommandException: if an error occurred when opening the file (including 572 CommandException: if an error occurred when opening the file (including
529 when the file already exists). 573 when the file already exists).
530 """ 574 """
531 flags = os.O_RDWR | os.O_CREAT | os.O_EXCL 575 flags = os.O_RDWR | os.O_CREAT | os.O_EXCL
532 # Accommodate Windows; stolen from python2.6/tempfile.py. 576 # Accommodate Windows; copied from python2.6/tempfile.py.
533 if hasattr(os, 'O_NOINHERIT'): 577 if hasattr(os, 'O_NOINHERIT'):
534 flags |= os.O_NOINHERIT 578 flags |= os.O_NOINHERIT
535 try: 579 try:
536 fd = os.open(file_path, flags, 0600) 580 fd = os.open(file_path, flags, 0600)
537 except (OSError, IOError), e: 581 except (OSError, IOError), e:
538 raise CommandException('Failed to open %s for writing: %s' % 582 raise CommandException('Failed to open %s for writing: %s' %
539 (file_path, e)) 583 (file_path, e))
540 return os.fdopen(fd, 'w') 584 return os.fdopen(fd, 'w')
541 585
542 def _CheckPrivateKeyFilePermissions(self, file_path): 586 def _CheckPrivateKeyFilePermissions(self, file_path):
543 """Checks that the file has reasonable permissions for a private key. 587 """Checks that the file has reasonable permissions for a private key.
544 588
545 In particular, check that the filename provided by the user is not 589 In particular, check that the filename provided by the user is not
546 world- or group-readable. If either of these are true, we issue a warning 590 world- or group-readable. If either of these are true, we issue a warning
547 and offer to fix the permissions. 591 and offer to fix the permissions.
548 592
549 Args: 593 Args:
550 filename: The name of the private key file. 594 file_path: The name of the private key file.
551 """ 595 """
552 if IS_WINDOWS: 596 if IS_WINDOWS:
553 # For Windows, this check doesn't work (it actually just checks whether 597 # For Windows, this check doesn't work (it actually just checks whether
554 # the file is read-only). Since Windows files have a complicated ACL 598 # the file is read-only). Since Windows files have a complicated ACL
555 # system, this check doesn't make much sense on Windows anyway, so we 599 # system, this check doesn't make much sense on Windows anyway, so we
556 # just don't do it. 600 # just don't do it.
557 return 601 return
558 602
559 st = os.stat(file_path) 603 st = os.stat(file_path)
560 if bool((stat.S_IRGRP | stat.S_IROTH) & st.st_mode): 604 if bool((stat.S_IRGRP | stat.S_IROTH) & st.st_mode):
561 self.logger.warn( 605 self.logger.warn(
562 '\nYour private key file is readable by people other than yourself.\n' 606 '\nYour private key file is readable by people other than yourself.\n'
563 'This is a security risk, since anyone with this information can use ' 607 'This is a security risk, since anyone with this information can use '
564 'your service account.\n') 608 'your service account.\n')
565 fix_it = raw_input('Would you like gsutil to change the file ' 609 fix_it = raw_input('Would you like gsutil to change the file '
566 'permissions for you? (y/N) ') 610 'permissions for you? (y/N) ')
567 if fix_it in ('y', 'Y'): 611 if fix_it in ('y', 'Y'):
568 try: 612 try:
569 os.chmod(file_path, 0400) 613 os.chmod(file_path, 0400)
570 self.logger.info( 614 self.logger.info(
571 '\nThe permissions on your file have been successfully ' 615 '\nThe permissions on your file have been successfully '
572 'modified.' 616 'modified.'
573 '\nThe only access allowed is readability by the user ' 617 '\nThe only access allowed is readability by the user '
574 '(permissions 0400 in chmod).') 618 '(permissions 0400 in chmod).')
575 except Exception as e: 619 except Exception, _: # pylint: disable=broad-except
576 self.logger.warn( 620 self.logger.warn(
577 '\nWe were unable to modify the permissions on your file.\n' 621 '\nWe were unable to modify the permissions on your file.\n'
578 'If you would like to fix this yourself, consider running:\n' 622 'If you would like to fix this yourself, consider running:\n'
579 '"sudo chmod 400 </path/to/key>" for improved security.') 623 '"sudo chmod 400 </path/to/key>" for improved security.')
580 else: 624 else:
581 self.logger.info( 625 self.logger.info(
582 '\nYou have chosen to allow this file to be readable by others.\n' 626 '\nYou have chosen to allow this file to be readable by others.\n'
583 'If you would like to fix this yourself, consider running:\n' 627 'If you would like to fix this yourself, consider running:\n'
584 '"sudo chmod 400 </path/to/key>" for improved security.') 628 '"sudo chmod 400 </path/to/key>" for improved security.')
585 629
586 def _PromptForProxyConfigVarAndMaybeSaveToBotoConfig(self, varname, prompt): 630 def _PromptForProxyConfigVarAndMaybeSaveToBotoConfig(self, varname, prompt,
587 """Prompts user for one proxy configuration line, and saves to boto.config 631 convert_to_bool=False):
588 if not empty. 632 """Prompts for one proxy config line, saves to boto.config if not empty.
589 633
590 Args: 634 Args:
591 varname: The config variable name. 635 varname: The config variable name.
592 prompt: The prompt to output to the user. 636 prompt: The prompt to output to the user.
637 convert_to_bool: Whether to convert "y/n" to True/False.
593 """ 638 """
594 value = raw_input(prompt) 639 value = raw_input(prompt)
595 if value: 640 if value:
641 if convert_to_bool:
642 if value == 'y' or value == 'Y':
643 value = 'True'
644 else:
645 value = 'False'
596 boto.config.set('Boto', varname, value) 646 boto.config.set('Boto', varname, value)
597 647
598 def _PromptForProxyConfig(self): 648 def _PromptForProxyConfig(self):
599 """ 649 """Prompts for proxy config data, loads non-empty values into boto.config.
600 Prompts user for proxy configuration data, and loads non-empty values into
601 boto.config.
602 """ 650 """
603 self._PromptForProxyConfigVarAndMaybeSaveToBotoConfig( 651 self._PromptForProxyConfigVarAndMaybeSaveToBotoConfig(
604 'proxy', 'What is your proxy host? ') 652 'proxy', 'What is your proxy host? ')
605 self._PromptForProxyConfigVarAndMaybeSaveToBotoConfig( 653 self._PromptForProxyConfigVarAndMaybeSaveToBotoConfig(
606 'proxy_port', 'What is your proxy port? ') 654 'proxy_port', 'What is your proxy port? ')
607 self._PromptForProxyConfigVarAndMaybeSaveToBotoConfig( 655 self._PromptForProxyConfigVarAndMaybeSaveToBotoConfig(
608 'proxy_user', 'What is your proxy user (leave blank if not used)? ') 656 'proxy_user', 'What is your proxy user (leave blank if not used)? ')
609 self._PromptForProxyConfigVarAndMaybeSaveToBotoConfig( 657 self._PromptForProxyConfigVarAndMaybeSaveToBotoConfig(
610 'proxy_pass', 'What is your proxy pass (leave blank if not used)? ') 658 'proxy_pass', 'What is your proxy pass (leave blank if not used)? ')
659 self._PromptForProxyConfigVarAndMaybeSaveToBotoConfig(
660 'proxy_rdns',
661 'Should DNS lookups be resolved by your proxy? (Y if your site '
662 'disallows client DNS lookups)? ',
663 convert_to_bool=True)
611 664
612 def _WriteConfigLineMaybeCommented(self, config_file, name, value, desc): 665 def _WriteConfigLineMaybeCommented(self, config_file, name, value, desc):
613 """Writes proxy name/value pair to config file if value is not None, else 666 """Writes proxy name/value pair or comment line to config file.
614 writes comment line. 667
668 Writes proxy name/value pair if value is not None. Otherwise writes
669 comment line.
615 670
616 Args: 671 Args:
672 config_file: File object to which the resulting config file will be
673 written.
617 name: The config variable name. 674 name: The config variable name.
618 value: The value, or None. 675 value: The value, or None.
619 desc: Human readable description (for comment). 676 desc: Human readable description (for comment).
620 config_file: File object to which the resulting config file will be
621 written.
622 """ 677 """
623 if not value: 678 if not value:
624 name = '#%s' % name 679 name = '#%s' % name
625 value = '<%s>' % desc 680 value = '<%s>' % desc
626 config_file.write('%s = %s\n' % (name, value)) 681 config_file.write('%s = %s\n' % (name, value))
627 682
628 def _WriteProxyConfigFileSection(self, config_file): 683 def _WriteProxyConfigFileSection(self, config_file):
629 """Writes proxy section of configuration file. 684 """Writes proxy section of configuration file.
630 685
631 Args: 686 Args:
632 config_file: File object to which the resulting config file will be 687 config_file: File object to which the resulting config file will be
633 written. 688 written.
634 """ 689 """
635 config = boto.config 690 config = boto.config
636 config_file.write( 691 config_file.write(
637 """# To use a proxy, edit and uncomment the proxy and proxy_port lines. If you 692 '# To use a proxy, edit and uncomment the proxy and proxy_port lines.\n'
638 # need a user/password with this proxy, edit and uncomment those lines as well. 693 '# If you need a user/password with this proxy, edit and uncomment\n'
639 """) 694 '# those lines as well. If your organization also disallows DNS\n'
695 '# lookups by client machines set proxy_rdns = True\n')
640 self._WriteConfigLineMaybeCommented( 696 self._WriteConfigLineMaybeCommented(
641 config_file, 'proxy', config.get_value('Boto', 'proxy', None), 697 config_file, 'proxy', config.get_value('Boto', 'proxy', None),
642 'proxy host') 698 'proxy host')
643 self._WriteConfigLineMaybeCommented( 699 self._WriteConfigLineMaybeCommented(
644 config_file, 'proxy_port', config.get_value('Boto', 'proxy_port', None), 700 config_file, 'proxy_port', config.get_value('Boto', 'proxy_port', None),
645 'proxy port') 701 'proxy port')
646 self._WriteConfigLineMaybeCommented( 702 self._WriteConfigLineMaybeCommented(
647 config_file, 'proxy_user', config.get_value('Boto', 'proxy_user', None), 703 config_file, 'proxy_user', config.get_value('Boto', 'proxy_user', None),
648 'proxy user') 704 'proxy user')
649 self._WriteConfigLineMaybeCommented( 705 self._WriteConfigLineMaybeCommented(
650 config_file, 'proxy_pass', config.get_value('Boto', 'proxy_pass', None), 706 config_file, 'proxy_pass', config.get_value('Boto', 'proxy_pass', None),
651 'proxy password') 707 'proxy password')
708 self._WriteConfigLineMaybeCommented(
709 config_file, 'proxy_rdns',
710 config.get_value('Boto', 'proxy_rdns', False),
711 'let proxy server perform DNS lookups')
652 712
713 # pylint: disable=dangerous-default-value,too-many-statements
653 def _WriteBotoConfigFile(self, config_file, launch_browser=True, 714 def _WriteBotoConfigFile(self, config_file, launch_browser=True,
654 oauth2_scopes=[SCOPE_FULL_CONTROL], 715 oauth2_scopes=[SCOPE_FULL_CONTROL],
655 cred_type=CredTypes.OAUTH2_USER_ACCOUNT): 716 cred_type=CredTypes.OAUTH2_USER_ACCOUNT):
656 """Creates a boto config file interactively. 717 """Creates a boto config file interactively.
657 718
658 Needed credentials are obtained interactively, either by asking the user for 719 Needed credentials are obtained interactively, either by asking the user for
659 access key and secret, or by walking the user through the OAuth2 approval 720 access key and secret, or by walking the user through the OAuth2 approval
660 flow. 721 flow.
661 722
662 Args: 723 Args:
663 config_file: File object to which the resulting config file will be 724 config_file: File object to which the resulting config file will be
664 written. 725 written.
726 launch_browser: In the OAuth2 approval flow, attempt to open a browser
727 window and navigate to the approval URL.
728 oauth2_scopes: A list of OAuth2 scopes to request authorization for, when
729 using OAuth2.
665 cred_type: There are three options: 730 cred_type: There are three options:
666 - for HMAC, ask the user for access key and secret 731 - for HMAC, ask the user for access key and secret
667 - for OAUTH2_USER_ACCOUNT, walk the user through OAuth2 approval flow 732 - for OAUTH2_USER_ACCOUNT, walk the user through OAuth2 approval flow
668 and produce a config with an oauth2_refresh_token credential. 733 and produce a config with an oauth2_refresh_token credential.
669 - for OAUTH2_SERVICE_ACCOUNT, prompt the user for OAuth2 for client ID, 734 - for OAUTH2_SERVICE_ACCOUNT, prompt the user for OAuth2 for service
670 and private key file (and password for the file) 735 account email address and private key file (and password for that
671 launch_browser: In the OAuth2 approval flow, attempt to open a browser 736 file).
672 window and navigate to the approval URL.
673 oauth2_scopes: A list of OAuth2 scopes to request authorization for, when
674 using OAuth2.
675 """ 737 """
676 # Collect credentials 738 # Collect credentials
677 provider_map = {'aws': 'aws', 'google': 'gs'} 739 provider_map = {'aws': 'aws', 'google': 'gs'}
678 uri_map = {'aws': 's3', 'google': 'gs'} 740 uri_map = {'aws': 's3', 'google': 'gs'}
679 key_ids = {} 741 key_ids = {}
680 sec_keys = {} 742 sec_keys = {}
681 if cred_type == CredTypes.OAUTH2_SERVICE_ACCOUNT: 743 if cred_type == CredTypes.OAUTH2_SERVICE_ACCOUNT:
682 gs_service_client_id = raw_input('What is your service account email ' 744 gs_service_client_id = raw_input('What is your service account email '
683 'address? ') 745 'address? ')
684 gs_service_key_file = raw_input('What is the full path to your private ' 746 gs_service_key_file = raw_input('What is the full path to your private '
685 'key file? ') 747 'key file? ')
686 gs_service_key_file_password = raw_input( 748 gs_service_key_file_password = raw_input(
687 '\n'.join(textwrap.wrap( 749 '\n'.join(textwrap.wrap(
688 "What is the password for your service key file? If you haven't " 750 'What is the password for your service key file [if you haven\'t '
689 " set one explicitly, leave this line blank. "))) 751 'set one explicitly, leave this line blank]?')) + ' ')
690 self._CheckPrivateKeyFilePermissions(gs_service_key_file) 752 self._CheckPrivateKeyFilePermissions(gs_service_key_file)
691 elif cred_type == CredTypes.OAUTH2_USER_ACCOUNT: 753 elif cred_type == CredTypes.OAUTH2_USER_ACCOUNT:
692 oauth2_client = oauth2_helper.OAuth2ClientFromBotoConfig(boto.config, 754 oauth2_client = oauth2_helper.OAuth2ClientFromBotoConfig(boto.config,
693 cred_type) 755 cred_type)
694 try: 756 try:
695 oauth2_refresh_token = oauth2_helper.OAuth2ApprovalFlow( 757 oauth2_refresh_token = oauth2_helper.OAuth2ApprovalFlow(
696 oauth2_client, oauth2_scopes, launch_browser) 758 oauth2_client, oauth2_scopes, launch_browser)
697 except (ResponseNotReady, ServerNotFoundError) as e: 759 except (ResponseNotReady, ServerNotFoundError, socket.error):
698 # TODO: Determine condition to check for in the ResponseNotReady 760 # TODO: Determine condition to check for in the ResponseNotReady
699 # exception so we only run proxy config flow if failure was caused by 761 # exception so we only run proxy config flow if failure was caused by
700 # request being blocked because it wasn't sent through proxy. (This 762 # request being blocked because it wasn't sent through proxy. (This
701 # error could also happen if gsutil or the oauth2 client had a bug that 763 # error could also happen if gsutil or the oauth2 client had a bug that
702 # attempted to incorrectly reuse an HTTP connection, for example.) 764 # attempted to incorrectly reuse an HTTP connection, for example.)
703 sys.stdout.write('\n'.join(textwrap.wrap( 765 sys.stdout.write('\n'.join(textwrap.wrap(
704 "Unable to connect to accounts.google.com during OAuth2 flow. This " 766 "Unable to connect to accounts.google.com during OAuth2 flow. This "
705 "can happen if your site uses a proxy. If you are using gsutil " 767 "can happen if your site uses a proxy. If you are using gsutil "
706 "through a proxy, please enter the proxy's information; otherwise " 768 "through a proxy, please enter the proxy's information; otherwise "
707 "leave the following fields blank.")) + '\n') 769 "leave the following fields blank.")) + '\n')
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
786 '# To add %s credentials ("%s://" URIs), edit and ' 848 '# To add %s credentials ("%s://" URIs), edit and '
787 'uncomment the\n# following two lines:\n' 849 'uncomment the\n# following two lines:\n'
788 '#%s_access_key_id = <your %s access key ID>\n' 850 '#%s_access_key_id = <your %s access key ID>\n'
789 '#%s_secret_access_key = <your %s secret access key>\n' % 851 '#%s_secret_access_key = <your %s secret access key>\n' %
790 (provider, uri_scheme, key_prefix, provider, key_prefix, 852 (provider, uri_scheme, key_prefix, provider, key_prefix,
791 provider)) 853 provider))
792 host_key = Provider.HostKeyMap[provider] 854 host_key = Provider.HostKeyMap[provider]
793 config_file.write( 855 config_file.write(
794 '# The ability to specify an alternate storage host and port\n' 856 '# The ability to specify an alternate storage host and port\n'
795 '# is primarily for cloud storage service developers.\n' 857 '# is primarily for cloud storage service developers.\n'
858 '# Setting a non-default gs_host only works if prefer_api=xml.\n'
796 '#%s_host = <alternate storage host address>\n' 859 '#%s_host = <alternate storage host address>\n'
797 '#%s_port = <alternate storage host port>\n\n' 860 '#%s_port = <alternate storage host port>\n'
798 % (host_key, host_key)) 861 % (host_key, host_key))
862 if host_key == 'gs':
863 config_file.write(
864 '#%s_json_host = <alternate JSON API storage host address>\n'
865 '#%s_json_port = <alternate JSON API storage host port>\n\n'
866 % (host_key, host_key))
867 config_file.write('\n')
799 868
800 # Write the config file Boto section. 869 # Write the config file Boto section.
801 config_file.write('%s\n' % CONFIG_BOTO_SECTION_CONTENT) 870 config_file.write('%s\n' % CONFIG_BOTO_SECTION_CONTENT)
802 self._WriteProxyConfigFileSection(config_file) 871 self._WriteProxyConfigFileSection(config_file)
803 872
804 # Write the config file GSUtil section that doesn't depend on user input. 873 # Write the config file GSUtil section that doesn't depend on user input.
805 config_file.write(CONFIG_INPUTLESS_GSUTIL_SECTION_CONTENT) 874 config_file.write(CONFIG_INPUTLESS_GSUTIL_SECTION_CONTENT)
806 875
807 # Write the default API version. 876 # Write the default API version.
808 config_file.write(""" 877 config_file.write("""
809 # 'default_api_version' specifies the default Google Cloud Storage API 878 # 'default_api_version' specifies the default Google Cloud Storage XML API
810 # version to use. If not set below gsutil defaults to API version 1. 879 # version to use. If not set below gsutil defaults to API version 1.
811 """) 880 """)
812 api_version = 2 881 api_version = 2
813 if cred_type == CredTypes.HMAC: api_version = 1 882 if cred_type == CredTypes.HMAC: api_version = 1
814 883
815 config_file.write('default_api_version = %d\n' % api_version) 884 config_file.write('default_api_version = %d\n' % api_version)
816 885
817 # Write the config file GSUtil section that includes the default 886 # Write the config file GSUtil section that includes the default
818 # project ID input from the user. 887 # project ID input from the user.
819 if launch_browser: 888 if launch_browser:
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
852 if not default_project_id: 921 if not default_project_id:
853 raise CommandException( 922 raise CommandException(
854 'No default project ID entered. The default project ID is needed by ' 923 'No default project ID entered. The default project ID is needed by '
855 'the\nls and mb commands; please try again.') 924 'the\nls and mb commands; please try again.')
856 config_file.write('%sdefault_project_id = %s\n\n\n' % 925 config_file.write('%sdefault_project_id = %s\n\n\n' %
857 (project_id_section_prelude, default_project_id)) 926 (project_id_section_prelude, default_project_id))
858 927
859 # Write the config file OAuth2 section. 928 # Write the config file OAuth2 section.
860 config_file.write(CONFIG_OAUTH2_CONFIG_CONTENT) 929 config_file.write(CONFIG_OAUTH2_CONFIG_CONTENT)
861 930
862 # Command entry point.
863 def RunCommand(self): 931 def RunCommand(self):
932 """Command entry point for the config command."""
864 scopes = [] 933 scopes = []
865 cred_type = CredTypes.OAUTH2_USER_ACCOUNT 934 cred_type = CredTypes.OAUTH2_USER_ACCOUNT
866 launch_browser = False 935 launch_browser = False
867 output_file_name = None 936 output_file_name = None
868 has_a = False 937 has_a = False
869 has_e = False 938 has_e = False
870 for opt, opt_arg in self.sub_opts: 939 for opt, opt_arg in self.sub_opts:
871 if opt == '-a': 940 if opt == '-a':
872 cred_type = CredTypes.HMAC 941 cred_type = CredTypes.HMAC
873 has_a = True 942 has_a = True
(...skipping 20 matching lines...) Expand all
894 if not HAS_CRYPTO: 963 if not HAS_CRYPTO:
895 raise CommandException( 964 raise CommandException(
896 'Service account authentication requires either\nPyOpenSSL or ' 965 'Service account authentication requires either\nPyOpenSSL or '
897 'PyCrypto 2.6 or later. Please install either of these\nto proceed,' 966 'PyCrypto 2.6 or later. Please install either of these\nto proceed,'
898 ' or configure a different type of credentials.') 967 ' or configure a different type of credentials.')
899 968
900 if not scopes: 969 if not scopes:
901 scopes.append(SCOPE_FULL_CONTROL) 970 scopes.append(SCOPE_FULL_CONTROL)
902 971
903 default_config_path_bak = None 972 default_config_path_bak = None
904 if output_file_name is None: 973 if not output_file_name:
905 # Check to see if a default config file name is requested via 974 # Check to see if a default config file name is requested via
906 # environment variable. If so, use it, otherwise use the hard-coded 975 # environment variable. If so, use it, otherwise use the hard-coded
907 # default file. Then use the default config file name, if it doesn't 976 # default file. Then use the default config file name, if it doesn't
908 # exist or can be moved out of the way without clobbering an existing 977 # exist or can be moved out of the way without clobbering an existing
909 # backup file. 978 # backup file.
910 boto_config_from_env = os.environ.get('BOTO_CONFIG', None) 979 boto_config_from_env = os.environ.get('BOTO_CONFIG', None)
911 if boto_config_from_env: 980 if boto_config_from_env:
912 default_config_path = boto_config_from_env 981 default_config_path = boto_config_from_env
913 else: 982 else:
914 default_config_path = os.path.expanduser(os.path.join('~', '.boto')) 983 default_config_path = os.path.expanduser(os.path.join('~', '.boto'))
915 if not os.path.exists(default_config_path): 984 if not os.path.exists(default_config_path):
916 output_file_name = default_config_path 985 output_file_name = default_config_path
917 else: 986 else:
918 default_config_path_bak = default_config_path + '.bak' 987 default_config_path_bak = default_config_path + '.bak'
919 if os.path.exists(default_config_path_bak): 988 if os.path.exists(default_config_path_bak):
920 raise CommandException( 989 raise CommandException(
921 'Cannot back up existing config ' 990 'Cannot back up existing config '
922 'file "%s": backup file exists ("%s").' 991 'file "%s": backup file exists ("%s").'
923 % (default_config_path, default_config_path_bak)) 992 % (default_config_path, default_config_path_bak))
924 else: 993 else:
925 try: 994 try:
926 sys.stderr.write( 995 sys.stderr.write(
927 'Backing up existing config file "%s" to "%s"...\n' 996 'Backing up existing config file "%s" to "%s"...\n'
928 % (default_config_path, default_config_path_bak)) 997 % (default_config_path, default_config_path_bak))
929 os.rename(default_config_path, default_config_path_bak) 998 os.rename(default_config_path, default_config_path_bak)
930 except e: 999 except Exception, e:
931 raise CommandException( 1000 raise CommandException(
932 'Failed to back up existing config ' 1001 'Failed to back up existing config '
933 'file ("%s" -> "%s"): %s.' 1002 'file ("%s" -> "%s"): %s.'
934 % (default_config_path, default_config_path_bak, e)) 1003 % (default_config_path, default_config_path_bak, e))
935 output_file_name = default_config_path 1004 output_file_name = default_config_path
936 1005
937 if output_file_name == '-': 1006 if output_file_name == '-':
938 output_file = sys.stdout 1007 output_file = sys.stdout
939 else: 1008 else:
940 output_file = self._OpenConfigFile(output_file_name) 1009 output_file = self._OpenConfigFile(output_file_name)
941 sys.stderr.write( 1010 sys.stderr.write('\n'.join(textwrap.wrap(
942 'This script will create a boto config file at\n%s\ncontaining your ' 1011 'This command will create a boto config file at %s containing your '
943 'credentials, based on your responses to the following questions.\n\n' 1012 'credentials, based on your responses to the following questions.'
944 % output_file_name) 1013 % output_file_name)) + '\n')
945 1014
946 # Catch ^C so we can restore the backup. 1015 # Catch ^C so we can restore the backup.
947 signal.signal(signal.SIGINT, cleanup_handler) 1016 signal.signal(signal.SIGINT, CleanupHandler)
948 try: 1017 try:
949 self._WriteBotoConfigFile(output_file, launch_browser=launch_browser, 1018 self._WriteBotoConfigFile(output_file, launch_browser=launch_browser,
950 oauth2_scopes=scopes, cred_type=cred_type) 1019 oauth2_scopes=scopes, cred_type=cred_type)
951 except Exception as e: 1020 except Exception as e:
952 user_aborted = isinstance(e, AbortException) 1021 user_aborted = isinstance(e, AbortException)
953 if user_aborted: 1022 if user_aborted:
954 sys.stderr.write('\nCaught ^C; cleaning up\n') 1023 sys.stderr.write('\nCaught ^C; cleaning up\n')
955 # If an error occurred during config file creation, remove the invalid 1024 # If an error occurred during config file creation, remove the invalid
956 # config file and restore the backup file. 1025 # config file and restore the backup file.
957 if output_file_name != '-': 1026 if output_file_name != '-':
(...skipping 15 matching lines...) Expand all
973 output_file.close() 1042 output_file.close()
974 if not boto.config.has_option('Boto', 'proxy'): 1043 if not boto.config.has_option('Boto', 'proxy'):
975 sys.stderr.write('\n' + '\n'.join(textwrap.wrap( 1044 sys.stderr.write('\n' + '\n'.join(textwrap.wrap(
976 'Boto config file "%s" created.\nIf you need to use a proxy to ' 1045 'Boto config file "%s" created.\nIf you need to use a proxy to '
977 'access the Internet please see the instructions in that file.' 1046 'access the Internet please see the instructions in that file.'
978 % output_file_name)) + '\n') 1047 % output_file_name)) + '\n')
979 1048
980 return 0 1049 return 0
981 1050
982 1051
983 def cleanup_handler(signalnum, handler): 1052 def CleanupHandler(unused_signalnum, unused_handler):
984 raise AbortException('User interrupted config command') 1053 raise AbortException('User interrupted config command')
OLDNEW
« no previous file with comments | « gslib/commands/compose.py ('k') | gslib/commands/cors.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698