Cleanup the salt-cp(salt.cli.SaltCP) binary parser.

For this, the timeout mix-in and both the target and output parser group mix-ins were re-used. Way less code and logic to keep track of.
Added a simple test for this binary too.
This commit is contained in:
Pedro Algarvio 2012-08-04 22:28:51 +01:00
parent b582e40ff1
commit f5aad4f8e2
4 changed files with 98 additions and 117 deletions

View file

@ -140,109 +140,17 @@ class SaltCMD(parsers.SaltCMDOptionParser):
print('')
class SaltCP(object):
class SaltCP(parsers.SaltCPOptionParser):
'''
Run the salt-cp command line client
'''
def __init__(self):
self.opts = self.__parse()
def __parse(self):
'''
Parse the command line
'''
usage = "%prog [options] '<target>' SOURCE DEST"
parser = optparse.OptionParser(version="%%prog %s" % VERSION, usage=usage)
parser.add_option('-t',
'--timeout',
default=5,
type=int,
dest='timeout',
help=('Set the return timeout for batch jobs; '
'default=5 seconds'))
parser.add_option('-E',
'--pcre',
default=False,
dest='pcre',
action='store_true',
help=('Instead of using shell globs to evaluate the target '
'servers, use pcre regular expressions'))
parser.add_option('-L',
'--list',
default=False,
dest='list',
action='store_true',
help=('Instead of using shell globs to evaluate the target '
'servers, take a comma delimited list of servers.'))
parser.add_option('-G',
'--grain',
default=False,
dest='grain',
action='store_true',
help=('Instead of using shell globs to evaluate the target '
'use a grain value to identify targets, the syntax '
'for the target is the grain key followed by a glob'
'expression:\n"os:Arch*"'))
parser.add_option('--grain-pcre',
default=False,
dest='grain_pcre',
action='store_true',
help=('Instead of using shell globs to evaluate the target '
'use a grain value to identify targets, the syntax '
'for the target is the grain key followed by a pcre '
'regular expression:\n"os:Arch.*"'))
parser.add_option('-N',
'--nodegroup',
default=False,
dest='nodegroup',
action='store_true',
help=('Instead of using shell globs to evaluate the target '
'use one of the predefined nodegroups to identify a '
'list of targets.'))
parser.add_option('-R',
'--range',
default=False,
dest='range',
action='store_true',
help=('Instead of using shell globs to evaluate the target '
'use a range expressions to identify targets. '
'Range expressions look like %cluster'))
parser.add_option('-c',
'--config',
default='/etc/salt/master',
dest='conf_file',
help=('The location of the salt master configuration file, '
'the salt master settings are required to know where '
'the connections are; default=/etc/salt/master'))
options, args = parser.parse_args()
opts = {}
for k, v in options.__dict__.items():
if v is not None:
opts[k] = v
# salt-cp needs arguments
if len(args) <= 1:
parser.print_help()
parser.exit(1)
if opts['list']:
opts['tgt'] = args[0].split(',')
else:
opts['tgt'] = args[0]
opts['src'] = args[1:-1]
opts['dest'] = args[-1]
return opts
def run(self):
'''
Execute salt-cp
'''
cp_ = salt.cli.cp.SaltCP(self.opts)
self.parse_args()
cp_ = salt.cli.cp.SaltCP(self.config)
cp_.run()

View file

@ -505,27 +505,6 @@ class OutputOptionsMixIn(object):
]))
)
# def get_printout(self, outputter=None):
# # Determine the proper output method and run it
# from salt.output import get_printout
# return get_outputter(outputter)
#
# if outputter is not None:
# return get_outputter(outputter)
#
# if self.options.raw_out:
# outputter = 'raw'
# elif self.options.json_out:
# outputter = 'json'
# elif self._include_text_out_ and self.options.text_out:
# outputter = 'txt'
# elif self.options.yaml_out:
# outputter = 'yaml'
#
# if outputter is not None:
# return get_outputter(outputter)
#
# return None
class OutputOptionsWithTextMixIn(OutputOptionsMixIn):
_include_text_out_ = True
@ -672,4 +651,32 @@ class SaltCMDOptionParser(OptionParser, ConfigDirMixIn, TimeoutMixIn,
def setup_config(self):
return config.master_config(self.get_config_file_path('master'))
return config.master_config(self.get_config_file_path('master'))
class SaltCPOptionParser(OptionParser, ConfigDirMixIn, TimeoutMixIn,
TargetOptionsMixIn):
__metaclass__ = OptionParserMeta
description = (
"salt-cp is NOT intended to broadcast large files, it is intended to "
"handle text files.\nsalt-cp can be used to distribute configuration "
"files."
)
default_timeout = 5
usage = "%prog [options] '<target>' SOURCE DEST"
def _mixin_after_parsed(self, options, args):
# salt-cp needs arguments
if len(args) <= 1:
self.print_help()
self.exit(1)
if options.list:
self.config['tgt'] = args[0].split(',')
else:
self.config['tgt'] = args[0]
self.config['src'] = args[1:-1]
self.config['dest'] = args[-1]

View file

@ -383,6 +383,14 @@ class ShellCase(TestCase):
arg_str = '-c {0} {1}'.format(mconf, arg_str)
return self.run_script('salt-key', arg_str)
def run_cp(self, arg_str):
'''
Execute salt-cp
'''
mconf = os.path.join(INTEGRATION_TEST_DIR, 'files', 'conf')
arg_str = '--config-dir {0} {1}'.format(mconf, arg_str)
return self.run_script('salt-cp', arg_str)
class ShellCaseCommonTestsMixIn(object):

View file

@ -0,0 +1,58 @@
# -*- coding: utf-8 -*-
"""
tests.integration.shell.cp
~~~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: © 2012 UfSoft.org - :email:`Pedro Algarvio (pedro@algarvio.me)`
:license: Apache 2.0, see LICENSE for more details.
"""
# Import python libs
import os
import re
import sys
import string
import random
# Import salt libs
from saltunittest import TestLoader, TextTestRunner
import integration
from integration import TestDaemon
class CopyTest(integration.ShellCase, integration.ShellCaseCommonTestsMixIn):
_call_binary_ = 'salt-cp'
def setUp(self):
self.testfile = os.path.join(integration.TMP, 'testfile')
self.testcontents = ''.join(
random.choice(string.ascii_uppercase) for x in range(128)
)
open(self.testfile, 'w').write(self.testcontents)
def tearDown(self):
os.unlink(self.testfile)
def test_cp_testfile(self):
'''
test salt-cp
'''
data = ''.join(self.run_salt('"*" test.ping'))
for minion in re.findall(r"{['|\"]([^:]+)['|\"]: True}", data):
minion_testfile = os.path.join(
integration.TMP, "{0}_testfile".format(minion)
)
self.run_cp("minion {0} {1}".format(self.testfile, minion_testfile))
self.assertTrue(os.path.isfile(minion_testfile))
self.assertTrue(open(minion_testfile, 'r').read()==self.testcontents)
os.unlink(minion_testfile)
if __name__ == "__main__":
loader = TestLoader()
tests = loader.loadTestsFromTestCase(CopyTest)
print('Setting up Salt daemons to execute tests')
with TestDaemon():
runner = TextTestRunner(verbosity=1).run(tests)
sys.exit(runner.wasSuccessful())