commit 604dc6f68b5f97cacc6c6d8d82e0fe505455e9dd
Author: Seth Vidal <skvidal@puppet01.phx2.fedoraproject.org>
Date:   Fri Aug 20 21:43:47 2010 +0000

    add --hosts-from-file option to func-command
    add compare command to func-yum to compare the installed pkgs of 2 hosts

diff --git a/modules/puppet/files/func-command.py b/modules/puppet/files/func-command.py
index 9246b99..585e4fe 100644
--- a/modules/puppet/files/func-command.py
+++ b/modules/puppet/files/func-command.py
@@ -16,8 +16,24 @@ def parse_args(args):
                help='set the wait timeout for func commands')
     parser.add_option('--forks', default=40, type='int',
                help='set the number of forks to start up')
+    parser.add_option('--hosts-from-file', default=None, dest="hostfile",
+               help="read list of hosts from this file, if '-' read from stdin")
     (opts, args) = parser.parse_args(args)
 
+    if opts.hostfile:
+        hosts = []
+        if opts.hostfile == '-':
+            hosts = sys.stdin.readlines()
+        else:
+            hosts = open(opts.hostfile, 'r').readlines()
+        
+        for hn in hosts:
+            hn = hn.strip()
+            if hn.startswith('#'):
+                continue
+            hn = hn.replace('\n', '')
+            opts.host.append(hn)
+
     return opts, args, parser
 
 
@@ -46,7 +62,9 @@ for (hn, output) in results.items():
         print >> sys.stderr, msg 
         continue
 
+    # FIXME - maybe for commands don't do it one line with hostname first
 
-    for line in output[1].split('\n'):
-        print '%s:%s' % (hn, line)
-        
+    print '%s' % hn
+    print output[1]
+    print ''
+    
diff --git a/modules/puppet/files/func-yum.py b/modules/puppet/files/func-yum.py
index 1011792..12a23b5 100644
--- a/modules/puppet/files/func-yum.py
+++ b/modules/puppet/files/func-yum.py
@@ -18,29 +18,21 @@
 
 #func yum overlord script
 
-#ideas:
-#  -  have everything run out of the cached info in outputpath unless '--live'
-#      is specified then you go and get it
-#  - take commands like normal yum 
-# get all updates via yumcmd.check_update via func
-# store timestamp of check and list of updates in a dir/db with name of host
-# store complete list of installed pkgs for each host
-# cmd should
- # list hosts needing updates
- # list hosts needing a certain pkg updated
-# apply updates - glob or all
- # report results of this
-# when it takes lists of hosts  - it should interpret names relatively
-# using fnmatches to ballpark what is being asked
-
-# ideas - more
-# push module out to hosts after figuring out which version of yum and python they have
-# figure out to make func read the module in and make it available
-# run the module
-# config file of some kind - using func's commonconfig/readconfig thing
-# func-yum custom command which uses cmd.run(yum ....) to run custom shit
-# lock files per-host for updating,etc - so multiple calls don't come in
-# 
+
+# TODO:
+# install ....
+# remove ....
+# push custom module over func and activate
+# config file
+# --test mode/options
+# add arbitrary args to a command (include, exclude, etc)
+# needs restarting
+# is running kernel latest installed (needs reboot?)
+# get list of repos
+# some kind of locking mechanism - so we hold off hitting a request on a host that's already doing something
+#   maybe that means client-local locking on the minion-side.
+
+
 
 import sys
 import os
@@ -91,7 +83,7 @@ def errorprint(msg):
     
 def parse_args(args):
     basecmds = ('update', 'getinfo', 'status', 'install', 'remove', 'list', 
-                'custom', 'clean', 'search')
+                'custom', 'clean', 'search', 'compare')
 
     usage = """func-yum [options] [command]
 commands: \n  %s""" % '\n  '.join(sorted(basecmds))
@@ -434,20 +426,25 @@ def search(hosts, opts, search_str, target=None):
                             results[hn] = []
                         results[hn].append('%s:%s' % (thistarget, r.strip()))
     return results
+
+def get_host_list(hosts):
+    fc = fclient.Client(hosts)
+    host_list = fc.minions_class.get_all_hosts() # grumble
+    return host_list
     
 def main(args):
 
     opts, args = parse_args(args)
     basecmd = args[0]
     extcmds = args[1:]
-    
     hosts ='*'
     if opts.host:
         hosts = ';'.join(opts.host)
-    fc = fclient.Client(hosts)
-    host_list = fc.minions_class.get_all_hosts() # grumble
+    
+    
 
     if basecmd == 'getinfo':
+        
         hosts, offline = filter_hosts(hosts, opts)
         getinfo_forks = len(hosts) # gives us a slight advantage on an expensive operation
         fc = fclient.Client(';'.join(hosts), timeout=opts.timeout, nforks=getinfo_forks)
@@ -480,6 +477,7 @@ def main(args):
         
         
     elif basecmd == 'status':
+        host_list = get_host_list(hosts)
         now = time.time()
         status =  return_status(host_list, opts)
         for hn in sorted(status.keys()):
@@ -497,6 +495,7 @@ def main(args):
 
 
     elif basecmd == 'list':
+        host_list = get_host_list(hosts)
         extopts = ['installed', 'updates', 'orphans', 'security-updates',
                    'updated', 'with-security', 'with-updates']
         if len(extcmds) == 0:
@@ -550,10 +549,12 @@ def main(args):
                     print ''
                 
     elif basecmd == 'search-updates':
+        host_list = get_host_list(hosts)
         # look for strings specified as matches in each of the updates output
         # return host names and what matched        
         pass
     elif basecmd == 'search-installed':
+        host_list = get_host_list(hosts)
         # look for strings specified as matches in each of the installed output 
         # return host names and what matched
         pass
@@ -566,6 +567,7 @@ def main(args):
             errorprint('  %s' % error)
     
     elif basecmd == 'clean':
+        host_list = get_host_list(hosts)
         extopts = ['old-data', 'downed-hosts', 'empty-hosts']
         if len(extcmds) == 0:
             errorprint("specify %s" % ' '.join(extopts))
@@ -589,6 +591,25 @@ def main(args):
             for i in returns:
                 print '%s:%s' % (hn, i)
 
+    elif basecmd == 'compare':
+        if len(extcmds) != 2:
+            errorprint("Must specify exactly two hosts to compare")
+        hosts = ';'.join(extcmds)
+        host_list = get_host_list(hosts)
+        if len(host_list) != 2:
+            errorprint("Must specify exactly two hosts to compare, hosts found: %s" % ' '.join(host_list))
+        
+        host1 = host_list[0]
+        host2 = host_list[1]
+        host1_inst = set(return_info(host1, opts, 'installed', as_list=True))
+        host2_inst = set(return_info(host2, opts, 'installed', as_list=True))
+        host1diff = host1_inst.difference(host2_inst)
+        host2diff = host2_inst.difference(host1_inst)
+        print 'Packages on %s not on %s' % (host1, host2)
+        print ''.join(host1diff)
+        print 'Packages on %s not on %s' % (host2, host1)
+        print ''.join(host2diff)
+        
     else:
         errorprint('command %s not implemented yet' % basecmd)
         return 1
