gcloud 0.0.2 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +2 -3
- data/CHANGELOG +4 -0
- data/LICENSE +674 -0
- data/Manifest +111 -0
- data/README.md +4 -3
- data/bin/gcutil +53 -0
- data/gcloud.gemspec +4 -3
- data/packages/gcutil-1.7.1/CHANGELOG +197 -0
- data/packages/gcutil-1.7.1/LICENSE +202 -0
- data/packages/gcutil-1.7.1/VERSION +1 -0
- data/packages/gcutil-1.7.1/gcutil +53 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/LICENSE +23 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/__init__.py +1 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/discovery.py +743 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/errors.py +123 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/ext/__init__.py +0 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/http.py +1443 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/mimeparse.py +172 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/model.py +385 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/schema.py +303 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/__init__.py +1 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/anyjson.py +32 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/appengine.py +528 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/client.py +1139 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/clientsecrets.py +105 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/crypt.py +244 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/django_orm.py +124 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/file.py +107 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/locked_file.py +343 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/multistore_file.py +379 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/tools.py +174 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/uritemplate/__init__.py +147 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/LICENSE +202 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/__init__.py +3 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/__init__.py +3 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/app.py +356 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/appcommands.py +783 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/basetest.py +1260 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/datelib.py +421 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/debug.py +60 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/file_util.py +181 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/resources.py +67 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/run_script_module.py +217 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/setup_command.py +159 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/shellutil.py +49 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/stopwatch.py +204 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/__init__.py +0 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auth_helper.py +140 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auth_helper_test.py +149 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auto_auth.py +130 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auto_auth_test.py +75 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/basic_cmds.py +128 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/basic_cmds_test.py +111 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/command_base.py +1808 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/command_base_test.py +1651 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/compute/v1beta13.json +2851 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/compute/v1beta14.json +3361 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/disk_cmds.py +342 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/disk_cmds_test.py +474 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/firewall_cmds.py +344 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/firewall_cmds_test.py +231 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/flags_cache.py +274 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/gcutil +89 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/gcutil_logging.py +69 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/image_cmds.py +262 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/image_cmds_test.py +172 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/instance_cmds.py +1506 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/instance_cmds_test.py +1904 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/kernel_cmds.py +91 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/kernel_cmds_test.py +56 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/machine_type_cmds.py +106 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/machine_type_cmds_test.py +59 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/metadata.py +96 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/metadata_lib.py +357 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/metadata_test.py +84 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/mock_api.py +420 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/mock_metadata.py +58 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/move_cmds.py +824 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/move_cmds_test.py +307 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/network_cmds.py +178 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/network_cmds_test.py +133 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/operation_cmds.py +181 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/operation_cmds_test.py +196 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/path_initializer.py +38 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/project_cmds.py +173 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/project_cmds_test.py +111 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/scopes.py +61 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/scopes_test.py +50 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/snapshot_cmds.py +276 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/snapshot_cmds_test.py +260 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/ssh_keys.py +266 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/ssh_keys_test.py +128 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/table_formatter.py +563 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/thread_pool.py +188 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/thread_pool_test.py +88 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/utils.py +208 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/utils_test.py +193 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/version.py +17 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/version_checker.py +246 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/version_checker_test.py +271 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/zone_cmds.py +151 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/zone_cmds_test.py +60 -0
- data/packages/gcutil-1.7.1/lib/httplib2/LICENSE +21 -0
- data/packages/gcutil-1.7.1/lib/httplib2/httplib2/__init__.py +1630 -0
- data/packages/gcutil-1.7.1/lib/httplib2/httplib2/cacerts.txt +714 -0
- data/packages/gcutil-1.7.1/lib/httplib2/httplib2/iri2uri.py +110 -0
- data/packages/gcutil-1.7.1/lib/httplib2/httplib2/socks.py +438 -0
- data/packages/gcutil-1.7.1/lib/iso8601/LICENSE +20 -0
- data/packages/gcutil-1.7.1/lib/iso8601/iso8601/__init__.py +1 -0
- data/packages/gcutil-1.7.1/lib/iso8601/iso8601/iso8601.py +102 -0
- data/packages/gcutil-1.7.1/lib/iso8601/iso8601/test_iso8601.py +111 -0
- data/packages/gcutil-1.7.1/lib/python_gflags/AUTHORS +2 -0
- data/packages/gcutil-1.7.1/lib/python_gflags/LICENSE +28 -0
- data/packages/gcutil-1.7.1/lib/python_gflags/gflags.py +2862 -0
- data/packages/gcutil-1.7.1/lib/python_gflags/gflags2man.py +544 -0
- data/packages/gcutil-1.7.1/lib/python_gflags/gflags_validators.py +187 -0
- metadata +118 -5
- metadata.gz.sig +0 -0
@@ -0,0 +1,159 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# Copyright 2010 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
|
+
|
16
|
+
"""Setuptools extension for running Google-style Python tests.
|
17
|
+
|
18
|
+
Google-style Python tests differ from normal Python tests in that each test
|
19
|
+
module is intended to be executed as an independent script. In particular, the
|
20
|
+
test fixture code in basetest.main() that executes module-wide setUp() and
|
21
|
+
tearDown() depends on __main__ being the module under test. This conflicts with
|
22
|
+
the usual setuptools test style, which uses a single TestSuite to run all of a
|
23
|
+
package's tests.
|
24
|
+
|
25
|
+
This package provides a new setuptools command, google_test, that runs all of
|
26
|
+
the google-style tests found in a specified directory.
|
27
|
+
|
28
|
+
NOTE: This works by overriding sys.modules['__main__'] with the module under
|
29
|
+
test, but still runs tests in the same process. Thus it will *not* work if your
|
30
|
+
tests depend on any of the following:
|
31
|
+
- Per-process (as opposed to per-module) initialization.
|
32
|
+
- Any entry point that is not basetest.main().
|
33
|
+
|
34
|
+
To use the google_test command in your project, do something like the following:
|
35
|
+
|
36
|
+
In setup.py:
|
37
|
+
setup(
|
38
|
+
name = "mypackage",
|
39
|
+
...
|
40
|
+
setup_requires = ["google-apputils>=0.2"],
|
41
|
+
google_test_dir = "tests",
|
42
|
+
)
|
43
|
+
|
44
|
+
Run:
|
45
|
+
$ python setup.py google_test
|
46
|
+
"""
|
47
|
+
|
48
|
+
from distutils import errors
|
49
|
+
import imp
|
50
|
+
import os
|
51
|
+
import re
|
52
|
+
import shlex
|
53
|
+
import sys
|
54
|
+
import traceback
|
55
|
+
|
56
|
+
from setuptools.command import test
|
57
|
+
|
58
|
+
|
59
|
+
def ValidateGoogleTestDir(unused_dist, unused_attr, value):
|
60
|
+
"""Validate that the test directory is a directory."""
|
61
|
+
if not os.path.isdir(value):
|
62
|
+
raise errors.DistutilsSetupError('%s is not a directory' % value)
|
63
|
+
|
64
|
+
|
65
|
+
class GoogleTest(test.test):
|
66
|
+
"""Command to run Google-style tests after in-place build."""
|
67
|
+
|
68
|
+
description = 'run Google-style tests after in-place build'
|
69
|
+
|
70
|
+
_DEFAULT_PATTERN = r'_(?:unit|reg)?test\.py$'
|
71
|
+
|
72
|
+
user_options = [
|
73
|
+
('test-dir=', 'd', 'Look for test modules in specified directory.'),
|
74
|
+
('test-module-pattern=', 'p',
|
75
|
+
('Pattern for matching test modules. Defaults to %r. '
|
76
|
+
'Only source files (*.py) will be considered, even if more files match '
|
77
|
+
'this pattern.' % _DEFAULT_PATTERN)),
|
78
|
+
('test-args=', 'a',
|
79
|
+
('Arguments to pass to basetest.main(). May only make sense if '
|
80
|
+
'test_module_pattern matches exactly one test.')),
|
81
|
+
]
|
82
|
+
|
83
|
+
def initialize_options(self):
|
84
|
+
self.test_dir = None
|
85
|
+
self.test_module_pattern = self._DEFAULT_PATTERN
|
86
|
+
self.test_args = ''
|
87
|
+
|
88
|
+
# Set to a dummy value, since we don't call the superclass methods for
|
89
|
+
# options parsing.
|
90
|
+
self.test_suite = True
|
91
|
+
|
92
|
+
def finalize_options(self):
|
93
|
+
if self.test_dir is None:
|
94
|
+
if self.distribution.google_test_dir:
|
95
|
+
self.test_dir = self.distribution.google_test_dir
|
96
|
+
else:
|
97
|
+
raise errors.DistutilsOptionError('No test directory specified')
|
98
|
+
|
99
|
+
self.test_module_pattern = re.compile(self.test_module_pattern)
|
100
|
+
self.test_args = shlex.split(self.test_args)
|
101
|
+
|
102
|
+
def _RunTestModule(self, module_path):
|
103
|
+
"""Run a module as a test module given its path.
|
104
|
+
|
105
|
+
Args:
|
106
|
+
module_path: The path to the module to test; must end in '.py'.
|
107
|
+
|
108
|
+
Returns:
|
109
|
+
True if the tests in this module pass, False if not or if an error occurs.
|
110
|
+
"""
|
111
|
+
|
112
|
+
path, filename = os.path.split(module_path)
|
113
|
+
|
114
|
+
old_argv = sys.argv[:]
|
115
|
+
old_path = sys.path[:]
|
116
|
+
old_modules = sys.modules.copy()
|
117
|
+
|
118
|
+
# Make relative imports in test modules work with our mangled sys.path.
|
119
|
+
sys.path.insert(0, path)
|
120
|
+
|
121
|
+
module_name = filename.replace('.py', '')
|
122
|
+
import_tuple = imp.find_module(module_name, [path])
|
123
|
+
module = imp.load_module(module_name, *import_tuple)
|
124
|
+
|
125
|
+
sys.modules['__main__'] = module
|
126
|
+
sys.argv = [module.__file__] + self.test_args
|
127
|
+
|
128
|
+
# Late import since this must be run with the project's sys.path.
|
129
|
+
import basetest
|
130
|
+
try:
|
131
|
+
try:
|
132
|
+
sys.stderr.write('Testing %s\n' % module_name)
|
133
|
+
basetest.main()
|
134
|
+
|
135
|
+
# basetest.main() should always call sys.exit, so this is very bad.
|
136
|
+
return False
|
137
|
+
except SystemExit, e:
|
138
|
+
returncode, = e.args
|
139
|
+
return not returncode
|
140
|
+
except:
|
141
|
+
traceback.print_exc()
|
142
|
+
return False
|
143
|
+
finally:
|
144
|
+
sys.argv[:] = old_argv
|
145
|
+
sys.path[:] = old_path
|
146
|
+
sys.modules.clear()
|
147
|
+
sys.modules.update(old_modules)
|
148
|
+
|
149
|
+
def run_tests(self):
|
150
|
+
ok = True
|
151
|
+
for path, _, filenames in os.walk(self.test_dir):
|
152
|
+
for filename in filenames:
|
153
|
+
if not filename.endswith('.py'):
|
154
|
+
continue
|
155
|
+
file_path = os.path.join(path, filename)
|
156
|
+
if self.test_module_pattern.search(file_path):
|
157
|
+
ok &= self._RunTestModule(file_path)
|
158
|
+
|
159
|
+
sys.exit(int(not ok))
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
#
|
3
|
+
# Copyright 2003 Google Inc. All Rights Reserved.
|
4
|
+
|
5
|
+
"""Utility functions for dealing with command interpreters."""
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
import os
|
10
|
+
|
11
|
+
# Running windows?
|
12
|
+
win32 = (os.name == 'nt')
|
13
|
+
|
14
|
+
|
15
|
+
def ShellEscapeList(words):
|
16
|
+
"""Turn a list of words into a shell-safe string.
|
17
|
+
|
18
|
+
Args:
|
19
|
+
words: A list of words, e.g. for a command.
|
20
|
+
|
21
|
+
Returns:
|
22
|
+
A string of shell-quoted and space-separated words.
|
23
|
+
"""
|
24
|
+
|
25
|
+
if win32:
|
26
|
+
return ' '.join(words)
|
27
|
+
|
28
|
+
s = ''
|
29
|
+
for word in words:
|
30
|
+
# Single quote word, and replace each ' in word with '"'"'
|
31
|
+
s += "'" + word.replace("'", "'\"'\"'") + "' "
|
32
|
+
|
33
|
+
return s[:-1]
|
34
|
+
|
35
|
+
|
36
|
+
def ShellifyStatus(status):
|
37
|
+
"""Translate from a wait() exit status to a command shell exit status."""
|
38
|
+
|
39
|
+
if not win32:
|
40
|
+
if os.WIFEXITED(status):
|
41
|
+
# decode and return exit status
|
42
|
+
status = os.WEXITSTATUS(status)
|
43
|
+
else:
|
44
|
+
# On Unix, the wait() produces a 16 bit return code. Unix shells
|
45
|
+
# lossily compress this to an 8 bit value, using the formula below.
|
46
|
+
# Shell status code < 128 means the process exited normally, status
|
47
|
+
# code >= 128 means the process died because of a signal.
|
48
|
+
status = 128 + os.WTERMSIG(status)
|
49
|
+
return status
|
@@ -0,0 +1,204 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# Copyright 2005 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
|
+
|
16
|
+
"""A useful class for digesting, on a high-level, where time in a program goes.
|
17
|
+
|
18
|
+
Usage:
|
19
|
+
|
20
|
+
sw = StopWatch()
|
21
|
+
sw.start()
|
22
|
+
sw.start('foo')
|
23
|
+
foo()
|
24
|
+
sw.stop('foo')
|
25
|
+
args = overhead_code()
|
26
|
+
sw.start('bar')
|
27
|
+
bar(args)
|
28
|
+
sw.stop('bar')
|
29
|
+
sw.dump()
|
30
|
+
|
31
|
+
If you start a new timer when one is already running, then the other one will
|
32
|
+
stop running, and restart when you stop this timer. This behavior is very
|
33
|
+
useful for when you want to try timing for a subcall without remembering
|
34
|
+
what is already running. For instance:
|
35
|
+
|
36
|
+
sw.start('all_this')
|
37
|
+
do_some_stuff()
|
38
|
+
sw.start('just_that')
|
39
|
+
small_but_expensive_function()
|
40
|
+
sw.stop('just_that')
|
41
|
+
cleanup_code()
|
42
|
+
sw.stop('all_this')
|
43
|
+
|
44
|
+
In this case, the output will be what you want: the time spent in
|
45
|
+
small_but_expensive function will show up in the timer for just_that and not
|
46
|
+
all_this.
|
47
|
+
"""
|
48
|
+
|
49
|
+
import StringIO
|
50
|
+
import time
|
51
|
+
|
52
|
+
|
53
|
+
__owner__ = 'dbentley@google.com (Dan Bentley)'
|
54
|
+
|
55
|
+
|
56
|
+
class StopWatch(object):
|
57
|
+
"""Class encapsulating a timer; see above for example usage.
|
58
|
+
|
59
|
+
Instance variables:
|
60
|
+
timers: map of stopwatch name -> time for each currently running stopwatch,
|
61
|
+
where time is seconds from the epoch of when this stopwatch was
|
62
|
+
started.
|
63
|
+
accum: map of stopwatch name -> accumulated time, in seconds, it has
|
64
|
+
already been run for.
|
65
|
+
stopped: map of timer name -> list of timer names that are blocking it.
|
66
|
+
counters: map of timer name -> number of times it has been started.
|
67
|
+
"""
|
68
|
+
|
69
|
+
def __init__(self):
|
70
|
+
self.timers = {}
|
71
|
+
self.accum = {}
|
72
|
+
self.stopped = {}
|
73
|
+
self.counters = {}
|
74
|
+
|
75
|
+
def start(self, timer='total', stop_others=True):
|
76
|
+
"""Start a timer.
|
77
|
+
|
78
|
+
Args:
|
79
|
+
timer: str; name of the timer to start, defaults to the overall timer.
|
80
|
+
stop_others: bool; if True, stop all other running timers. If False, then
|
81
|
+
you can have time that is spent inside more than one timer
|
82
|
+
and there's a good chance that the overhead measured will be
|
83
|
+
negative.
|
84
|
+
"""
|
85
|
+
if stop_others:
|
86
|
+
stopped = []
|
87
|
+
for other in list(self.timers):
|
88
|
+
if not other == 'total':
|
89
|
+
self.stop(other)
|
90
|
+
stopped.append(other)
|
91
|
+
self.stopped[timer] = stopped
|
92
|
+
self.counters[timer] = self.counters.get(timer, 0) + 1
|
93
|
+
self.timers[timer] = time.time()
|
94
|
+
|
95
|
+
def stop(self, timer='total'):
|
96
|
+
"""Stop a running timer.
|
97
|
+
|
98
|
+
This includes restarting anything that was stopped on behalf of this timer.
|
99
|
+
|
100
|
+
Args:
|
101
|
+
timer: str; name of the timer to stop, defaults to the overall timer.
|
102
|
+
|
103
|
+
Raises:
|
104
|
+
RuntimeError: if timer refers to a timer that was never started.
|
105
|
+
"""
|
106
|
+
if timer not in self.timers:
|
107
|
+
raise RuntimeError(
|
108
|
+
'Tried to stop timer that was never started: %s' % timer)
|
109
|
+
self.accum[timer] = self.timervalue(timer)
|
110
|
+
del self.timers[timer]
|
111
|
+
for stopped in self.stopped.get(timer, []):
|
112
|
+
self.start(stopped, stop_others=0)
|
113
|
+
|
114
|
+
def timervalue(self, timer='total', now=None):
|
115
|
+
"""Return the value seen by this timer so far.
|
116
|
+
|
117
|
+
If the timer is stopped, this will be the accumulated time it has seen.
|
118
|
+
If the timer is running, this will be the time it has seen up to now.
|
119
|
+
If the timer has never been started, this will be zero.
|
120
|
+
|
121
|
+
Args:
|
122
|
+
timer: str; the name of the timer to report on.
|
123
|
+
now: long; if provided, the time to use for 'now' for running timers.
|
124
|
+
"""
|
125
|
+
if not now:
|
126
|
+
now = time.time()
|
127
|
+
|
128
|
+
if timer in self.timers:
|
129
|
+
# Timer is running now.
|
130
|
+
return self.accum.get(timer, 0.0) + (now - self.timers[timer])
|
131
|
+
elif timer in self.accum:
|
132
|
+
# Timer is stopped.
|
133
|
+
return self.accum[timer]
|
134
|
+
else:
|
135
|
+
# Timer is never started.
|
136
|
+
return 0.0
|
137
|
+
|
138
|
+
def overhead(self, now=None):
|
139
|
+
"""Calculate the overhead.
|
140
|
+
|
141
|
+
Args:
|
142
|
+
now: (optional) time to use as the current time.
|
143
|
+
|
144
|
+
Returns:
|
145
|
+
The overhead, that is, time spent in total but not in any sub timer. This
|
146
|
+
may be negative if time was counted in two sub timers. Avoid this by
|
147
|
+
always using stop_others.
|
148
|
+
"""
|
149
|
+
total = self.timervalue('total', now)
|
150
|
+
if total == 0.0:
|
151
|
+
return 0.0
|
152
|
+
|
153
|
+
all_timers = sum(self.accum.itervalues())
|
154
|
+
return total - (all_timers - total)
|
155
|
+
|
156
|
+
def results(self, verbose=False):
|
157
|
+
"""Get the results of this stopwatch.
|
158
|
+
|
159
|
+
Args:
|
160
|
+
verbose: bool; if True, show all times; otherwise, show only the total.
|
161
|
+
|
162
|
+
Returns:
|
163
|
+
A list of tuples showing the output of this stopwatch, of the form
|
164
|
+
(name, value, num_starts) for each timer. Note that if the total timer
|
165
|
+
is not used, non-verbose results will be the empty list.
|
166
|
+
"""
|
167
|
+
now = time.time()
|
168
|
+
|
169
|
+
all_names = self.accum.keys()
|
170
|
+
names = []
|
171
|
+
|
172
|
+
if 'total' in all_names:
|
173
|
+
all_names.remove('total')
|
174
|
+
all_names.sort()
|
175
|
+
if verbose:
|
176
|
+
names = all_names
|
177
|
+
|
178
|
+
results = [(name, self.timervalue(name, now=now), self.counters[name])
|
179
|
+
for name in names]
|
180
|
+
if verbose:
|
181
|
+
results.append(('overhead', self.overhead(now=now), 1))
|
182
|
+
if 'total' in self.accum or 'total' in self.timers:
|
183
|
+
results.append(('total', self.timervalue('total', now=now),
|
184
|
+
self.counters['total']))
|
185
|
+
return results
|
186
|
+
|
187
|
+
def dump(self, verbose=False):
|
188
|
+
"""Describes where time in this stopwatch was spent.
|
189
|
+
|
190
|
+
Args:
|
191
|
+
verbose: bool; if True, show all timers; otherwise, show only the total.
|
192
|
+
|
193
|
+
Returns:
|
194
|
+
A string describing the stopwatch.
|
195
|
+
"""
|
196
|
+
output = StringIO.StringIO()
|
197
|
+
results = self.results(verbose=verbose)
|
198
|
+
maxlength = max([len(result[0]) for result in results])
|
199
|
+
for result in results:
|
200
|
+
output.write('%*s: %6.2fs\n' % (maxlength, result[0], result[1]))
|
201
|
+
return output.getvalue()
|
202
|
+
|
203
|
+
# Create a stopwatch to be publicly used.
|
204
|
+
sw = StopWatch()
|
File without changes
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# Copyright 2012 Google Inc. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
"""Google Compute Engine specific helpers to use the common auth library."""
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
import os
|
20
|
+
|
21
|
+
import oauth2client.client as oauth2_client
|
22
|
+
import oauth2client.multistore_file as oauth2_multistore_file
|
23
|
+
import oauth2client.tools as oauth2_tools
|
24
|
+
|
25
|
+
import gflags as flags
|
26
|
+
|
27
|
+
from gcutil import auto_auth
|
28
|
+
from gcutil import metadata_lib
|
29
|
+
|
30
|
+
FLAGS = flags.FLAGS
|
31
|
+
|
32
|
+
# These identifieres are required as part of the OAuth2 spec but have
|
33
|
+
# limited utility with a command line tool. Note that the secret
|
34
|
+
# isn't really secret here. These are copied from the Identity tab on
|
35
|
+
# the Google APIs Console <http://code.google.com/apis/console>
|
36
|
+
OAUTH2_CLIENT_ID = '1025389682001.apps.googleusercontent.com'
|
37
|
+
OAUTH2_CLIENT_SECRET = 'xslsVXhA7C8aOfSfb6edB6p6'
|
38
|
+
USER_AGENT = 'google-compute-cmdline/1.0'
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
flags.DEFINE_string(
|
43
|
+
'credentials_file',
|
44
|
+
'~/.gcutil_auth',
|
45
|
+
'File where user authorization credentials are stored.')
|
46
|
+
|
47
|
+
flags.DEFINE_string(
|
48
|
+
'auth_service_account',
|
49
|
+
'default',
|
50
|
+
'Service account to use for automatic authorization. '
|
51
|
+
'Empty string disables automatic authorization.')
|
52
|
+
|
53
|
+
flags.DEFINE_string(
|
54
|
+
'authorization_uri_base',
|
55
|
+
'https://accounts.google.com/o/oauth2',
|
56
|
+
'The base URI for authorization requests')
|
57
|
+
|
58
|
+
|
59
|
+
def GetCredentialFromStore(scopes,
|
60
|
+
ask_user=True,
|
61
|
+
force_reauth=False,
|
62
|
+
credentials_file=None,
|
63
|
+
authorization_uri_base=None,
|
64
|
+
client_id=OAUTH2_CLIENT_ID,
|
65
|
+
client_secret=OAUTH2_CLIENT_SECRET,
|
66
|
+
user_agent=USER_AGENT,
|
67
|
+
metadata=metadata_lib.Metadata(),
|
68
|
+
logger=None):
|
69
|
+
"""Get OAuth2 credentials for a specific scope.
|
70
|
+
|
71
|
+
Args:
|
72
|
+
scopes: A list of OAuth2 scopes to request.
|
73
|
+
ask_user: If True, prompt the user to authenticate.
|
74
|
+
force_reauth: If True, force users to reauth
|
75
|
+
credentials_file: The file to use to get/store credentials. If left at None
|
76
|
+
FLAGS.credentials_file will be used.
|
77
|
+
authorization_uri_base: The base URI for auth requests. If left at None
|
78
|
+
FLAGS.authorization_uri_base will be used.
|
79
|
+
client_id: The OAuth2 client id
|
80
|
+
client_secret: The OAuth2 client secret
|
81
|
+
user_agent: The user agent for requests
|
82
|
+
|
83
|
+
Returns:
|
84
|
+
An OAuth2Credentials object or None
|
85
|
+
"""
|
86
|
+
if not credentials_file:
|
87
|
+
credentials_file = FLAGS.credentials_file
|
88
|
+
if not authorization_uri_base:
|
89
|
+
authorization_uri_base = FLAGS.authorization_uri_base
|
90
|
+
|
91
|
+
# Ensure that the directory to contain the credentials file exists.
|
92
|
+
credentials_dir = os.path.expanduser(os.path.dirname(credentials_file))
|
93
|
+
if not os.path.exists(credentials_dir):
|
94
|
+
os.makedirs(credentials_dir)
|
95
|
+
|
96
|
+
|
97
|
+
scopes = sorted(scopes)
|
98
|
+
scopes_str = ' '.join(scopes)
|
99
|
+
|
100
|
+
metadata_present = False
|
101
|
+
if FLAGS.auth_service_account:
|
102
|
+
metadata_present = metadata.IsPresent()
|
103
|
+
|
104
|
+
if FLAGS.auth_service_account and metadata_present:
|
105
|
+
try:
|
106
|
+
return auto_auth.Credentials(
|
107
|
+
metadata,
|
108
|
+
FLAGS.auth_service_account,
|
109
|
+
scopes,
|
110
|
+
any_available=True)
|
111
|
+
except auto_auth.CredentialsNotPresentError, e:
|
112
|
+
pass
|
113
|
+
except auto_auth.CredentialsError, e:
|
114
|
+
# We failed to get the scopes from the metadata server.
|
115
|
+
if logger:
|
116
|
+
logger.warn('Failed to automatically authenticate with service '
|
117
|
+
'account: %s' % (e))
|
118
|
+
|
119
|
+
storage = oauth2_multistore_file.get_credential_storage(
|
120
|
+
credentials_file, client_id, user_agent, scopes_str)
|
121
|
+
|
122
|
+
credentials = storage.get()
|
123
|
+
|
124
|
+
if force_reauth and credentials:
|
125
|
+
credentials.invalid = True
|
126
|
+
if (not credentials or credentials.invalid == True) and ask_user:
|
127
|
+
|
128
|
+
if FLAGS.auth_service_account and metadata_present:
|
129
|
+
print ('Service account scopes are not enabled for %s on this instance. '
|
130
|
+
'Using manual authentication.') % (FLAGS.auth_service_account)
|
131
|
+
|
132
|
+
flow = oauth2_client.OAuth2WebServerFlow(
|
133
|
+
client_id=client_id,
|
134
|
+
client_secret=client_secret,
|
135
|
+
scope=scopes_str,
|
136
|
+
user_agent=user_agent,
|
137
|
+
auth_uri=authorization_uri_base + '/auth',
|
138
|
+
token_uri=authorization_uri_base + '/token')
|
139
|
+
credentials = oauth2_tools.run(flow, storage)
|
140
|
+
return credentials
|