Merge lp:~harlowja/cloud-init/query-back-duo into lp:~cloud-init-dev/cloud-init/trunk

Proposed by Joshua Harlow
Status: Rejected
Rejected by: Chad Smith
Proposed branch: lp:~harlowja/cloud-init/query-back-duo
Merge into: lp:~cloud-init-dev/cloud-init/trunk
Diff against target: 182 lines (+75/-21)
3 files modified
bin/cloud-init (+70/-13)
cloudinit/sources/__init__.py (+0/-4)
cloudinit/stages.py (+5/-4)
To merge this branch: bzr merge lp:~harlowja/cloud-init/query-back-duo
Reviewer Review Type Date Requested Status
Chad Smith Needs Fixing
Server Team CI bot continuous-integration Needs Fixing
Review via email: mp+141198@code.launchpad.net

Description of the change

Reworking the query tool back to life addition. This method is a little less intrusive.

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Chad Smith (chad.smith) wrote :

Hello,
Thank you for taking the time to contribute to cloud-init. Cloud-init has moved its revision control system to git. We are cleaning up old reviews that no longer apply to the current codebase. As a result, we are marking all bzr merge proposals as 'rejected'. If you would like to re-submit this proposal for review, please do so by following the current HACKING documentation at http://cloudinit.readthedocs.io/en/latest/topics/hacking.html.

Also, as you know= cloud-init cmdline util has now moved to cloudinit/cmd/main.py

review: Needs Fixing

Unmerged revisions

755. By Joshua Harlow

Integrate a slightly cleaner query tool, bring it back to life!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bin/cloud-init'
--- bin/cloud-init 2012-09-20 01:19:43 +0000
+++ bin/cloud-init 2012-12-24 04:32:20 +0000
@@ -26,6 +26,8 @@
26import sys26import sys
27import traceback27import traceback
2828
29import cPickle as pickle
30
29# This is more just for running from the bin folder so that31# This is more just for running from the bin folder so that
30# cloud-init binary can find the cloudinit module32# cloud-init binary can find the cloudinit module
31possible_topdir = os.path.normpath(os.path.join(os.path.abspath(33possible_topdir = os.path.normpath(os.path.join(os.path.abspath(
@@ -45,6 +47,8 @@
45from cloudinit import util47from cloudinit import util
46from cloudinit import version48from cloudinit import version
4749
50from cloudinit.sources import DataSource
51
48from cloudinit.settings import (PER_INSTANCE, PER_ALWAYS, PER_ONCE,52from cloudinit.settings import (PER_INSTANCE, PER_ALWAYS, PER_ONCE,
49 CLOUD_CONFIG)53 CLOUD_CONFIG)
5054
@@ -56,12 +60,18 @@
56# Module section template60# Module section template
57MOD_SECTION_TPL = "cloud_%s_modules"61MOD_SECTION_TPL = "cloud_%s_modules"
5862
59# Things u can query on63# Things u can query on and the lambda to fetch that
60QUERY_DATA_TYPES = [64# item when given a datasource to apply on
61 'data',65QUERY_DATA_TYPES = {
62 'data_raw',66 'metadata': lambda ds: ds.metadata,
63 'instance_id',67 'userdata': lambda ds: ds.userdata,
64]68 'iid': lambda ds: ds.get_instance_id(),
69 'hostname': lambda ds: ds.get_hostname(),
70 'locale': lambda ds: ds.get_locale(),
71 'az': lambda ds: ds.availability_zone,
72 'launch_index': lambda ds: ds.launch_index,
73 'public_keys': lambda ds: ds.get_public_ssh_keys(),
74}
6575
66# Frequency shortname to full name76# Frequency shortname to full name
67# (so users don't have to remember the full name...)77# (so users don't have to remember the full name...)
@@ -86,6 +96,10 @@
86 sys.stderr.write("\n")96 sys.stderr.write("\n")
8797
8898
99def is_root():
100 return os.geteuid() == 0
101
102
89def welcome(action, msg=None):103def welcome(action, msg=None):
90 if not msg:104 if not msg:
91 msg = welcome_format(action)105 msg = welcome_format(action)
@@ -346,9 +360,48 @@
346 return run_module_section(mods, name, name)360 return run_module_section(mods, name, name)
347361
348362
349def main_query(name, _args):363def main_query(name, args):
350 raise NotImplementedError(("Action '%s' is not"364 # TODO(harlowja) refactor init so that
351 " currently implemented") % (name))365 # it is not the sole entrypoint for so many operations
366 # perhaps split into
367 init = stages.Init(ds_deps=[])
368 safe_ds_where = init.paths.get_ipath_cur("obj_pkl_safe")
369 if not os.path.isfile(safe_ds_where):
370 if is_root() and args.populate:
371 # At this point we can make a safe datasource from whatever
372 # may exist locally (if anything)
373 ds = init.fetch(True)
374 if not ds:
375 raise NotImplementedError(("No datasource found to "
376 "convert into a 'safe' datasource"))
377 else:
378 # Keep only the basics, ignoring the userdata since typically
379 # said userdata contains contents and data that users should
380 # not always be able to see.
381 safe_ds = DataSource(ds.sys_cfg, ds.distro, ds.paths)
382 safe_ds.metadata = ds.metadata
383 pk_contents = pickle.dumps(safe_ds)
384 util.write_file(safe_ds_where, pk_contents, mode=0644)
385 if args.what:
386 ds = None
387 if is_root():
388 # Use a full datasource if running as root
389 ds = init.fetch(True)
390 if not ds:
391 try:
392 pk_contents = util.load_file(safe_ds_where)
393 ds = pickle.loads(pk_contents)
394 except:
395 pass
396 if not ds:
397 raise NotImplementedError("No datasource found for querying.")
398 for i in args.what:
399 i_canon = i.lower().strip()
400 if i_canon not in QUERY_DATA_TYPES:
401 print("Unknown how to query on %s!" % (i))
402 else:
403 func = QUERY_DATA_TYPES[i_canon]
404 print("%s: %s" % (i, func(ds)))
352405
353406
354def main_single(name, args):407def main_single(name, args):
@@ -468,10 +521,14 @@
468 parser_query = subparsers.add_parser('query',521 parser_query = subparsers.add_parser('query',
469 help=('query information stored '522 help=('query information stored '
470 'in cloud-init'))523 'in cloud-init'))
471 parser_query.add_argument("--name", '-n', action="store",524 if is_root():
472 help="item name to query on",525 parser_query.add_argument("--populate", '-p', action="store_true",
473 required=True,526 help=("populate the 'safe' "
474 choices=QUERY_DATA_TYPES)527 "datasource that users can query"),
528 default=False)
529 query_help = "query the given datasource field (%s)"
530 query_help = query_help % (", ".join(sorted(QUERY_DATA_TYPES.keys())))
531 parser_query.add_argument('what', nargs='*', help=query_help)
475 parser_query.set_defaults(action=('query', main_query))532 parser_query.set_defaults(action=('query', main_query))
476533
477 # This subcommand allows you to run a single module534 # This subcommand allows you to run a single module
478535
=== modified file 'cloudinit/sources/__init__.py'
--- cloudinit/sources/__init__.py 2012-11-12 17:26:49 +0000
+++ cloudinit/sources/__init__.py 2012-12-24 04:32:20 +0000
@@ -20,7 +20,6 @@
20# You should have received a copy of the GNU General Public License20# You should have received a copy of the GNU General Public License
21# along with this program. If not, see <http://www.gnu.org/licenses/>.21# along with this program. If not, see <http://www.gnu.org/licenses/>.
2222
23import abc
24import os23import os
2524
26from cloudinit import importer25from cloudinit import importer
@@ -42,9 +41,6 @@
4241
4342
44class DataSource(object):43class DataSource(object):
45
46 __metaclass__ = abc.ABCMeta
47
48 def __init__(self, sys_cfg, distro, paths, ud_proc=None):44 def __init__(self, sys_cfg, distro, paths, ud_proc=None):
49 self.sys_cfg = sys_cfg45 self.sys_cfg = sys_cfg
50 self.distro = distro46 self.distro = distro
5147
=== modified file 'cloudinit/stages.py'
--- cloudinit/stages.py 2012-12-17 13:41:11 +0000
+++ cloudinit/stages.py 2012-12-24 04:32:20 +0000
@@ -217,13 +217,14 @@
217 cfg_list = self.cfg.get('datasource_list') or []217 cfg_list = self.cfg.get('datasource_list') or []
218 return (cfg_list, pkg_list)218 return (cfg_list, pkg_list)
219219
220 def _get_data_source(self):220 def _get_data_source(self, local_only):
221 if self.datasource is not NULL_DATA_SOURCE:221 if self.datasource is not NULL_DATA_SOURCE:
222 return self.datasource222 return self.datasource
223 ds = self._restore_from_cache()223 ds = self._restore_from_cache()
224 if ds:224 if ds:
225 LOG.debug("Restored from cache, datasource: %s", ds)225 LOG.debug("Restored from cache, datasource: %s", ds)
226 if not ds:226 # Try to find one that will work
227 if not ds and not local_only:
227 (cfg_list, pkg_list) = self._get_datasources()228 (cfg_list, pkg_list) = self._get_datasources()
228 # Deep copy so that user-data handlers can not modify229 # Deep copy so that user-data handlers can not modify
229 # (which will affect user-data handlers down the line...)230 # (which will affect user-data handlers down the line...)
@@ -303,8 +304,8 @@
303 self._reset()304 self._reset()
304 return iid305 return iid
305306
306 def fetch(self):307 def fetch(self, local_only=False):
307 return self._get_data_source()308 return self._get_data_source(local_only)
308309
309 def instancify(self):310 def instancify(self):
310 return self._reflect_cur_instance()311 return self._reflect_cur_instance()