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,344 @@
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 firewalls."""
16
+
17
+
18
+
19
+ import socket
20
+
21
+ from google.apputils import appcommands
22
+ import gflags as flags
23
+
24
+ from gcutil import command_base
25
+ from gcutil import utils
26
+
27
+
28
+ FLAGS = flags.FLAGS
29
+
30
+
31
+ class FirewallCommand(command_base.GoogleComputeCommand):
32
+ """Base command for working with the firewalls collection."""
33
+
34
+ default_sort_field = 'name'
35
+ summary_fields = (('name', 'name'),
36
+ ('description', 'description'),
37
+ ('network', 'network'),
38
+ ('source-ips', 'sourceRanges'),
39
+ ('source-tags', 'sourceTags'),
40
+ ('target-tags', 'targetTags'))
41
+
42
+ # The remaining complex fields are filled in via CustomizePrintResult
43
+ detail_fields = (('name', 'name'),
44
+ ('description', 'description'),
45
+ ('creation-time', 'creationTimestamp'),
46
+ ('network', 'network'),
47
+ ('source-ips', 'sourceRanges'),
48
+ ('source-tags', 'sourceTags'),
49
+ ('target-tags', 'targetTags'))
50
+
51
+ resource_collection_name = 'firewalls'
52
+
53
+ def __init__(self, name, flag_values):
54
+ super(FirewallCommand, self).__init__(name, flag_values)
55
+
56
+ def SetApi(self, api):
57
+ """Set the Google Compute Engine API for the command.
58
+
59
+ Args:
60
+ api: The Google Compute Engine API used by this command.
61
+
62
+ Returns:
63
+ None.
64
+
65
+ """
66
+ self._firewalls_api = api.firewalls()
67
+
68
+ def CustomizePrintResult(self, result, table):
69
+ """Customized result printing for this type.
70
+
71
+ Args:
72
+ result: json dictionary returned by the server
73
+ table: the pretty printing table to be customized
74
+
75
+ Returns:
76
+ None.
77
+
78
+ """
79
+ # Add the rules
80
+ for allowed in result.get('allowed', []):
81
+ as_string = str(allowed['IPProtocol'])
82
+ if allowed.get('ports'):
83
+ as_string += ': %s' % ', '.join(allowed['ports'])
84
+ table.AddRow(('allowed', as_string))
85
+
86
+
87
+ class FirewallRules(object):
88
+ """Class representing the list of a firewall's rules.
89
+
90
+ This class is only used for parsing a firewall from command-line flags,
91
+ for printing the firewall, we simply dump the JSON.
92
+ """
93
+
94
+ @staticmethod
95
+ def ParsePortSpecs(port_spec_strings):
96
+ """Parse the port-specification portion of firewall rules.
97
+
98
+ This takes the value of the 'allowed' flag and builds the
99
+ corresponding firewall rules, excluding the 'source' fields.
100
+
101
+ Args:
102
+ port_spec_strings: A list of strings specifying the port-specific
103
+ components of a firewall rule. These are of the form
104
+ "(<protocol>)?(:<port>('-'<port>)?)?"
105
+
106
+ Returns:
107
+ A list of dict values containing a protocol string and a list
108
+ of port range strings. This is a substructure of the firewall
109
+ rule dictionaries, which additionally contain a 'source' field.
110
+
111
+ Raises:
112
+ ValueError: If any of the input strings are malformed.
113
+ """
114
+
115
+ def _AddToPortSpecs(protocol, port_string, port_specs):
116
+ """Ensure the specified rule for this protocol allows the given port(s).
117
+
118
+ If there is no port_string specified it implies all ports are allowed,
119
+ and whatever is in the port_specs map for that protocol get clobbered.
120
+ This method also makes sure that any protocol entry without a ports
121
+ member does not get further restricted.
122
+
123
+ Args:
124
+ protocol: The protocol under which the given port range is allowed.
125
+ port_string: The string specification of what ports are allowed.
126
+ port_specs: The mapping from protocols to firewall rules.
127
+ """
128
+ port_spec_entry = port_specs.setdefault(protocol,
129
+ {'IPProtocol': str(protocol),
130
+ 'ports': []})
131
+ if 'ports' in port_spec_entry:
132
+ # We only handle the 'then' case because in the other case the
133
+ # existing entry already allows all ports.
134
+ if not port_string:
135
+ # A missing 'ports' field indicates all ports are allowed.
136
+ port_spec_entry.pop('ports')
137
+ else:
138
+ port_spec_entry['ports'].append(port_string)
139
+
140
+ port_specs = {}
141
+ for port_spec_string in port_spec_strings:
142
+ protocol = None
143
+ port_string = None
144
+ parts = port_spec_string.split(':')
145
+
146
+ if len(parts) > 2:
147
+ raise ValueError('Invalid allowed entry: %s' %
148
+ port_spec_string)
149
+ elif len(parts) == 2:
150
+ if parts[0]:
151
+ protocol = utils.ParseProtocol(parts[0])
152
+ port_string = utils.ReplacePortNames(parts[1])
153
+ else:
154
+ protocol = utils.ParseProtocol(parts[0])
155
+
156
+ if protocol:
157
+ _AddToPortSpecs(protocol, port_string, port_specs)
158
+ else:
159
+ # Add entries for both UPD and TCP
160
+ _AddToPortSpecs(socket.getprotobyname('tcp'), port_string, port_specs)
161
+ _AddToPortSpecs(socket.getprotobyname('udp'), port_string, port_specs)
162
+
163
+ return port_specs.values()
164
+
165
+ def __init__(self, allowed, allowed_ip_sources):
166
+ self.port_specs = FirewallRules.ParsePortSpecs(allowed)
167
+ self.source_ranges = allowed_ip_sources
168
+ self.source_tags = []
169
+ self.target_tags = []
170
+
171
+ def SetTags(self, source_tags, target_tags):
172
+ self.source_tags = sorted(set(source_tags))
173
+ self.target_tags = sorted(set(target_tags))
174
+
175
+ def AddToFirewall(self, firewall):
176
+ if self.source_ranges:
177
+ firewall['sourceRanges'] = self.source_ranges
178
+ if self.source_tags:
179
+ firewall['sourceTags'] = self.source_tags
180
+ if self.target_tags:
181
+ firewall['targetTags'] = self.target_tags
182
+ firewall['allowed'] = self.port_specs
183
+
184
+
185
+ class AddFirewall(FirewallCommand):
186
+ """Create a new firewall rule to allow incoming traffic for
187
+ instances on a given network.
188
+ """
189
+
190
+ positional_args = '<firewall-name>'
191
+
192
+ def __init__(self, name, flag_values):
193
+ super(AddFirewall, self).__init__(name, flag_values)
194
+ flags.DEFINE_string('description',
195
+ '',
196
+ 'Firewall description',
197
+ flag_values=flag_values)
198
+ flags.DEFINE_string('network',
199
+ 'default',
200
+ 'Which network to apply the firewall to.',
201
+ flag_values=flag_values)
202
+ flags.DEFINE_list('allowed',
203
+ None,
204
+ 'The set of allowed ports for this firewall. A list of '
205
+ 'specifications of the form '
206
+ '"(<protocol>)?(\':\'<port>(\'-\'<port>)?)?" for allowing'
207
+ ' packets through the firewall. Examples: '
208
+ '"tcp:ssh", "udp:5000-6000", "tcp:80", or "icmp".',
209
+ flag_values=flag_values)
210
+ flags.DEFINE_list('allowed_ip_sources',
211
+ [],
212
+ 'The set of addresses allowed to talk to the '
213
+ 'protocols:ports listed in allowed (comma separated). '
214
+ 'If no ip or tag sources are listed, all sources '
215
+ 'will be allowed.',
216
+ flag_values=flag_values)
217
+ flags.DEFINE_list('allowed_tag_sources',
218
+ [],
219
+ 'The set of tagged instances allowed to talk to the '
220
+ 'protocols:ports listed in allowed (comma separated). '
221
+ 'If no tag or ip sources are listed, all sources will '
222
+ 'be allowed.',
223
+ flag_values=flag_values)
224
+ flags.DEFINE_list('target_tags',
225
+ [],
226
+ 'The set of tagged instances to apply the firewall to '
227
+ '(comma separated).',
228
+ flag_values=flag_values)
229
+
230
+ def Handle(self, firewall_name):
231
+ """Add the specified firewall.
232
+
233
+ Args:
234
+ firewall_name: The name of the firewall to add.
235
+
236
+ Returns:
237
+ The result of inserting the firewall.
238
+
239
+ Raises:
240
+ command_base.CommandError: If the passed flag values cannot be
241
+ interpreted.
242
+ """
243
+ if not self._flags.allowed:
244
+ raise command_base.CommandError(
245
+ 'You must specify at least one rule through --allowed.')
246
+
247
+ firewall_resource = {
248
+ 'kind': self._GetResourceApiKind('firewall'),
249
+ 'name': self.DenormalizeResourceName(firewall_name),
250
+ 'description': self._flags.description,
251
+ 'rules': []
252
+ }
253
+
254
+ if self._flags.network is not None:
255
+ firewall_resource['network'] = (self.NormalizeGlobalResourceName(
256
+ self._project,
257
+ 'networks',
258
+ self._flags.network))
259
+
260
+ if (not self._flags.allowed_ip_sources and
261
+ not self._flags.allowed_tag_sources):
262
+ self._flags.allowed_ip_sources.append('0.0.0.0/0')
263
+
264
+ try:
265
+ firewall_rules = FirewallRules(self._flags.allowed,
266
+ self._flags.allowed_ip_sources)
267
+ firewall_rules.SetTags(self._flags.allowed_tag_sources,
268
+ self._flags.target_tags)
269
+ firewall_rules.AddToFirewall(firewall_resource)
270
+ firewall_request = self._firewalls_api.insert(project=self._project,
271
+ body=firewall_resource)
272
+ return firewall_request.execute()
273
+ except ValueError, e:
274
+ raise command_base.CommandError(e)
275
+
276
+
277
+ class GetFirewall(FirewallCommand):
278
+ """Get a firewall."""
279
+
280
+ positional_args = '<firewall-name>'
281
+
282
+ def __init__(self, name, flag_values):
283
+ super(GetFirewall, self).__init__(name, flag_values)
284
+
285
+ def Handle(self, firewall_name):
286
+ """Get the specified firewall.
287
+
288
+ Args:
289
+ firewall_name: The name of the firewall to get.
290
+
291
+ Returns:
292
+ The result of getting the firewall.
293
+ """
294
+ firewall_request = self._firewalls_api.get(
295
+ project=self._project,
296
+ firewall=self.DenormalizeResourceName(firewall_name))
297
+
298
+ return firewall_request.execute()
299
+
300
+
301
+ class DeleteFirewall(FirewallCommand):
302
+ """Delete one or more firewall rules.
303
+
304
+ If multiple firewall names are specified, the firewalls will be deleted in
305
+ parallel.
306
+ """
307
+
308
+ positional_args = '<firewall-name-1> ... <firewall-name-n>'
309
+ safety_prompt = 'Delete firewall'
310
+
311
+ def __init__(self, name, flag_values):
312
+ super(DeleteFirewall, self).__init__(name, flag_values)
313
+
314
+ def Handle(self, *firewall_names):
315
+ """Delete the specified firewall.
316
+
317
+ Args:
318
+ *firewall_names: The names of the firewalls to delete.
319
+
320
+ Returns:
321
+ Tuple (results, exceptions) - results of deleting the firewalls.
322
+ """
323
+ requests = []
324
+ for name in firewall_names:
325
+ requests.append(self._firewalls_api.delete(
326
+ project=self._project,
327
+ firewall=self.DenormalizeResourceName(name)))
328
+ results, exceptions = self.ExecuteRequests(requests)
329
+ return (self.MakeListResult(results, 'operationList'), exceptions)
330
+
331
+
332
+ class ListFirewalls(FirewallCommand, command_base.GoogleComputeListCommand):
333
+ """List the firewall rules for a project."""
334
+
335
+ def ListFunc(self):
336
+ """Returns the function for listing firewalls."""
337
+ return self._firewalls_api.list
338
+
339
+
340
+ def AddCommands():
341
+ appcommands.AddCmd('addfirewall', AddFirewall)
342
+ appcommands.AddCmd('getfirewall', GetFirewall)
343
+ appcommands.AddCmd('deletefirewall', DeleteFirewall)
344
+ appcommands.AddCmd('listfirewalls', ListFirewalls)
@@ -0,0 +1,231 @@
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 firewall 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 firewall_cmds
31
+ from gcutil import mock_api
32
+
33
+ FLAGS = flags.FLAGS
34
+
35
+
36
+ class FirewallRulesTest(unittest.TestCase):
37
+ def testParsePortSpecs(self):
38
+ parse_port_specs = firewall_cmds.FirewallRules.ParsePortSpecs
39
+ self.assertRaises(ValueError, parse_port_specs, [''])
40
+ self.assertRaises(ValueError, parse_port_specs, ['foo'])
41
+ self.assertRaises(ValueError, parse_port_specs, ['foo:'])
42
+ self.assertRaises(ValueError, parse_port_specs, ['tcp:foo-bar'])
43
+ self.assertRaises(ValueError, parse_port_specs, ['tcp:http:https'])
44
+
45
+ self.assertEqual(parse_port_specs([]), [])
46
+ self.assertEqual(parse_port_specs(['tcp']),
47
+ [{'IPProtocol': '6'}])
48
+ self.assertEqual(parse_port_specs(['6']),
49
+ [{'IPProtocol': '6'}])
50
+ self.assertEqual(parse_port_specs(['tcp:80', 'tcp', 'tcp:ssh']),
51
+ [{'IPProtocol': '6'}])
52
+ self.assertEqual(parse_port_specs(['tcp:ssh']),
53
+ [{'IPProtocol': '6',
54
+ 'ports': ['22']}])
55
+ self.assertEqual(parse_port_specs([':ssh']),
56
+ [{'IPProtocol': '17',
57
+ 'ports': ['22']},
58
+ {'IPProtocol': '6',
59
+ 'ports': ['22']}])
60
+ self.assertEqual(parse_port_specs([':ssh']),
61
+ parse_port_specs(['udp:ssh', 'tcp:ssh']))
62
+ self.assertEqual(parse_port_specs([':ssh', 'tcp:80']),
63
+ [{'IPProtocol': '17',
64
+ 'ports': ['22']},
65
+ {'IPProtocol': '6',
66
+ 'ports': ['22', '80']}])
67
+
68
+
69
+ class FirewallCmdsTest(unittest.TestCase):
70
+
71
+ def _doAddFirewallGeneratesCorrectRequest(self, service_version,
72
+ allowed_ip_source):
73
+ flag_values = copy.deepcopy(FLAGS)
74
+
75
+ command = firewall_cmds.AddFirewall('addfirewall', flag_values)
76
+
77
+ expected_project = 'test_project'
78
+ expected_firewall = 'test_firewall'
79
+ submitted_network = 'test_network'
80
+ expected_description = 'test firewall'
81
+ flag_values.service_version = service_version
82
+ flag_values.project = expected_project
83
+ flag_values.description = expected_description
84
+ flag_values.network = submitted_network
85
+ flag_values.allowed = [':22']
86
+ if allowed_ip_source:
87
+ flag_values.allowed_ip_sources.append(allowed_ip_source)
88
+
89
+ command.SetFlags(flag_values)
90
+ command.SetApi(mock_api.MockApi())
91
+
92
+ expected_network = command.NormalizeGlobalResourceName(expected_project,
93
+ 'networks',
94
+ submitted_network)
95
+
96
+ result = command.Handle(expected_firewall)
97
+
98
+ self.assertEqual(result['project'], expected_project)
99
+
100
+ response_body = result['body']
101
+ self.assertEqual(response_body['name'], expected_firewall)
102
+ self.assertEqual(response_body['network'], expected_network)
103
+ self.assertEqual(response_body['description'], expected_description)
104
+
105
+ self.assertEqual(response_body['sourceRanges'],
106
+ [allowed_ip_source or '0.0.0.0/0'])
107
+ allowed = response_body['allowed']
108
+ self.assertEqual(len(allowed), 2)
109
+ used_protocols = set([x['IPProtocol'] for x in allowed])
110
+ self.assertEqual(used_protocols, set(['6', '17']))
111
+ self.assertEqual(allowed[0]['ports'], allowed[1]['ports'])
112
+ self.assertFalse('sourceTags' in response_body, response_body)
113
+ self.assertFalse('targetTags' in response_body, response_body)
114
+
115
+ def testAddFirewallGeneratesCorrectRequest(self):
116
+ for version in command_base.SUPPORTED_VERSIONS:
117
+ self._doAddFirewallGeneratesCorrectRequest(version, '10.10.10.10/0')
118
+
119
+ def testAddFirewallGeneratesCorrectRequestWithNoAllowedIpSource(self):
120
+ for version in command_base.SUPPORTED_VERSIONS:
121
+ self._doAddFirewallGeneratesCorrectRequest(version,
122
+ allowed_ip_source=None)
123
+
124
+ def testGetFirewallGeneratesCorrectRequest(self):
125
+ flag_values = copy.deepcopy(FLAGS)
126
+
127
+ command = firewall_cmds.GetFirewall('getfirewall', flag_values)
128
+
129
+ expected_project = 'test_project'
130
+ expected_firewall = 'test_firewall'
131
+ flag_values.project = expected_project
132
+
133
+ command.SetFlags(flag_values)
134
+ command.SetApi(mock_api.MockApi())
135
+
136
+ result = command.Handle(expected_firewall)
137
+
138
+ self.assertEqual(result['project'], expected_project)
139
+ self.assertEqual(result['firewall'], expected_firewall)
140
+
141
+ def testDeleteFirewallGeneratesCorrectRequest(self):
142
+ flag_values = copy.deepcopy(FLAGS)
143
+
144
+ command = firewall_cmds.DeleteFirewall('deletefirewall', flag_values)
145
+
146
+ expected_project = 'test_project'
147
+ expected_firewall = 'test_firewall'
148
+ flag_values.project = expected_project
149
+
150
+ command.SetFlags(flag_values)
151
+ command.SetApi(mock_api.MockApi())
152
+ command._credential = mock_api.MockCredential()
153
+
154
+ results, exceptions = command.Handle(expected_firewall)
155
+ self.assertEqual(exceptions, [])
156
+ self.assertEqual(len(results['items']), 1)
157
+ result = results['items'][0]
158
+
159
+ self.assertEqual(result['project'], expected_project)
160
+ self.assertEqual(result['firewall'], expected_firewall)
161
+
162
+ def testDeleteMultipleFirewalls(self):
163
+ flag_values = copy.deepcopy(FLAGS)
164
+ command = firewall_cmds.DeleteFirewall('deletefirewall', flag_values)
165
+
166
+ expected_project = 'test_project'
167
+ expected_firewalls = ['test-firewalls-%02d' % x for x in xrange(100)]
168
+ flag_values.project = expected_project
169
+
170
+ command.SetFlags(flag_values)
171
+ command.SetApi(mock_api.MockApi())
172
+ command._credential = mock_api.MockCredential()
173
+
174
+ results, exceptions = command.Handle(*expected_firewalls)
175
+ self.assertEqual(exceptions, [])
176
+ results = results['items']
177
+ self.assertEqual(len(results), len(expected_firewalls))
178
+
179
+ for expected_firewall, result in zip(expected_firewalls, results):
180
+ self.assertEqual(result['project'], expected_project)
181
+ self.assertEqual(result['firewall'], expected_firewall)
182
+
183
+ def testAddtFirewallsWithTagsGeneratesCorrectRequest(self):
184
+ flag_values = copy.deepcopy(FLAGS)
185
+
186
+ command = firewall_cmds.AddFirewall('addfirewall', flag_values)
187
+
188
+ expected_project = 'test_project'
189
+ expected_firewall = 'test_firewall'
190
+ submitted_network = 'test_network'
191
+ expected_description = 'test firewall'
192
+ expected_source_tags = ['a', 'b']
193
+ expected_target_tags = ['c', 'd']
194
+ flag_values.service_version = 'v1beta13'
195
+ flag_values.project = expected_project
196
+ flag_values.description = expected_description
197
+ flag_values.network = submitted_network
198
+ flag_values.allowed = [':22']
199
+ flag_values.allowed_tag_sources = expected_source_tags
200
+ flag_values.target_tags = expected_target_tags * 2 # Create duplicates
201
+
202
+ command.SetFlags(flag_values)
203
+ command.SetApi(mock_api.MockApi())
204
+
205
+ expected_network = command.NormalizeGlobalResourceName(expected_project,
206
+ 'networks',
207
+ submitted_network)
208
+
209
+ result = command.Handle(expected_firewall)
210
+
211
+ self.assertEqual(result['project'], expected_project)
212
+
213
+ response_body = result['body']
214
+ self.assertEqual(response_body['name'], expected_firewall)
215
+ self.assertEqual(response_body['network'], expected_network)
216
+ self.assertEqual(response_body['description'], expected_description)
217
+
218
+ allowed = response_body['allowed']
219
+ self.assertEqual(len(allowed), 2)
220
+ used_protocols = set([allowed[0]['IPProtocol'], allowed[1]['IPProtocol']])
221
+ self.assertEqual(used_protocols, set(['6', '17']))
222
+ self.assertEqual(allowed[0]['ports'], allowed[1]['ports'])
223
+ self.assertEqual(allowed[0]['ports'], ['22'])
224
+ self.assertTrue('sourceTags' in response_body)
225
+ self.assertTrue('targetTags' in response_body)
226
+ self.assertEqual(response_body['sourceTags'], expected_source_tags)
227
+ self.assertEqual(response_body['targetTags'], expected_target_tags)
228
+
229
+
230
+ if __name__ == '__main__':
231
+ unittest.main()