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.
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()