gcloud 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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,271 @@
|
|
|
1
|
+
#!/usr/bin/python
|
|
2
|
+
#
|
|
3
|
+
# Copyright 2012 Google Inc. All Rights Reserved.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
"""Unit tests for the version_checker module."""
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
import path_initializer
|
|
22
|
+
path_initializer.InitializeSysPath()
|
|
23
|
+
|
|
24
|
+
import json
|
|
25
|
+
import os
|
|
26
|
+
import tempfile
|
|
27
|
+
|
|
28
|
+
import httplib2
|
|
29
|
+
|
|
30
|
+
import unittest
|
|
31
|
+
from gcutil import version_checker
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class VersionCheckerTests(unittest.TestCase):
|
|
35
|
+
|
|
36
|
+
class MockHttp(httplib2.Http):
|
|
37
|
+
"""A mock for httplib2.Http that always times out on requests."""
|
|
38
|
+
|
|
39
|
+
def request(self, *unused_args, **unused_kwargs):
|
|
40
|
+
return (httplib2.Response({
|
|
41
|
+
'status': '200',
|
|
42
|
+
'content-length': '81',
|
|
43
|
+
'last-modified': 'Thu, 28 Jun 2012 21:35:00 GMT',
|
|
44
|
+
'date': 'Fri, 14 Sep 2012 21:59:51 GMT',
|
|
45
|
+
'content-type': 'application/json'}),
|
|
46
|
+
'{\n "version": "1.3.0",\n "package_name": "gcutil-1.3.0"\n}\n')
|
|
47
|
+
|
|
48
|
+
def testReadCacheWithNonExistentCacheFile(self):
|
|
49
|
+
vc = version_checker.VersionChecker(cache_path='non-existent-file')
|
|
50
|
+
self.assertEqual(vc._ReadCache(), {})
|
|
51
|
+
|
|
52
|
+
def testReadCacheWithMalformedJson(self):
|
|
53
|
+
malformed_caches = (
|
|
54
|
+
'MALFORMED JSON',
|
|
55
|
+
'{ "last_checked_version": "1.2", "last_check": 3000.0, }',
|
|
56
|
+
'{ "last_checked_version": "1.2", "last_check": 3000.0 }}',
|
|
57
|
+
'{ "last_checked_version": "1.2", "last_check": 3000.0 }bad characters')
|
|
58
|
+
|
|
59
|
+
for malformed_cache in malformed_caches:
|
|
60
|
+
_, bad_cache_file = tempfile.mkstemp()
|
|
61
|
+
try:
|
|
62
|
+
with open(bad_cache_file, 'w') as f:
|
|
63
|
+
f.write(malformed_cache)
|
|
64
|
+
|
|
65
|
+
vc = version_checker.VersionChecker(cache_path=bad_cache_file)
|
|
66
|
+
self.assertEqual(vc._ReadCache(), {})
|
|
67
|
+
finally:
|
|
68
|
+
os.remove(bad_cache_file)
|
|
69
|
+
|
|
70
|
+
def testReadCacheWithGoodCache(self):
|
|
71
|
+
_, cache_file = tempfile.mkstemp()
|
|
72
|
+
try:
|
|
73
|
+
with open(cache_file, 'w') as f:
|
|
74
|
+
f.write('{ "last_checked_version": "1.2", "last_check": 3000.0 }')
|
|
75
|
+
|
|
76
|
+
vc = version_checker.VersionChecker(cache_path=cache_file)
|
|
77
|
+
self.assertEqual(vc._ReadCache(), {'last_checked_version': '1.2',
|
|
78
|
+
'last_check': 3000})
|
|
79
|
+
finally:
|
|
80
|
+
os.remove(cache_file)
|
|
81
|
+
|
|
82
|
+
def testWriteToCache(self):
|
|
83
|
+
_, cache_file = tempfile.mkstemp()
|
|
84
|
+
try:
|
|
85
|
+
cache = {'last_checked_version': '1.2', 'last_check': 3000}
|
|
86
|
+
vc = version_checker.VersionChecker(cache_path=cache_file)
|
|
87
|
+
vc._WriteToCache(cache)
|
|
88
|
+
|
|
89
|
+
with open(cache_file) as f:
|
|
90
|
+
self.assertEqual(json.load(f), cache)
|
|
91
|
+
finally:
|
|
92
|
+
os.remove(cache_file)
|
|
93
|
+
|
|
94
|
+
def testUpdateCache(self):
|
|
95
|
+
vc = version_checker.VersionChecker(
|
|
96
|
+
cache_ttl_sec=20, current_version='1.2.0')
|
|
97
|
+
cache = {}
|
|
98
|
+
vc._UpdateCache(
|
|
99
|
+
cache, http=VersionCheckerTests.MockHttp(), current_time=123456.7)
|
|
100
|
+
self.assertEqual(cache['current_version'], '1.2.0')
|
|
101
|
+
self.assertEqual(cache['last_checked_version'], '1.3.0')
|
|
102
|
+
self.assertEqual(cache['last_check'], 123456.7)
|
|
103
|
+
|
|
104
|
+
def testIsCacheMalformed(self):
|
|
105
|
+
malformed_caches = (
|
|
106
|
+
{},
|
|
107
|
+
{'last_checked_version': 'x', 'last_check': 3000.0,
|
|
108
|
+
'current_version': 'y'},
|
|
109
|
+
{'last_checked_version': '1...2', 'last_check': 3000.0,
|
|
110
|
+
'current_version': '1.2'},
|
|
111
|
+
{'last_checked_version': '1.2', 'last_check': 3000,
|
|
112
|
+
'current_version': '1.2.0'},
|
|
113
|
+
{'last_checked_version': '1.2', 'current_version': '1.2.0'},
|
|
114
|
+
{'last_checked_version': '1.2.x', 'last_check': 3000,
|
|
115
|
+
'current_version': '1.2.0'})
|
|
116
|
+
for cache in malformed_caches:
|
|
117
|
+
self.assertTrue(version_checker.VersionChecker._IsCacheMalformed(cache))
|
|
118
|
+
|
|
119
|
+
good_caches = (
|
|
120
|
+
{'last_checked_version': '1.3.0', 'last_check': 3000.0,
|
|
121
|
+
'current_version': '1.2.0'},
|
|
122
|
+
{'last_checked_version': '1.3.0', 'last_check': 3000.0,
|
|
123
|
+
'current_version': '1.2.0',
|
|
124
|
+
'last_check_time': '2012-09-17T18:03:48.792579+00:00',
|
|
125
|
+
'latest_version': '1.1.20120628.1214'})
|
|
126
|
+
for cache in good_caches:
|
|
127
|
+
self.assertFalse(version_checker.VersionChecker._IsCacheMalformed(cache))
|
|
128
|
+
|
|
129
|
+
def testIsCacheStale(self):
|
|
130
|
+
vc = version_checker.VersionChecker(
|
|
131
|
+
cache_ttl_sec=20, current_version='1.2.0')
|
|
132
|
+
cache = {'last_checked_version': '1.2', 'last_check': 3000.0,
|
|
133
|
+
'current_version': '1.2.0'}
|
|
134
|
+
|
|
135
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=1))
|
|
136
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=2000))
|
|
137
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=2999))
|
|
138
|
+
self.assertFalse(vc._IsCacheStale(cache, current_time=3000))
|
|
139
|
+
self.assertFalse(vc._IsCacheStale(cache, current_time=3005))
|
|
140
|
+
self.assertFalse(vc._IsCacheStale(cache, current_time=3010))
|
|
141
|
+
self.assertFalse(vc._IsCacheStale(cache, current_time=3019))
|
|
142
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=3020))
|
|
143
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=3021))
|
|
144
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=4000))
|
|
145
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=398457398))
|
|
146
|
+
|
|
147
|
+
self.assertTrue(vc._IsCacheStale({}, current_time=1))
|
|
148
|
+
self.assertTrue(vc._IsCacheStale({}, current_time=2000))
|
|
149
|
+
self.assertTrue(vc._IsCacheStale({}, current_time=2999))
|
|
150
|
+
self.assertTrue(vc._IsCacheStale({}, current_time=3000))
|
|
151
|
+
self.assertTrue(vc._IsCacheStale({}, current_time=3005))
|
|
152
|
+
self.assertTrue(vc._IsCacheStale({}, current_time=3010))
|
|
153
|
+
self.assertTrue(vc._IsCacheStale({}, current_time=3019))
|
|
154
|
+
self.assertTrue(vc._IsCacheStale({}, current_time=3020))
|
|
155
|
+
self.assertTrue(vc._IsCacheStale({}, current_time=3021))
|
|
156
|
+
self.assertTrue(vc._IsCacheStale({}, current_time=4000))
|
|
157
|
+
self.assertTrue(vc._IsCacheStale({}, current_time=398457398))
|
|
158
|
+
|
|
159
|
+
def testIsCacheStaleWithMalformedCache(self):
|
|
160
|
+
vc = version_checker.VersionChecker(
|
|
161
|
+
cache_ttl_sec=20, current_version='1.2.0')
|
|
162
|
+
malformed_caches = (
|
|
163
|
+
{'last_checked_version': '1.2', 'last_check': 3000,
|
|
164
|
+
'current_version': '1.2.0'},
|
|
165
|
+
{'last_checked_version': '1.2', 'current_version': '1.2.0'},
|
|
166
|
+
{'last_checked_version': '1.2.x', 'last_check': 3000,
|
|
167
|
+
'current_version': '1.2.0'})
|
|
168
|
+
|
|
169
|
+
for cache in malformed_caches:
|
|
170
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=1))
|
|
171
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=2000))
|
|
172
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=2999))
|
|
173
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=3000))
|
|
174
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=3005))
|
|
175
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=3010))
|
|
176
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=3019))
|
|
177
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=3020))
|
|
178
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=3021))
|
|
179
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=4000))
|
|
180
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=398457398))
|
|
181
|
+
|
|
182
|
+
def testIsCacheStaleWithUpgradedVersion(self):
|
|
183
|
+
vc = version_checker.VersionChecker(
|
|
184
|
+
cache_ttl_sec=20, current_version='1.3.0')
|
|
185
|
+
cache = {'last_checked_version': '1.3.0', 'last_check': 3000.0,
|
|
186
|
+
'current_version': '1.2.0'}
|
|
187
|
+
|
|
188
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=1))
|
|
189
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=2000))
|
|
190
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=2999))
|
|
191
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=3000))
|
|
192
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=3005))
|
|
193
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=3010))
|
|
194
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=3019))
|
|
195
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=3020))
|
|
196
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=3021))
|
|
197
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=4000))
|
|
198
|
+
self.assertTrue(vc._IsCacheStale(cache, current_time=398457398))
|
|
199
|
+
|
|
200
|
+
def testParseVersionString(self):
|
|
201
|
+
parse_fn = version_checker.VersionChecker._ParseVersionString
|
|
202
|
+
self.assertEqual(parse_fn('1'), (1,))
|
|
203
|
+
self.assertEqual(parse_fn('1.2'), (1, 2))
|
|
204
|
+
self.assertEqual(parse_fn('1.2.0'), (1, 2, 0))
|
|
205
|
+
self.assertEqual(parse_fn('0.1.0'), (0, 1, 0))
|
|
206
|
+
self.assertEqual(parse_fn('12.13.14'), (12, 13, 14))
|
|
207
|
+
|
|
208
|
+
def testCompareVersions(self):
|
|
209
|
+
compare_fn = version_checker.VersionChecker._CompareVersions
|
|
210
|
+
self.assertTrue(compare_fn('0', '1.2'))
|
|
211
|
+
self.assertTrue(compare_fn('1.2', '1.3'))
|
|
212
|
+
self.assertTrue(compare_fn('1.2', '1.2.1'))
|
|
213
|
+
self.assertTrue(compare_fn('1.2.0', '1.2.1'))
|
|
214
|
+
self.assertTrue(compare_fn('1.2.0', '1.2.13'))
|
|
215
|
+
self.assertTrue(compare_fn('1.2.0', '1.3'))
|
|
216
|
+
self.assertFalse(compare_fn('1.3', '1.3'))
|
|
217
|
+
self.assertFalse(compare_fn('1.2.2', '1.2.0'))
|
|
218
|
+
self.assertFalse(compare_fn('1.1', '1.0'))
|
|
219
|
+
|
|
220
|
+
def testNewVersionExistsWithNonStaleCache(self):
|
|
221
|
+
|
|
222
|
+
def MockReadCache():
|
|
223
|
+
return {'last_checked_version': '1.3.0', 'last_check': 3000.0,
|
|
224
|
+
'current_version': '1.2.0'}
|
|
225
|
+
|
|
226
|
+
def MockIsCacheStale(cache):
|
|
227
|
+
return False
|
|
228
|
+
|
|
229
|
+
vc = version_checker.VersionChecker(current_version='1.2.0')
|
|
230
|
+
vc._ReadCache = MockReadCache
|
|
231
|
+
vc._IsCacheStale = MockIsCacheStale
|
|
232
|
+
self.assertTrue(vc._NewVersionExists())
|
|
233
|
+
|
|
234
|
+
vc = version_checker.VersionChecker(current_version='1.3.0')
|
|
235
|
+
vc._ReadCache = MockReadCache
|
|
236
|
+
vc._IsCacheStale = MockIsCacheStale
|
|
237
|
+
self.assertFalse(vc._NewVersionExists())
|
|
238
|
+
|
|
239
|
+
def testNewVersionExistsWithStaleCache(self):
|
|
240
|
+
|
|
241
|
+
def MockIsCacheStale(cache):
|
|
242
|
+
return True
|
|
243
|
+
|
|
244
|
+
def MockUpdateCache(cache):
|
|
245
|
+
cache['last_checked_version'] = '1.3.0'
|
|
246
|
+
|
|
247
|
+
_, cache_file = tempfile.mkstemp()
|
|
248
|
+
try:
|
|
249
|
+
with open(cache_file, 'w') as f:
|
|
250
|
+
f.write('{ "last_checked_version": "1.2.0", "last_check": 3000.0,'
|
|
251
|
+
' "current_version": "1.2.0"}')
|
|
252
|
+
|
|
253
|
+
vc = version_checker.VersionChecker(
|
|
254
|
+
cache_path=cache_file, current_version='1.2.0')
|
|
255
|
+
vc._IsCacheStale = MockIsCacheStale
|
|
256
|
+
vc._UpdateCache = MockUpdateCache
|
|
257
|
+
self.assertTrue(vc._NewVersionExists())
|
|
258
|
+
self.assertEqual(vc._ReadCache()['last_checked_version'], '1.3.0')
|
|
259
|
+
|
|
260
|
+
def MockUpdateCache2(cache):
|
|
261
|
+
cache['last_checked_version'] = '1.2.0'
|
|
262
|
+
|
|
263
|
+
vc._UpdateCache = MockUpdateCache2
|
|
264
|
+
self.assertFalse(vc._NewVersionExists())
|
|
265
|
+
self.assertEqual(vc._ReadCache()['last_checked_version'], '1.2.0')
|
|
266
|
+
finally:
|
|
267
|
+
os.remove(cache_file)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
if __name__ == '__main__':
|
|
271
|
+
unittest.main()
|
|
@@ -0,0 +1,151 @@
|
|
|
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
|
+
"""Commands for interacting with Google Compute Engine availability zones."""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
import iso8601
|
|
20
|
+
|
|
21
|
+
from google.apputils import appcommands
|
|
22
|
+
import gflags as flags
|
|
23
|
+
|
|
24
|
+
from gcutil import command_base
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
FLAGS = flags.FLAGS
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class ZoneCommand(command_base.GoogleComputeCommand):
|
|
31
|
+
"""Base command for working with the zones collection."""
|
|
32
|
+
|
|
33
|
+
default_sort_field = 'name'
|
|
34
|
+
summary_fields = (('name', 'name'),
|
|
35
|
+
('description', 'description'),
|
|
36
|
+
('status', 'status'),
|
|
37
|
+
('next-maintenance-window', 'next_maintenance_window'))
|
|
38
|
+
|
|
39
|
+
detail_fields = (('name', 'name'),
|
|
40
|
+
('description', 'description'),
|
|
41
|
+
('creation-time', 'creationTimestamp'),
|
|
42
|
+
('status', 'status'))
|
|
43
|
+
|
|
44
|
+
def SetApi(self, api):
|
|
45
|
+
"""Set the Google Compute Engine API for the command.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
api: The Google Compute Engine API used by this command.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
None.
|
|
52
|
+
"""
|
|
53
|
+
self._zones_api = api.zones()
|
|
54
|
+
if self._IsUsingAtLeastApiVersion('v1beta14'):
|
|
55
|
+
self.summary_fields = (
|
|
56
|
+
('name', 'name'),
|
|
57
|
+
('description', 'description'),
|
|
58
|
+
('status', 'status'),
|
|
59
|
+
('next-maintenance-window', 'next_maintenance_window'),
|
|
60
|
+
('instances-usage', 'instances'),
|
|
61
|
+
('cpus-usage', 'cpus'),
|
|
62
|
+
('disks-usage', 'disks'),
|
|
63
|
+
('disks-total-gb-usage', 'disks_total_gb'))
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class GetZone(ZoneCommand):
|
|
67
|
+
"""Get a zone."""
|
|
68
|
+
|
|
69
|
+
positional_args = '<zone-name>'
|
|
70
|
+
|
|
71
|
+
def CustomizePrintResult(self, result, table):
|
|
72
|
+
"""Customized result printing for this type.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
result: json dictionary returned by the server
|
|
76
|
+
table: the pretty printing table to be customized
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
None.
|
|
80
|
+
|
|
81
|
+
"""
|
|
82
|
+
# Add machine types
|
|
83
|
+
for (i, m) in enumerate(result.get('availableMachineType', [])):
|
|
84
|
+
key = ''
|
|
85
|
+
if i == 0:
|
|
86
|
+
key = 'machine types'
|
|
87
|
+
table.AddRow((key, self._PresentElement(m)))
|
|
88
|
+
# Add the maintenance windows
|
|
89
|
+
table.AddRow(('maintenance-windows', ''))
|
|
90
|
+
for window in result.get('maintenanceWindows', []):
|
|
91
|
+
table.AddRow(('', ''))
|
|
92
|
+
table.AddRow((' name', window['name']))
|
|
93
|
+
table.AddRow((' description', window['description']))
|
|
94
|
+
table.AddRow((' begin-time', window['beginTime']))
|
|
95
|
+
table.AddRow((' end-time', window['endTime']))
|
|
96
|
+
# Add the zone quotas
|
|
97
|
+
table.AddRow(('', ''))
|
|
98
|
+
table.AddRow(('usage', ''))
|
|
99
|
+
for quota in result.get('quotas', []):
|
|
100
|
+
table.AddRow((' %s' % quota['metric'].lower().replace('_', '-'),
|
|
101
|
+
'%s/%s' % (str(quota['usage']), str(quota['limit']))))
|
|
102
|
+
|
|
103
|
+
def Handle(self, zone_name):
|
|
104
|
+
"""Get the specified zone.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
zone_name: Path of the zone to get.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
The result of getting the zone.
|
|
111
|
+
"""
|
|
112
|
+
request = self._zones_api.get(project=self._project, zone=zone_name)
|
|
113
|
+
return request.execute()
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class ListZones(ZoneCommand, command_base.GoogleComputeListCommand):
|
|
117
|
+
"""List available zones for a project."""
|
|
118
|
+
|
|
119
|
+
def ListFunc(self):
|
|
120
|
+
return self._zones_api.list
|
|
121
|
+
|
|
122
|
+
def Handle(self):
|
|
123
|
+
"""List the project's zones."""
|
|
124
|
+
result = super(ListZones, self).Handle()
|
|
125
|
+
items = result.get('items', [])
|
|
126
|
+
|
|
127
|
+
# Add the next maintenance window start time to each entry.
|
|
128
|
+
for zone in items:
|
|
129
|
+
next_iso = None
|
|
130
|
+
next_str = 'None scheduled'
|
|
131
|
+
|
|
132
|
+
for window in zone.get('maintenanceWindows', []):
|
|
133
|
+
begin_str = window['beginTime']
|
|
134
|
+
begin_iso = iso8601.parse_date(begin_str)
|
|
135
|
+
if next_iso is None or begin_iso < next_iso:
|
|
136
|
+
next_iso = begin_iso
|
|
137
|
+
next_str = begin_str
|
|
138
|
+
|
|
139
|
+
zone['next_maintenance_window'] = next_str
|
|
140
|
+
|
|
141
|
+
for quota in zone.get('quotas', []):
|
|
142
|
+
column_name = quota['metric'].lower()
|
|
143
|
+
zone[column_name] = (
|
|
144
|
+
'%s/%s' % (str(quota['usage']), str(quota['limit'])))
|
|
145
|
+
|
|
146
|
+
return result
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def AddCommands():
|
|
150
|
+
appcommands.AddCmd('getzone', GetZone)
|
|
151
|
+
appcommands.AddCmd('listzones', ListZones)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/python
|
|
2
|
+
#
|
|
3
|
+
# Copyright 2012 Google Inc. All Rights Reserved.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
"""Unit tests for the zone commands."""
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
import path_initializer
|
|
22
|
+
path_initializer.InitializeSysPath()
|
|
23
|
+
|
|
24
|
+
import copy
|
|
25
|
+
|
|
26
|
+
import gflags as flags
|
|
27
|
+
import unittest
|
|
28
|
+
|
|
29
|
+
from gcutil import command_base
|
|
30
|
+
from gcutil import mock_api
|
|
31
|
+
from gcutil import zone_cmds
|
|
32
|
+
|
|
33
|
+
FLAGS = flags.FLAGS
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ZoneCmdsTest(unittest.TestCase):
|
|
37
|
+
|
|
38
|
+
def testGetZoneGeneratesCorrectRequest(self):
|
|
39
|
+
flag_values = copy.deepcopy(FLAGS)
|
|
40
|
+
|
|
41
|
+
command = zone_cmds.GetZone('getzone', flag_values)
|
|
42
|
+
|
|
43
|
+
expected_jurisdiction = 'test_jurisdiction'
|
|
44
|
+
expected_region = 'test_region'
|
|
45
|
+
expected_zone = 'z'
|
|
46
|
+
submitted_full_zone = '%s-%s-%s' % (expected_jurisdiction,
|
|
47
|
+
expected_region,
|
|
48
|
+
expected_zone)
|
|
49
|
+
flag_values.service_version = command_base.CURRENT_VERSION
|
|
50
|
+
|
|
51
|
+
command.SetFlags(flag_values)
|
|
52
|
+
command.SetApi(mock_api.MockApi())
|
|
53
|
+
|
|
54
|
+
result = command.Handle(submitted_full_zone)
|
|
55
|
+
|
|
56
|
+
self.assertEqual(result['zone'], submitted_full_zone)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
if __name__ == '__main__':
|
|
60
|
+
unittest.main()
|