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,307 @@
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 move commands."""
18
+
19
+
20
+
21
+ import path_initializer
22
+ path_initializer.InitializeSysPath()
23
+
24
+ import copy
25
+ import uuid
26
+
27
+ from google.apputils import app
28
+ import gflags as flags
29
+ import unittest
30
+
31
+ from gcutil import command_base
32
+ from gcutil import mock_api
33
+ from gcutil import move_cmds
34
+
35
+ FLAGS = flags.FLAGS
36
+
37
+ class MoveInstancesBaseTestCase(unittest.TestCase):
38
+
39
+ def setUp(self):
40
+ self.flag_values = copy.deepcopy(FLAGS)
41
+ self.command = self._CreateCommand()
42
+ self.api = mock_api.MockApi()
43
+ self.command.SetFlags(self.flag_values)
44
+ self.command.SetApi(self.api)
45
+
46
+ def _CreateCommand(self):
47
+ return move_cmds.MoveInstances('basemoveinstances', self.flag_values)
48
+
49
+ class MoveInstancesBaseTest(MoveInstancesBaseTestCase):
50
+
51
+ cmd_name = 'moveinstancesbase'
52
+
53
+ def testExtractAvailableQuota(self):
54
+ project_quota = [
55
+ {'metric': 'INSTANCES',
56
+ 'usage': 5.0,
57
+ 'limit': 10.0},
58
+ {'metric': 'CPUS',
59
+ 'usage': 40.0,
60
+ 'limit': 0}, # Quota was changed after resource-creation.
61
+ {'metric': 'EPHEMERAL_ADDRESSES',
62
+ 'usage': 5.0,
63
+ 'limit': 10.0},
64
+ {'metric': 'DISKS',
65
+ 'usage': 7.0,
66
+ 'limit': 10.0},
67
+ {'metric': 'DISKS_TOTAL_GB',
68
+ 'usage': 40.0,
69
+ 'limit': 100.0},
70
+ {'metric': 'SNAPSHOTS',
71
+ 'usage': 3.0,
72
+ 'limit': 100.0},
73
+ {'metric': 'NETWORKS',
74
+ 'usage': 2.0,
75
+ 'limit': 10.0},
76
+ {'metric': 'FIREWALLS',
77
+ 'usage': 3.0,
78
+ 'limit': 10.0},
79
+ {'metric': 'IMAGES',
80
+ 'usage': 9.0,
81
+ 'limit': 10.0}]
82
+
83
+ zone_quota = [
84
+ {'metric': 'INSTANCES',
85
+ 'usage': 3.0,
86
+ 'limit': 10.0},
87
+ {'metric': 'CPUS',
88
+ 'usage': 3.0,
89
+ 'limit': 10.0},
90
+ {'metric': 'DISKS',
91
+ 'usage': 2.0,
92
+ 'limit': 10.0},
93
+ {'metric': 'DISKS_TOTAL_GB',
94
+ 'usage': 22.0,
95
+ 'limit': 25.0}]
96
+
97
+ requirements = {
98
+ 'INSTANCES': 2.0,
99
+ 'CPUS': 2.0,
100
+ 'DISKS_TOTAL_GB': 32.0,
101
+ 'SNAPSHOTS': 3.0,
102
+ 'DISKS': 3.0}
103
+
104
+ expected = {
105
+ 'INSTANCES': 7.0,
106
+ 'CPUS': -38.0,
107
+ 'DISKS_TOTAL_GB': 3.0,
108
+ 'SNAPSHOTS': 97.0,
109
+ 'DISKS': 6.0}
110
+
111
+ self.assertEqual(self.command._ExtractAvailableQuota(
112
+ project_quota, zone_quota, requirements), expected)
113
+
114
+
115
+ class MoveInstancesTest(MoveInstancesBaseTestCase):
116
+
117
+ def _CreateCommand(self):
118
+ return move_cmds.MoveInstances('moveinstances', self.flag_values)
119
+
120
+ def testServiceVersionValidation(self):
121
+ for version in command_base.SUPPORTED_VERSIONS:
122
+ if version == 'v1beta14':
123
+ break
124
+
125
+ self.flag_values.source_zone = 'src-zone'
126
+ self.flag_values.destination_zone = 'dest-zone'
127
+ self.flag_values.service_version = version
128
+ self.assertRaises(app.UsageError, self.command.Handle, ['.*'])
129
+
130
+ def testFlagValidationWithNoSourceZone(self):
131
+ self.flag_values.destination_zone = 'dest-zone'
132
+ self.flag_values.service_version = 'v1beta14'
133
+ self.assertRaises(app.UsageError, self.command.Handle, ['.*'])
134
+
135
+ def testFlagValidationWithNoDestinationZone(self):
136
+ self.flag_values.source_zone = 'src-zone'
137
+ self.flag_values.service_version = 'v1beta14'
138
+ self.assertRaises(app.UsageError, self.command.Handle, ['.*'])
139
+
140
+ def testFlagValidationWithNoSameSrcAndDest(self):
141
+ self.flag_values.source_zone = 'my-zone'
142
+ self.flag_values.destination_zone = 'my-zone'
143
+ self.assertRaises(app.UsageError, self.command.Handle, ['.*'])
144
+
145
+ def testGenerateSnapshotNames(self):
146
+ test_cases = (
147
+ [],
148
+ ['disk-0'],
149
+ ['disk-1', 'disk2', 'disk3'])
150
+
151
+ for arg in test_cases:
152
+ res = self.command._GenerateSnapshotNames(arg)
153
+ self.assertEqual(len(res), len(arg))
154
+ self.assertEqual(sorted(res.keys()), sorted(arg))
155
+ for val in res.values():
156
+ self.assertTrue(isinstance(val, basestring))
157
+ self.assertTrue(val.startswith('snapshot-'))
158
+ try:
159
+ uuid.UUID(val[len('snapshot-'):])
160
+ except ValueError:
161
+ self.fail('Value generated does not include valid UUID.')
162
+
163
+ def _GenerateInstanceResources(self, num, prefix='instance'):
164
+ template = {
165
+ 'status': 'RUNNING',
166
+ 'kind': 'compute#instance',
167
+ 'machineType': 'https://googleapis.com/compute/.../n1-standard-1',
168
+ 'zone': 'https://googleapis.com/compute/.../zones/my-zone',
169
+ 'tags': [],
170
+ 'image': 'https://googleapis.com/compute/.../images/gcel',
171
+ 'disks': [
172
+ {
173
+ 'index': 0,
174
+ 'kind': 'compute#instanceDisk',
175
+ 'type': 'EPHEMERAL',
176
+ 'mode': 'READ_WRITE'
177
+ },
178
+ {
179
+ 'index': 1,
180
+ 'kind': 'compute#attachedDisk',
181
+ 'mode': 'READ_ONLY',
182
+ 'type': 'PERSISTENT'
183
+ }
184
+ ],
185
+ 'networkInterfaces': [
186
+ {
187
+ 'networkIP': '10.211.197.175',
188
+ 'kind': 'compute#instanceNetworkInterface',
189
+ 'accessConfigs': [
190
+ {
191
+ 'type': 'ONE_TO_ONE_NAT',
192
+ 'name': 'External NAT',
193
+ 'natIP': '173.255.120.98'
194
+ }
195
+ ],
196
+ 'name': 'nic0',
197
+ 'network': 'https://googleapis.com/compute/.../networks/default'
198
+ }
199
+ ],
200
+ 'id': '12884714477555140369'}
201
+
202
+ res = []
203
+ for i in xrange(num):
204
+ instance = copy.deepcopy(template)
205
+ instance['name'] = '%s-%s' % (prefix, i)
206
+ instance['selfLink'] = (
207
+ 'https://googleapis.com/compute/.../instances/%s' % instance['name'])
208
+ instance['disks'][1]['deviceName'] = instance['name']
209
+ instance['disks'][1]['source'] = (
210
+ 'https://www.googleapis.com/compute/.../disks/%s' % instance['name'])
211
+ res.append(instance)
212
+ return res
213
+
214
+ def testCheckInstancePreconditionsWithNoMatchingInstances(self):
215
+ self.assertRaises(command_base.CommandError,
216
+ self.command._CheckInstancePreconditions,
217
+ [], [])
218
+
219
+ def testCheckInstancePreconditionsWithTooManyInstances(self):
220
+ for num_instances_to_mv in (101, 120, 200):
221
+ for num_instances_in_dest in (0, 10, 100, 101, 200):
222
+ instances_to_mv = self._GenerateInstanceResources(
223
+ num_instances_to_mv, prefix='i')
224
+ instances_in_dest = self._GenerateInstanceResources(
225
+ num_instances_in_dest, prefix='x')
226
+ self.assertRaises(
227
+ command_base.CommandError,
228
+ self.command._CheckInstancePreconditions,
229
+ instances_to_mv,
230
+ instances_in_dest)
231
+
232
+ def testCheckInstancePreconditionsWithNameCollisions(self):
233
+ # Tests with lots of collisions.
234
+ for num_instances in (1, 2, 10):
235
+ instances = self._GenerateInstanceResources(num_instances)
236
+ self.assertRaises(command_base.CommandError,
237
+ self.command._CheckInstancePreconditions,
238
+ instances, instances)
239
+
240
+ # Tests with only a single collision.
241
+ for num_instances in (1, 2, 10):
242
+ instances_to_mv = self._GenerateInstanceResources(
243
+ num_instances, prefix='i')
244
+ instances_in_dest = self._GenerateInstanceResources(
245
+ num_instances, prefix='x')
246
+ instances_in_dest.extend(self._GenerateInstanceResources(1, prefix='i'))
247
+ self.assertRaises(
248
+ command_base.CommandError,
249
+ self.command._CheckInstancePreconditions,
250
+ instances_to_mv,
251
+ instances_in_dest)
252
+
253
+ def testCheckInstancePreconditionsUnderNormalConditions(self):
254
+ for num_instances_to_mv in (1, 2, 10):
255
+ for num_instances_in_dest in (0, 2, 10):
256
+ instances_to_mv = self._GenerateInstanceResources(
257
+ num_instances_to_mv, prefix='i')
258
+ instances_in_dest = self._GenerateInstanceResources(
259
+ num_instances_in_dest, prefix='x')
260
+ self.command._CheckInstancePreconditions(
261
+ instances_to_mv, instances_in_dest)
262
+
263
+ def testCheckDiskPreconditionsWithTooManyDisks(self):
264
+ for num_disks in (101, 120, 200):
265
+ disk_names = ['disk-%s' % i for i in xrange(num_disks)]
266
+ self.assertRaises(
267
+ command_base.CommandError,
268
+ self.command._CheckDiskPreconditions,
269
+ [],
270
+ disk_names)
271
+
272
+ def testCheckDiskPreconditionsWithPoorDiskAttachment(self):
273
+ for num_instances in (1, 2, 10):
274
+ for num_disks in xrange(1, num_instances + 1):
275
+ self.assertRaises(
276
+ command_base.CommandError,
277
+ self.command._CheckDiskPreconditions,
278
+ self._GenerateInstanceResources(num_instances, prefix='i'),
279
+ ['i-%s' % i for i in xrange(num_disks)])
280
+
281
+
282
+ class ResumeMoveTest(MoveInstancesBaseTestCase):
283
+
284
+ def _CreateCommand(self):
285
+ return move_cmds.ResumeMove('resumemove', self.flag_values)
286
+
287
+ def testGetKeyWithGoodKeys(self):
288
+ test_cases = (
289
+ ({'key1': []}, 'key1', []),
290
+ ({'key1': [1, 2, 3]}, 'key1', [1, 2, 3]),
291
+ ({'key1': [1, 2, 3], 'key2': 5}, 'key2', 5))
292
+ for log, key, expected in test_cases:
293
+ self.assertEqual(self.command._GetKey(log, key), expected)
294
+
295
+ def testGetKeyWithBadKeys(self):
296
+ test_cases = (
297
+ {},
298
+ {'key1': []},
299
+ {'key1': [1, 2, 3]},
300
+ {'key1': [1, 2, 3], 'key2': 5})
301
+ for log in test_cases:
302
+ self.assertRaises(command_base.CommandError,
303
+ self.command._GetKey, log, 'nonexistent')
304
+
305
+
306
+ if __name__ == '__main__':
307
+ unittest.main()
@@ -0,0 +1,178 @@
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 VM networks."""
16
+
17
+
18
+
19
+
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 NetworkCommand(command_base.GoogleComputeCommand):
31
+ """Base command for working with the networks collection."""
32
+
33
+ default_sort_field = 'name'
34
+ summary_fields = (('name', 'name'),
35
+ ('description', 'description'),
36
+ ('addresses', 'IPv4Range'),
37
+ ('gateway', 'gatewayIPv4'))
38
+
39
+ detail_fields = (('name', 'name'),
40
+ ('description', 'description'),
41
+ ('creation-time', 'creationTimestamp'),
42
+ ('addresses', 'IPv4Range'),
43
+ ('gateway', 'gatewayIPv4'))
44
+
45
+ resource_collection_name = 'networks'
46
+
47
+ def __init__(self, name, flag_values):
48
+ super(NetworkCommand, self).__init__(name, flag_values)
49
+
50
+ def SetApi(self, api):
51
+ """Set the Google Compute Engine API for the command.
52
+
53
+ Args:
54
+ api: The Google Compute Engine API used by this command.
55
+
56
+ Returns:
57
+ None.
58
+
59
+ """
60
+ self._networks_api = api.networks()
61
+
62
+
63
+ class AddNetwork(NetworkCommand):
64
+ """Create a new network instance."""
65
+
66
+ positional_args = '<network-name>'
67
+
68
+ def __init__(self, name, flag_values):
69
+ super(AddNetwork, self).__init__(name, flag_values)
70
+
71
+ flags.DEFINE_string('description',
72
+ '',
73
+ 'Network description.',
74
+ flag_values=flag_values)
75
+ flags.DEFINE_string('range',
76
+ '10.0.0.0/8',
77
+ 'IPv4 address range of this network.',
78
+ flag_values=flag_values)
79
+ flags.DEFINE_string('gateway',
80
+ '10.0.0.1',
81
+ 'IPv4 address of the gateway within the network.',
82
+ flag_values=flag_values)
83
+ flags.DEFINE_list('reserve',
84
+ [],
85
+ 'IPv4 addresses on the network which should not be '
86
+ 'automatically assigned (comma separated).',
87
+ flag_values=flag_values)
88
+
89
+ def Handle(self, network_name):
90
+ """Add the specified network.
91
+
92
+ Args:
93
+ network_name: The name of the network to add.
94
+
95
+ Returns:
96
+ The result of adding the network.
97
+ """
98
+ network_resource = {
99
+ 'kind': self._GetResourceApiKind('network'),
100
+ 'name': self.DenormalizeResourceName(network_name),
101
+ 'description': self._flags.description,
102
+ 'IPv4Range': self._flags.range,
103
+ 'gatewayIPv4': self._flags.gateway,
104
+ 'reservedIPv4': self._flags.reserve,
105
+ }
106
+
107
+ network_request = self._networks_api.insert(project=self._project,
108
+ body=network_resource)
109
+ return network_request.execute()
110
+
111
+
112
+ class GetNetwork(NetworkCommand):
113
+ """Get a network instance."""
114
+
115
+ positional_args = '<network-name>'
116
+
117
+ def __init__(self, name, flag_values):
118
+ super(GetNetwork, self).__init__(name, flag_values)
119
+
120
+ def Handle(self, network_name):
121
+ """Get the specified network.
122
+
123
+ Args:
124
+ network_name: The name of the network to get.
125
+
126
+ Returns:
127
+ The result of getting the network.
128
+ """
129
+ network_request = self._networks_api.get(
130
+ project=self._project,
131
+ network=self.DenormalizeResourceName(network_name))
132
+
133
+ return network_request.execute()
134
+
135
+
136
+ class DeleteNetwork(NetworkCommand):
137
+ """Delete one or more machine networks.
138
+
139
+ If multiple network names are specified, the networks will be deleted in
140
+ parallel.
141
+ """
142
+
143
+ positional_args = '<network-name-1> ... <network-name-n>'
144
+ safety_prompt = 'Delete network'
145
+
146
+ def __init__(self, name, flag_values):
147
+ super(DeleteNetwork, self).__init__(name, flag_values)
148
+
149
+ def Handle(self, *network_names):
150
+ """Delete the specified networks.
151
+
152
+ Args:
153
+ *network_names: The names of the networks to delete.
154
+
155
+ Returns:
156
+ Tuple (results, exceptions) - results of deleting the networks.
157
+ """
158
+ requests = []
159
+ for name in network_names:
160
+ requests.append(self._networks_api.delete(
161
+ project=self._project,
162
+ network=self.DenormalizeResourceName(name)))
163
+ results, exceptions = self.ExecuteRequests(requests)
164
+ return self.MakeListResult(results, 'operationList'), exceptions
165
+
166
+
167
+ class ListNetworks(NetworkCommand, command_base.GoogleComputeListCommand):
168
+ """List the networks for a project."""
169
+
170
+ def ListFunc(self):
171
+ return self._networks_api.list
172
+
173
+
174
+ def AddCommands():
175
+ appcommands.AddCmd('addnetwork', AddNetwork)
176
+ appcommands.AddCmd('getnetwork', GetNetwork)
177
+ appcommands.AddCmd('deletenetwork', DeleteNetwork)
178
+ appcommands.AddCmd('listnetworks', ListNetworks)