gcloud 0.0.2 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +2 -3
- data/CHANGELOG +4 -0
- data/LICENSE +674 -0
- data/Manifest +111 -0
- data/README.md +4 -3
- data/bin/gcutil +53 -0
- data/gcloud.gemspec +4 -3
- data/packages/gcutil-1.7.1/CHANGELOG +197 -0
- data/packages/gcutil-1.7.1/LICENSE +202 -0
- data/packages/gcutil-1.7.1/VERSION +1 -0
- data/packages/gcutil-1.7.1/gcutil +53 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/LICENSE +23 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/__init__.py +1 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/discovery.py +743 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/errors.py +123 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/ext/__init__.py +0 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/http.py +1443 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/mimeparse.py +172 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/model.py +385 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/schema.py +303 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/__init__.py +1 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/anyjson.py +32 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/appengine.py +528 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/client.py +1139 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/clientsecrets.py +105 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/crypt.py +244 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/django_orm.py +124 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/file.py +107 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/locked_file.py +343 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/multistore_file.py +379 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/tools.py +174 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/uritemplate/__init__.py +147 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/LICENSE +202 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/__init__.py +3 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/__init__.py +3 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/app.py +356 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/appcommands.py +783 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/basetest.py +1260 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/datelib.py +421 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/debug.py +60 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/file_util.py +181 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/resources.py +67 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/run_script_module.py +217 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/setup_command.py +159 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/shellutil.py +49 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/stopwatch.py +204 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/__init__.py +0 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auth_helper.py +140 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auth_helper_test.py +149 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auto_auth.py +130 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auto_auth_test.py +75 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/basic_cmds.py +128 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/basic_cmds_test.py +111 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/command_base.py +1808 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/command_base_test.py +1651 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/compute/v1beta13.json +2851 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/compute/v1beta14.json +3361 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/disk_cmds.py +342 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/disk_cmds_test.py +474 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/firewall_cmds.py +344 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/firewall_cmds_test.py +231 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/flags_cache.py +274 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/gcutil +89 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/gcutil_logging.py +69 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/image_cmds.py +262 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/image_cmds_test.py +172 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/instance_cmds.py +1506 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/instance_cmds_test.py +1904 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/kernel_cmds.py +91 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/kernel_cmds_test.py +56 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/machine_type_cmds.py +106 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/machine_type_cmds_test.py +59 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/metadata.py +96 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/metadata_lib.py +357 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/metadata_test.py +84 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/mock_api.py +420 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/mock_metadata.py +58 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/move_cmds.py +824 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/move_cmds_test.py +307 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/network_cmds.py +178 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/network_cmds_test.py +133 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/operation_cmds.py +181 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/operation_cmds_test.py +196 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/path_initializer.py +38 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/project_cmds.py +173 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/project_cmds_test.py +111 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/scopes.py +61 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/scopes_test.py +50 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/snapshot_cmds.py +276 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/snapshot_cmds_test.py +260 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/ssh_keys.py +266 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/ssh_keys_test.py +128 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/table_formatter.py +563 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/thread_pool.py +188 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/thread_pool_test.py +88 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/utils.py +208 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/utils_test.py +193 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/version.py +17 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/version_checker.py +246 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/version_checker_test.py +271 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/zone_cmds.py +151 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/zone_cmds_test.py +60 -0
- data/packages/gcutil-1.7.1/lib/httplib2/LICENSE +21 -0
- data/packages/gcutil-1.7.1/lib/httplib2/httplib2/__init__.py +1630 -0
- data/packages/gcutil-1.7.1/lib/httplib2/httplib2/cacerts.txt +714 -0
- data/packages/gcutil-1.7.1/lib/httplib2/httplib2/iri2uri.py +110 -0
- data/packages/gcutil-1.7.1/lib/httplib2/httplib2/socks.py +438 -0
- data/packages/gcutil-1.7.1/lib/iso8601/LICENSE +20 -0
- data/packages/gcutil-1.7.1/lib/iso8601/iso8601/__init__.py +1 -0
- data/packages/gcutil-1.7.1/lib/iso8601/iso8601/iso8601.py +102 -0
- data/packages/gcutil-1.7.1/lib/iso8601/iso8601/test_iso8601.py +111 -0
- data/packages/gcutil-1.7.1/lib/python_gflags/AUTHORS +2 -0
- data/packages/gcutil-1.7.1/lib/python_gflags/LICENSE +28 -0
- data/packages/gcutil-1.7.1/lib/python_gflags/gflags.py +2862 -0
- data/packages/gcutil-1.7.1/lib/python_gflags/gflags2man.py +544 -0
- data/packages/gcutil-1.7.1/lib/python_gflags/gflags_validators.py +187 -0
- metadata +118 -5
- metadata.gz.sig +0 -0
@@ -0,0 +1,274 @@
|
|
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
|
+
"""Cache of previously used flag values."""
|
16
|
+
|
17
|
+
from __future__ import with_statement
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
import copy
|
22
|
+
import os
|
23
|
+
|
24
|
+
import gflags as flags
|
25
|
+
from gcutil import gcutil_logging
|
26
|
+
|
27
|
+
FLAGS = flags.FLAGS
|
28
|
+
LOGGER = gcutil_logging.LOGGER
|
29
|
+
|
30
|
+
flags.DEFINE_bool(
|
31
|
+
'cache_flag_values',
|
32
|
+
False,
|
33
|
+
'If true, cache all specified flag values in the file specified '
|
34
|
+
'by the "cached_flags_file" flag.')
|
35
|
+
flags.DEFINE_string(
|
36
|
+
'cached_flags_file',
|
37
|
+
'.gcutil.flags',
|
38
|
+
'File storing a cache of gcutil flag values. If the name does not '
|
39
|
+
'contain a path separator it will be searched in the current working '
|
40
|
+
'directory and up to "/", as well as the user\'s home directory. '
|
41
|
+
'The first matching file will be used and no merging is done upstream. '
|
42
|
+
'Use the "cache_flag_values" flag to persist the current flags.')
|
43
|
+
|
44
|
+
|
45
|
+
class FlagsCache(object):
|
46
|
+
"""File based cache of values for flags with user-specific defaults."""
|
47
|
+
|
48
|
+
def __init__(self, cache_file_name=None, open_function=open, os_module=os):
|
49
|
+
"""Constructor.
|
50
|
+
|
51
|
+
Args:
|
52
|
+
cache_file_name: (str) optional path of the flags cache file (default
|
53
|
+
is FLAGS.cached_flags_file).
|
54
|
+
open_function: (function) used to open a file (overriden in tests).
|
55
|
+
os_module: (module) used to perform OS operations (overriden in testsa).
|
56
|
+
"""
|
57
|
+
self._open = open_function
|
58
|
+
self._os = os_module
|
59
|
+
self.cache_file_path = FlagsCache._FindFlagsCacheFile(
|
60
|
+
cache_file_name or FLAGS.cached_flags_file, self._os)
|
61
|
+
if self._os.path.exists(self.cache_file_path):
|
62
|
+
LOGGER.debug('Found flag cache file: %s', self.cache_file_path)
|
63
|
+
with self._open(self.cache_file_path) as cache_file:
|
64
|
+
self.cache_string = cache_file.read()
|
65
|
+
else:
|
66
|
+
self.cache_string = ''
|
67
|
+
|
68
|
+
self._serialized_flags = None
|
69
|
+
|
70
|
+
@staticmethod
|
71
|
+
def _FindFlagsCacheFile(name, os_module):
|
72
|
+
"""Returns the full path to the flags cache file.
|
73
|
+
|
74
|
+
If the name contains a file separator or a user expander ('~'), then
|
75
|
+
its full expanded path is returned. Otherwise name is searched in
|
76
|
+
the current working directory and recursively up, as well as in the
|
77
|
+
user's home directory. If an existing flags cache file cannot be found,
|
78
|
+
then the full path to the config file in the user's home directory is
|
79
|
+
returned so that it can be optionally created.
|
80
|
+
|
81
|
+
Args:
|
82
|
+
name: (string) the name of the file to search.
|
83
|
+
os_module: (module) used to perform OS operations.
|
84
|
+
Returns:
|
85
|
+
(string) the path to an existing or expected cache flag file, or the
|
86
|
+
empty string if name is None or empty.
|
87
|
+
"""
|
88
|
+
if not name:
|
89
|
+
return ''
|
90
|
+
|
91
|
+
name = os_module.path.expanduser(name)
|
92
|
+
|
93
|
+
if os_module.path.isdir(name):
|
94
|
+
gcutil_flags = '.gcutil.flags'
|
95
|
+
return os_module.path.join(name, gcutil_flags)
|
96
|
+
elif os_module.path.dirname(name):
|
97
|
+
# name contains a path separator.
|
98
|
+
return os_module.path.realpath(name)
|
99
|
+
|
100
|
+
# Search for the flags cache file up the directory path.
|
101
|
+
directory = os_module.path.realpath(os_module.getcwd())
|
102
|
+
while directory:
|
103
|
+
filename = os_module.path.join(directory, name)
|
104
|
+
if os_module.path.exists(filename):
|
105
|
+
return filename
|
106
|
+
parent = os_module.path.dirname(directory)
|
107
|
+
if parent == directory:
|
108
|
+
directory = None
|
109
|
+
else:
|
110
|
+
directory = parent
|
111
|
+
|
112
|
+
# Use the flags cache file in the home directory.
|
113
|
+
return os_module.path.realpath(os_module.path.expanduser(
|
114
|
+
os_module.path.join('~', name)))
|
115
|
+
|
116
|
+
@staticmethod
|
117
|
+
def _GetCacheableFlagValues(flag_values):
|
118
|
+
"""Get the subset of flags that are appropriate to cache.
|
119
|
+
|
120
|
+
All non-duplicate flags excluding --cache_flag_values and
|
121
|
+
--cached_flags_file are eligible for caching.
|
122
|
+
|
123
|
+
Args:
|
124
|
+
flag_values: The superset FlagValues object.
|
125
|
+
Returns:
|
126
|
+
A subset FlagValues object that contains only the cacheable flags.
|
127
|
+
"""
|
128
|
+
cacheable_flag_values = flags.FlagValues()
|
129
|
+
for name, flag in flag_values.FlagDict().iteritems():
|
130
|
+
# We only process the flag if seen by its full name (not short_name).
|
131
|
+
if (name == flag.name and
|
132
|
+
not name in ['cache_flag_values', 'cached_flags_file'] and
|
133
|
+
not name in cacheable_flag_values and
|
134
|
+
not flag.short_name in cacheable_flag_values):
|
135
|
+
cacheable_flag_values[name] = flag
|
136
|
+
|
137
|
+
return cacheable_flag_values
|
138
|
+
|
139
|
+
@staticmethod
|
140
|
+
def _GetCachedFlagValues(flag_values, cache_string):
|
141
|
+
"""Get the values for cacheable flags from the given cache string.
|
142
|
+
|
143
|
+
Any flags in the parsed_flags argument will be omitted regardless of
|
144
|
+
whether or not they are in the cache_string. This allows cached and
|
145
|
+
parsed flags to be combined without conflict.
|
146
|
+
|
147
|
+
Args:
|
148
|
+
flag_values: A FlagValues instance defining the cacheable flags.
|
149
|
+
cache_string: The contents of the cache as a newline delimited string.
|
150
|
+
Returns:
|
151
|
+
A FlagValues instance containing the flags present in the cache.
|
152
|
+
"""
|
153
|
+
# We don't want to inadvertantly overwrite the parsed members of the
|
154
|
+
# cacheable_flags, so we make a deep copy of it before appending.
|
155
|
+
flag_values_copy = copy.deepcopy(flag_values)
|
156
|
+
|
157
|
+
# Clear flags to load cache into clean state.
|
158
|
+
for _, flag in flag_values_copy.FlagDict().iteritems():
|
159
|
+
flag.present = 0
|
160
|
+
flag.value = None
|
161
|
+
|
162
|
+
cached_flag_values = flags.FlagValues()
|
163
|
+
cached_flag_values.AppendFlagValues(flag_values_copy)
|
164
|
+
undefok = []
|
165
|
+
cache_entries = cache_string.split('\n')
|
166
|
+
while cache_entries:
|
167
|
+
try:
|
168
|
+
argv = (['dummy_command', '--undefok=\'%s\'' % ','.join(undefok)] +
|
169
|
+
cache_entries)
|
170
|
+
cache_entries = cached_flag_values(argv)[2:]
|
171
|
+
except flags.UnrecognizedFlagError, err:
|
172
|
+
undefok.append(err.flagname)
|
173
|
+
return cached_flag_values
|
174
|
+
|
175
|
+
@staticmethod
|
176
|
+
def _UnifyProjectFlags(flags, warn=False):
|
177
|
+
"""Unifies --project and --project_id flags in the flag value set.
|
178
|
+
|
179
|
+
Args:
|
180
|
+
flags: A FlagValues instance with the flags to unify.
|
181
|
+
warn: If True, log warning if project_id is encountered.
|
182
|
+
"""
|
183
|
+
if 'project_id' in flags and 'project' in flags:
|
184
|
+
project_id = flags['project_id']
|
185
|
+
project = flags['project']
|
186
|
+
if project_id.present:
|
187
|
+
if not project.present:
|
188
|
+
if warn:
|
189
|
+
LOGGER.warning('--project_id is deprecated, please use --project')
|
190
|
+
project.present = project_id.present
|
191
|
+
project.value = project_id.value
|
192
|
+
elif warn:
|
193
|
+
LOGGER.warning('--project_id and --project provided. '
|
194
|
+
'--project_id is deprecated, using value of '
|
195
|
+
'--project.')
|
196
|
+
project_id.present = 0
|
197
|
+
project_id.value = None
|
198
|
+
|
199
|
+
@staticmethod
|
200
|
+
def _ApplyCachedFlags(cacheable, cached):
|
201
|
+
"""Applies cached values to the flags in cacheable flag set.
|
202
|
+
|
203
|
+
Only flags that are not themselves present are updated with the
|
204
|
+
cached value. Returns flags whose value is present, either by
|
205
|
+
user specifying them at command line (cacheable) or by having been
|
206
|
+
loaded from cache (cached).
|
207
|
+
|
208
|
+
Args:
|
209
|
+
cacheable: flags whose value can be cached (and whose values will be
|
210
|
+
updated from cache if value not present)
|
211
|
+
cache: flags loaded from the cache.
|
212
|
+
|
213
|
+
Returns:
|
214
|
+
FlagValues object which contains all present flags
|
215
|
+
"""
|
216
|
+
canonical = flags.FlagValues()
|
217
|
+
for name, flag in cacheable.FlagDict().iteritems():
|
218
|
+
if flag.name == name:
|
219
|
+
if not flag.present:
|
220
|
+
cached_flag = cached[name]
|
221
|
+
if cached_flag.present:
|
222
|
+
LOGGER.debug('Flag override from cache file: %s -> %s',
|
223
|
+
repr(name), repr(cached_flag.value))
|
224
|
+
flag.present = cached_flag.present
|
225
|
+
flag.value = cached_flag.value
|
226
|
+
|
227
|
+
if flag.present:
|
228
|
+
canonical[name] = flag
|
229
|
+
return canonical
|
230
|
+
|
231
|
+
def UpdateCacheFile(self, update_cache=None):
|
232
|
+
"""Updates the flags cache file.
|
233
|
+
|
234
|
+
This method assumes that SynchronizeFlags() has been called. If
|
235
|
+
the assumption is violated, this method will produce a DEBUG log
|
236
|
+
message and return.
|
237
|
+
|
238
|
+
Args:
|
239
|
+
update_cache: If True, updates the cache file. This is for testing.
|
240
|
+
"""
|
241
|
+
if self._serialized_flags is None:
|
242
|
+
LOGGER.debug('Flags cache cannot be updated before synchronizing flags.')
|
243
|
+
return
|
244
|
+
|
245
|
+
if update_cache or FLAGS.cache_flag_values:
|
246
|
+
with self._open(self.cache_file_path, 'w') as cache_file:
|
247
|
+
cache_file.write(self._serialized_flags)
|
248
|
+
|
249
|
+
def SynchronizeFlags(self, flag_values=None):
|
250
|
+
"""Synchronize the given FlagValues instance with this cache.
|
251
|
+
|
252
|
+
This updates the FlagValues instance with values for any unparsed flags if
|
253
|
+
they have an entry in the cache.
|
254
|
+
|
255
|
+
Args:
|
256
|
+
flag_values: The FlagValues instance to synchronized. If not specified,
|
257
|
+
then the global FlagValues instance is used.
|
258
|
+
Returns:
|
259
|
+
The synchronized FlagValues instance.
|
260
|
+
"""
|
261
|
+
if not flag_values:
|
262
|
+
flag_values = FLAGS
|
263
|
+
# update_cache will be set to a boolean value, so we have to explicitly
|
264
|
+
# check if it is None rather than relying on the implicit false behavior.
|
265
|
+
|
266
|
+
cacheable = FlagsCache._GetCacheableFlagValues(flag_values)
|
267
|
+
cached = FlagsCache._GetCachedFlagValues(cacheable, self.cache_string)
|
268
|
+
|
269
|
+
FlagsCache._UnifyProjectFlags(cacheable, True)
|
270
|
+
FlagsCache._UnifyProjectFlags(cached)
|
271
|
+
|
272
|
+
canonical = FlagsCache._ApplyCachedFlags(cacheable, cached)
|
273
|
+
self._serialized_flags = canonical.FlagsIntoString()
|
274
|
+
return flag_values
|
@@ -0,0 +1,89 @@
|
|
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
|
+
"""Command line tool for interacting with Google Compute Engine.
|
18
|
+
|
19
|
+
Please refer to http://developers.google.com/compute/docs/gcutil/tips for
|
20
|
+
more information about gcutil usage.
|
21
|
+
"""
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
import path_initializer
|
26
|
+
path_initializer.InitializeSysPath()
|
27
|
+
|
28
|
+
import atexit
|
29
|
+
import logging
|
30
|
+
import os
|
31
|
+
import sys
|
32
|
+
|
33
|
+
|
34
|
+
from google.apputils import appcommands
|
35
|
+
import gflags as flags
|
36
|
+
|
37
|
+
from gcutil import basic_cmds
|
38
|
+
from gcutil import disk_cmds
|
39
|
+
from gcutil import firewall_cmds
|
40
|
+
from gcutil import image_cmds
|
41
|
+
from gcutil import instance_cmds
|
42
|
+
from gcutil import kernel_cmds
|
43
|
+
from gcutil import machine_type_cmds
|
44
|
+
from gcutil import move_cmds
|
45
|
+
from gcutil import network_cmds
|
46
|
+
from gcutil import operation_cmds
|
47
|
+
from gcutil import project_cmds
|
48
|
+
from gcutil import snapshot_cmds
|
49
|
+
from gcutil import version_checker
|
50
|
+
from gcutil import zone_cmds
|
51
|
+
|
52
|
+
|
53
|
+
FLAGS = flags.FLAGS
|
54
|
+
|
55
|
+
# This utility will often be run in a VM and the local web server
|
56
|
+
# behavior can be annoying there.
|
57
|
+
FLAGS.SetDefault('auth_local_webserver', False)
|
58
|
+
|
59
|
+
|
60
|
+
def main(unused_argv):
|
61
|
+
# The real work is performed by the appcommands.Run() method, which
|
62
|
+
# first invokes this method, and then runs the specified command.
|
63
|
+
|
64
|
+
# Set up early logging configuration
|
65
|
+
format_string = '%(levelname)s: %(message)s'
|
66
|
+
logging.basicConfig(stream=sys.stderr, format=format_string)
|
67
|
+
|
68
|
+
# Next, register all the commands.
|
69
|
+
basic_cmds.AddCommands()
|
70
|
+
disk_cmds.AddCommands()
|
71
|
+
firewall_cmds.AddCommands()
|
72
|
+
image_cmds.AddCommands()
|
73
|
+
instance_cmds.AddCommands()
|
74
|
+
kernel_cmds.AddCommands()
|
75
|
+
machine_type_cmds.AddCommands()
|
76
|
+
move_cmds.AddCommands()
|
77
|
+
network_cmds.AddCommands()
|
78
|
+
operation_cmds.AddCommands()
|
79
|
+
project_cmds.AddCommands()
|
80
|
+
snapshot_cmds.AddCommands()
|
81
|
+
zone_cmds.AddCommands()
|
82
|
+
|
83
|
+
|
84
|
+
# Registers the version checker.
|
85
|
+
vc = version_checker.VersionChecker()
|
86
|
+
atexit.register(vc.CheckForNewVersion)
|
87
|
+
|
88
|
+
if __name__ == '__main__':
|
89
|
+
appcommands.Run()
|
@@ -0,0 +1,69 @@
|
|
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
|
+
"""Common code for logging across gcutil."""
|
16
|
+
|
17
|
+
import logging
|
18
|
+
|
19
|
+
import gflags as flags
|
20
|
+
|
21
|
+
FLAGS = flags.FLAGS
|
22
|
+
|
23
|
+
_LOG_ROOT = 'gcutil-logs'
|
24
|
+
LOGGER = logging.getLogger(_LOG_ROOT)
|
25
|
+
|
26
|
+
CRITICAL = logging.CRITICAL
|
27
|
+
FATAL = logging.FATAL
|
28
|
+
ERROR = logging.ERROR
|
29
|
+
WARNING = logging.WARNING
|
30
|
+
WARN = logging.WARN
|
31
|
+
INFO = logging.INFO
|
32
|
+
DEBUG = logging.DEBUG
|
33
|
+
|
34
|
+
_LOG_LEVELS = (DEBUG, INFO, WARNING, ERROR, CRITICAL)
|
35
|
+
_LOG_LEVEL_NAMES = tuple(map(logging.getLevelName, _LOG_LEVELS))
|
36
|
+
|
37
|
+
|
38
|
+
flags.DEFINE_enum(
|
39
|
+
'log_level',
|
40
|
+
logging.getLevelName(logging.INFO),
|
41
|
+
_LOG_LEVEL_NAMES,
|
42
|
+
'Logging output level for core Google Compute Engine messages. '
|
43
|
+
'For logging output from other libraries, use library_log_level.')
|
44
|
+
flags.DEFINE_enum(
|
45
|
+
'library_log_level',
|
46
|
+
logging.getLevelName(logging.WARN),
|
47
|
+
_LOG_LEVEL_NAMES,
|
48
|
+
'Logging output level for libraries.')
|
49
|
+
|
50
|
+
|
51
|
+
def SetupLogging():
|
52
|
+
"""Set up a logger that will have its own logging level."""
|
53
|
+
gc_handler = logging.StreamHandler()
|
54
|
+
gc_handler.setFormatter(logging.Formatter('%(levelname)s: %(message)s'))
|
55
|
+
LOGGER.addHandler(gc_handler)
|
56
|
+
LOGGER.propagate = False
|
57
|
+
|
58
|
+
log_level_map = dict(
|
59
|
+
[(logging.getLevelName(level), level) for level in _LOG_LEVELS])
|
60
|
+
|
61
|
+
# Update library_log_level to INFO if user wants to see
|
62
|
+
# dump_request_response.
|
63
|
+
if FLAGS.dump_request_response:
|
64
|
+
if (not FLAGS['library_log_level'].present and
|
65
|
+
not logging.getLogger().isEnabledFor(logging.INFO)):
|
66
|
+
FLAGS.library_log_level = 'INFO'
|
67
|
+
|
68
|
+
LOGGER.setLevel(log_level_map[FLAGS.log_level])
|
69
|
+
logging.getLogger().setLevel(log_level_map[FLAGS.library_log_level])
|
@@ -0,0 +1,262 @@
|
|
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 machine images."""
|
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
|
+
|
31
|
+
class ImageCommand(command_base.GoogleComputeCommand):
|
32
|
+
"""Base command for working with the images collection."""
|
33
|
+
|
34
|
+
default_sort_field = 'name'
|
35
|
+
summary_fields = (('name', 'name'),
|
36
|
+
('description', 'description'),
|
37
|
+
('creation-time', 'creationTimestamp'),
|
38
|
+
('kernel', 'preferredKernel'))
|
39
|
+
|
40
|
+
detail_fields = (('name', 'name'),
|
41
|
+
('description', 'description'),
|
42
|
+
('creation-time', 'creationTimestamp'),
|
43
|
+
('kernel', 'preferredKernel'))
|
44
|
+
|
45
|
+
resource_collection_name = 'images'
|
46
|
+
|
47
|
+
def __init__(self, name, flag_values):
|
48
|
+
super(ImageCommand, 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
|
+
self._images_api = api.images()
|
60
|
+
self._kernels_api = api.kernels()
|
61
|
+
|
62
|
+
|
63
|
+
class AddImage(ImageCommand):
|
64
|
+
"""Create a new machine image.
|
65
|
+
|
66
|
+
The root_source_tarball parameter must point to a tar file of the
|
67
|
+
contents of the desired root directory stored in Google Storage.
|
68
|
+
"""
|
69
|
+
|
70
|
+
positional_args = '<image-name> <root-source-tarball>'
|
71
|
+
|
72
|
+
def __init__(self, name, flag_values):
|
73
|
+
super(AddImage, self).__init__(name, flag_values)
|
74
|
+
flags.DEFINE_string('description',
|
75
|
+
'',
|
76
|
+
'Image description',
|
77
|
+
flag_values=flag_values)
|
78
|
+
flags.DEFINE_string('preferred_kernel',
|
79
|
+
None,
|
80
|
+
'Kernel name',
|
81
|
+
flag_values=flag_values)
|
82
|
+
|
83
|
+
def Handle(self, image_name, root_source_tarball):
|
84
|
+
"""Add the specified image.
|
85
|
+
|
86
|
+
Args:
|
87
|
+
image_name: The name of the image to add.
|
88
|
+
root_source_tarball: Tarball in Google Storage containing the
|
89
|
+
desired root directory for the resulting image.
|
90
|
+
|
91
|
+
Returns:
|
92
|
+
The result of inserting the image.
|
93
|
+
"""
|
94
|
+
|
95
|
+
# Accept gs:// URLs.
|
96
|
+
if root_source_tarball.startswith('gs://'):
|
97
|
+
root_source_tarball = ('http://storage.googleapis.com/' +
|
98
|
+
root_source_tarball[len('gs://'):])
|
99
|
+
|
100
|
+
image_resource = {
|
101
|
+
'kind': self._GetResourceApiKind('image'),
|
102
|
+
'name': self.DenormalizeResourceName(image_name),
|
103
|
+
'description': self._flags.description,
|
104
|
+
'sourceType': 'RAW',
|
105
|
+
'rawDisk': {
|
106
|
+
'source': root_source_tarball,
|
107
|
+
'containerType': 'TAR'
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
if self._flags.preferred_kernel:
|
112
|
+
image_resource['preferredKernel'] = self.NormalizeGlobalResourceName(
|
113
|
+
self._project, 'kernels', self._flags.preferred_kernel)
|
114
|
+
elif self._IsUsingAtLeastApiVersion('v1beta14'):
|
115
|
+
kernel = self._PromptForKernel()
|
116
|
+
image_resource['preferredKernel'] = kernel['selfLink']
|
117
|
+
image_request = self._images_api.insert(project=self._project,
|
118
|
+
body=image_resource)
|
119
|
+
return image_request.execute()
|
120
|
+
|
121
|
+
|
122
|
+
class GetImage(ImageCommand):
|
123
|
+
"""Get a machine image."""
|
124
|
+
|
125
|
+
positional_args = '<image-name>'
|
126
|
+
|
127
|
+
def __init__(self, name, flag_values):
|
128
|
+
super(GetImage, self).__init__(name, flag_values)
|
129
|
+
|
130
|
+
def Handle(self, image_name):
|
131
|
+
"""GSet the specified image.
|
132
|
+
|
133
|
+
Args:
|
134
|
+
image_name: The name of the image to get.
|
135
|
+
|
136
|
+
Returns:
|
137
|
+
The result of getting the image.
|
138
|
+
"""
|
139
|
+
image_request = self._images_api.get(
|
140
|
+
project=self._project,
|
141
|
+
image=self.DenormalizeResourceName(image_name))
|
142
|
+
|
143
|
+
return image_request.execute()
|
144
|
+
|
145
|
+
|
146
|
+
class DeleteImage(ImageCommand):
|
147
|
+
"""Delete one or more machine images.
|
148
|
+
|
149
|
+
If multiple image names are specified, the images will be deleted in parallel.
|
150
|
+
"""
|
151
|
+
|
152
|
+
positional_args = '<image-name-1> ... <image-name-n>'
|
153
|
+
safety_prompt = 'Delete image'
|
154
|
+
|
155
|
+
def __init__(self, name, flag_values):
|
156
|
+
super(DeleteImage, self).__init__(name, flag_values)
|
157
|
+
|
158
|
+
def Handle(self, *image_names):
|
159
|
+
"""Delete the specified images.
|
160
|
+
|
161
|
+
Args:
|
162
|
+
*image_names: The names of the images to delete.
|
163
|
+
|
164
|
+
Returns:
|
165
|
+
Tuple (results, exceptions) - results of deleting the images.
|
166
|
+
"""
|
167
|
+
requests = []
|
168
|
+
for name in image_names:
|
169
|
+
requests.append(self._images_api.delete(
|
170
|
+
project=self._project,
|
171
|
+
image=self.DenormalizeResourceName(name)))
|
172
|
+
results, exceptions = self.ExecuteRequests(requests)
|
173
|
+
return (self.MakeListResult(results, 'operationList'), exceptions)
|
174
|
+
|
175
|
+
|
176
|
+
class ListImages(ImageCommand, command_base.GoogleComputeListCommand):
|
177
|
+
"""List the images for a project."""
|
178
|
+
|
179
|
+
def ListFunc(self):
|
180
|
+
"""Returns the function for listing images."""
|
181
|
+
return self._images_api.list
|
182
|
+
|
183
|
+
|
184
|
+
class Deprecate(ImageCommand):
|
185
|
+
"""Sets the deprecation status for an image."""
|
186
|
+
|
187
|
+
positional_args = '<image-name>'
|
188
|
+
|
189
|
+
def __init__(self, name, flag_values):
|
190
|
+
super(Deprecate, self).__init__(name, flag_values)
|
191
|
+
flags.DEFINE_enum('state',
|
192
|
+
None,
|
193
|
+
['DEPRECATED', 'OBSOLETE', 'DELETED'],
|
194
|
+
'The new deprecation state for this image. '
|
195
|
+
'Valid values are DEPRECATED, OBSOLETE, and '
|
196
|
+
'DELETED. DEPRECATED resources will generate '
|
197
|
+
'a warning when new uses occur, OBSOLETE '
|
198
|
+
'and DELETED resources generate an error on '
|
199
|
+
'new uses.',
|
200
|
+
flag_values=flag_values)
|
201
|
+
flags.DEFINE_string('replacement',
|
202
|
+
None,
|
203
|
+
'A valid full URL to a compute engine image. '
|
204
|
+
'Users of the deprecated image will be advised '
|
205
|
+
'to switch to this replacement.',
|
206
|
+
flag_values=flag_values)
|
207
|
+
flags.DEFINE_string('deprecated_on',
|
208
|
+
None,
|
209
|
+
'A valid RFC 3339 full-date or date-time on which '
|
210
|
+
'the state of this resource became or will become '
|
211
|
+
'DEPRECATED. For example: 2020-01-02T00:00:00Z for '
|
212
|
+
'midnight on January 2nd, 2020.',
|
213
|
+
flag_values=flag_values)
|
214
|
+
flags.DEFINE_string('obsolete_on',
|
215
|
+
None,
|
216
|
+
'A valid RFC 3339 full-date or date-time on which '
|
217
|
+
'the state of this resource became or will become '
|
218
|
+
'OBSOLETE. For example: 2020-01-02T00:00:00Z for '
|
219
|
+
'midnight on January 2nd, 2020.',
|
220
|
+
flag_values=flag_values)
|
221
|
+
flags.DEFINE_string('deleted_on',
|
222
|
+
None,
|
223
|
+
'A valid RFC 3339 full-date or date-time on which '
|
224
|
+
'the state of this resource became or will become '
|
225
|
+
'DELETED. For example: 2020-01-02T00:00:00Z for '
|
226
|
+
'midnight on January 2nd, 2020.',
|
227
|
+
flag_values=flag_values)
|
228
|
+
|
229
|
+
def _BuildRequest(self, image_name):
|
230
|
+
"""Build a request to set deprecation status for the given image."""
|
231
|
+
deprecation_status = {
|
232
|
+
'state': self._flags.state,
|
233
|
+
'replacement': self.NormalizeGlobalResourceName(
|
234
|
+
self._project, 'images', self._flags.replacement),
|
235
|
+
'deprecated': self._flags.deprecated_on,
|
236
|
+
'obsolete': self._flags.obsolete_on,
|
237
|
+
'deleted': self._flags.deleted_on,
|
238
|
+
}
|
239
|
+
return self._images_api.deprecate(
|
240
|
+
project=self._project,
|
241
|
+
image=self.DenormalizeResourceName(image_name),
|
242
|
+
body=deprecation_status)
|
243
|
+
|
244
|
+
def Handle(self, image_name):
|
245
|
+
"""Sets deprecation status on an image.
|
246
|
+
|
247
|
+
Args:
|
248
|
+
image_name: the name of the image for which deprecation will be set.
|
249
|
+
|
250
|
+
Returns:
|
251
|
+
An operation resource.
|
252
|
+
"""
|
253
|
+
set_deprecation_request = self._BuildRequest(image_name)
|
254
|
+
return set_deprecation_request.execute()
|
255
|
+
|
256
|
+
|
257
|
+
def AddCommands():
|
258
|
+
appcommands.AddCmd('addimage', AddImage)
|
259
|
+
appcommands.AddCmd('getimage', GetImage)
|
260
|
+
appcommands.AddCmd('deleteimage', DeleteImage)
|
261
|
+
appcommands.AddCmd('listimages', ListImages)
|
262
|
+
appcommands.AddCmd('deprecateimage', Deprecate)
|