gcloud 0.0.2 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data.tar.gz.sig +2 -3
  2. data/CHANGELOG +4 -0
  3. data/LICENSE +674 -0
  4. data/Manifest +111 -0
  5. data/README.md +4 -3
  6. data/bin/gcutil +53 -0
  7. data/gcloud.gemspec +4 -3
  8. data/packages/gcutil-1.7.1/CHANGELOG +197 -0
  9. data/packages/gcutil-1.7.1/LICENSE +202 -0
  10. data/packages/gcutil-1.7.1/VERSION +1 -0
  11. data/packages/gcutil-1.7.1/gcutil +53 -0
  12. data/packages/gcutil-1.7.1/lib/google_api_python_client/LICENSE +23 -0
  13. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/__init__.py +1 -0
  14. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/discovery.py +743 -0
  15. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/errors.py +123 -0
  16. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/ext/__init__.py +0 -0
  17. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/http.py +1443 -0
  18. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/mimeparse.py +172 -0
  19. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/model.py +385 -0
  20. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/schema.py +303 -0
  21. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/__init__.py +1 -0
  22. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/anyjson.py +32 -0
  23. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/appengine.py +528 -0
  24. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/client.py +1139 -0
  25. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/clientsecrets.py +105 -0
  26. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/crypt.py +244 -0
  27. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/django_orm.py +124 -0
  28. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/file.py +107 -0
  29. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/locked_file.py +343 -0
  30. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/multistore_file.py +379 -0
  31. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/tools.py +174 -0
  32. data/packages/gcutil-1.7.1/lib/google_api_python_client/uritemplate/__init__.py +147 -0
  33. data/packages/gcutil-1.7.1/lib/google_apputils/LICENSE +202 -0
  34. data/packages/gcutil-1.7.1/lib/google_apputils/google/__init__.py +3 -0
  35. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/__init__.py +3 -0
  36. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/app.py +356 -0
  37. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/appcommands.py +783 -0
  38. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/basetest.py +1260 -0
  39. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/datelib.py +421 -0
  40. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/debug.py +60 -0
  41. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/file_util.py +181 -0
  42. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/resources.py +67 -0
  43. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/run_script_module.py +217 -0
  44. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/setup_command.py +159 -0
  45. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/shellutil.py +49 -0
  46. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/stopwatch.py +204 -0
  47. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/__init__.py +0 -0
  48. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auth_helper.py +140 -0
  49. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auth_helper_test.py +149 -0
  50. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auto_auth.py +130 -0
  51. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auto_auth_test.py +75 -0
  52. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/basic_cmds.py +128 -0
  53. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/basic_cmds_test.py +111 -0
  54. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/command_base.py +1808 -0
  55. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/command_base_test.py +1651 -0
  56. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/compute/v1beta13.json +2851 -0
  57. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/compute/v1beta14.json +3361 -0
  58. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/disk_cmds.py +342 -0
  59. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/disk_cmds_test.py +474 -0
  60. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/firewall_cmds.py +344 -0
  61. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/firewall_cmds_test.py +231 -0
  62. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/flags_cache.py +274 -0
  63. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/gcutil +89 -0
  64. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/gcutil_logging.py +69 -0
  65. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/image_cmds.py +262 -0
  66. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/image_cmds_test.py +172 -0
  67. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/instance_cmds.py +1506 -0
  68. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/instance_cmds_test.py +1904 -0
  69. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/kernel_cmds.py +91 -0
  70. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/kernel_cmds_test.py +56 -0
  71. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/machine_type_cmds.py +106 -0
  72. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/machine_type_cmds_test.py +59 -0
  73. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/metadata.py +96 -0
  74. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/metadata_lib.py +357 -0
  75. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/metadata_test.py +84 -0
  76. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/mock_api.py +420 -0
  77. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/mock_metadata.py +58 -0
  78. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/move_cmds.py +824 -0
  79. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/move_cmds_test.py +307 -0
  80. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/network_cmds.py +178 -0
  81. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/network_cmds_test.py +133 -0
  82. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/operation_cmds.py +181 -0
  83. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/operation_cmds_test.py +196 -0
  84. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/path_initializer.py +38 -0
  85. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/project_cmds.py +173 -0
  86. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/project_cmds_test.py +111 -0
  87. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/scopes.py +61 -0
  88. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/scopes_test.py +50 -0
  89. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/snapshot_cmds.py +276 -0
  90. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/snapshot_cmds_test.py +260 -0
  91. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/ssh_keys.py +266 -0
  92. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/ssh_keys_test.py +128 -0
  93. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/table_formatter.py +563 -0
  94. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/thread_pool.py +188 -0
  95. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/thread_pool_test.py +88 -0
  96. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/utils.py +208 -0
  97. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/utils_test.py +193 -0
  98. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/version.py +17 -0
  99. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/version_checker.py +246 -0
  100. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/version_checker_test.py +271 -0
  101. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/zone_cmds.py +151 -0
  102. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/zone_cmds_test.py +60 -0
  103. data/packages/gcutil-1.7.1/lib/httplib2/LICENSE +21 -0
  104. data/packages/gcutil-1.7.1/lib/httplib2/httplib2/__init__.py +1630 -0
  105. data/packages/gcutil-1.7.1/lib/httplib2/httplib2/cacerts.txt +714 -0
  106. data/packages/gcutil-1.7.1/lib/httplib2/httplib2/iri2uri.py +110 -0
  107. data/packages/gcutil-1.7.1/lib/httplib2/httplib2/socks.py +438 -0
  108. data/packages/gcutil-1.7.1/lib/iso8601/LICENSE +20 -0
  109. data/packages/gcutil-1.7.1/lib/iso8601/iso8601/__init__.py +1 -0
  110. data/packages/gcutil-1.7.1/lib/iso8601/iso8601/iso8601.py +102 -0
  111. data/packages/gcutil-1.7.1/lib/iso8601/iso8601/test_iso8601.py +111 -0
  112. data/packages/gcutil-1.7.1/lib/python_gflags/AUTHORS +2 -0
  113. data/packages/gcutil-1.7.1/lib/python_gflags/LICENSE +28 -0
  114. data/packages/gcutil-1.7.1/lib/python_gflags/gflags.py +2862 -0
  115. data/packages/gcutil-1.7.1/lib/python_gflags/gflags2man.py +544 -0
  116. data/packages/gcutil-1.7.1/lib/python_gflags/gflags_validators.py +187 -0
  117. metadata +118 -5
  118. 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()