"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "barbican/cmd/barbican_manage.py" between
barbican-11.0.0.tar.gz and barbican-12.0.0.tar.gz

About: OpenStack Barbican is the OpenStack Key Manager service. It provides secure storage, provisioning and management of secret data.
The "Wallaby" series (latest release).

barbican_manage.py  (barbican-11.0.0):barbican_manage.py  (barbican-12.0.0)
skipping to change at line 33 skipping to change at line 33
import sys import sys
from oslo_config import cfg from oslo_config import cfg
from oslo_log import log as logging from oslo_log import log as logging
from barbican.cmd import pkcs11_kek_rewrap as pkcs11_rewrap from barbican.cmd import pkcs11_kek_rewrap as pkcs11_rewrap
from barbican.common import config from barbican.common import config
from barbican.model import clean from barbican.model import clean
from barbican.model.migration import commands from barbican.model.migration import commands
from barbican.model import sync from barbican.model import sync
from barbican.plugin.crypto import p11_crypto
from barbican.plugin.crypto import pkcs11 from barbican.plugin.crypto import pkcs11
import barbican.version import barbican.version
CONF = cfg.CONF CONF = cfg.CONF
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
# Decorators for actions # Decorators for actions
def args(*args, **kwargs): def args(*args, **kwargs):
def _decorator(func): def _decorator(func):
func.__dict__.setdefault('args', []).insert(0, (args, kwargs)) func.__dict__.setdefault('args', []).insert(0, (args, kwargs))
skipping to change at line 70 skipping to change at line 71
@args('--log-file', '-L', metavar='<log-file>', type=str, default=None, @args('--log-file', '-L', metavar='<log-file>', type=str, default=None,
dest='log_file', help='Set log file location. ' dest='log_file', help='Set log file location. '
'Default value for log_file can be found in barbican.conf') 'Default value for log_file can be found in barbican.conf')
@args('--clean-unassociated-projects', '-p', action='store_true', @args('--clean-unassociated-projects', '-p', action='store_true',
dest='do_clean_unassociated_projects', default=False, dest='do_clean_unassociated_projects', default=False,
help='Remove projects that have no ' help='Remove projects that have no '
'associated resources.') 'associated resources.')
@args('--soft-delete-expired-secrets', '-e', action='store_true', @args('--soft-delete-expired-secrets', '-e', action='store_true',
dest='do_soft_delete_expired_secrets', default=False, dest='do_soft_delete_expired_secrets', default=False,
help='Soft delete secrets that are expired.') help='Soft delete secrets that are expired.')
def clean(self, dburl=None, min_days=None, verbose=None, log_file=None, def clean(self, conf, dburl=None, min_days=None, verbose=None,
do_clean_unassociated_projects=None, log_file=None, do_clean_unassociated_projects=None,
do_soft_delete_expired_secrets=None): do_soft_delete_expired_secrets=None):
"""Clean soft deletions in the database""" """Clean soft deletions in the database"""
if dburl is None: if dburl is None:
dburl = CONF.sql_connection dburl = CONF.sql_connection
if log_file is None: if log_file is None:
log_file = CONF.log_file log_file = CONF.log_file
clean.clean_command( clean.clean_command(
sql_url=dburl, sql_url=dburl,
min_num_days=min_days, min_num_days=min_days,
skipping to change at line 95 skipping to change at line 96
log_file=log_file) log_file=log_file)
revision_description = "Create a new database version file" revision_description = "Create a new database version file"
@args('--db-url', '-d', metavar='<db-url>', dest='dburl', @args('--db-url', '-d', metavar='<db-url>', dest='dburl',
help='barbican database URL') help='barbican database URL')
@args('--message', '-m', metavar='<message>', default='DB change', @args('--message', '-m', metavar='<message>', default='DB change',
help='the message for the DB change') help='the message for the DB change')
@args('--autogenerate', action="store_true", dest='autogen', @args('--autogenerate', action="store_true", dest='autogen',
default=False, help='autogenerate from models') default=False, help='autogenerate from models')
def revision(self, dburl=None, message=None, autogen=None): def revision(self, conf, dburl=None, message=None, autogen=None):
"""Process the 'revision' Alembic command.""" """Process the 'revision' Alembic command."""
if dburl is None: if dburl is None:
commands.generate(autogenerate=autogen, message=str(message), commands.generate(autogenerate=autogen, message=str(message),
sql_url=CONF.sql_connection) sql_url=CONF.sql_connection)
else: else:
commands.generate(autogenerate=autogen, message=str(message), commands.generate(autogenerate=autogen, message=str(message),
sql_url=str(dburl)) sql_url=str(dburl))
upgrade_description = "Upgrade to a future database version" upgrade_description = "Upgrade to a future database version"
@args('--db-url', '-d', metavar='<db-url>', dest='dburl', @args('--db-url', '-d', metavar='<db-url>', dest='dburl',
help='barbican database URL') help='barbican database URL')
@args('--version', '-v', metavar='<version>', default='head', @args('--version', '-v', metavar='<version>', default='head',
help='the version to upgrade to, or else ' help='the version to upgrade to, or else '
'the latest/head if not specified.') 'the latest/head if not specified.')
def upgrade(self, dburl=None, version=None): def upgrade(self, conf, dburl=None, version=None):
"""Process the 'upgrade' Alembic command.""" """Process the 'upgrade' Alembic command."""
if dburl is None: if dburl is None:
commands.upgrade(to_version=str(version), commands.upgrade(to_version=str(version),
sql_url=CONF.sql_connection) sql_url=CONF.sql_connection)
else: else:
commands.upgrade(to_version=str(version), sql_url=str(dburl)) commands.upgrade(to_version=str(version), sql_url=str(dburl))
history_description = "Show database changset history" history_description = "Show database changset history"
@args('--db-url', '-d', metavar='<db-url>', dest='dburl', @args('--db-url', '-d', metavar='<db-url>', dest='dburl',
help='barbican database URL') help='barbican database URL')
@args('--verbose', '-V', action='store_true', dest='verbose', @args('--verbose', '-V', action='store_true', dest='verbose',
default=False, help='Show full information about the revisions.') default=False, help='Show full information about the revisions.')
def history(self, dburl=None, verbose=None): def history(self, conf, dburl=None, verbose=None):
if dburl is None: if dburl is None:
commands.history(verbose, sql_url=CONF.sql_connection) commands.history(verbose, sql_url=CONF.sql_connection)
else: else:
commands.history(verbose, sql_url=str(dburl)) commands.history(verbose, sql_url=str(dburl))
current_description = "Show current revision of database" current_description = "Show current revision of database"
@args('--db-url', '-d', metavar='<db-url>', dest='dburl', @args('--db-url', '-d', metavar='<db-url>', dest='dburl',
help='barbican database URL') help='barbican database URL')
@args('--verbose', '-V', action='store_true', dest='verbose', @args('--verbose', '-V', action='store_true', dest='verbose',
default=False, help='Show full information about the revisions.') default=False, help='Show full information about the revisions.')
def current(self, dburl=None, verbose=None): def current(self, conf, dburl=None, verbose=None):
if dburl is None: if dburl is None:
commands.current(verbose, sql_url=CONF.sql_connection) commands.current(verbose, sql_url=CONF.sql_connection)
else: else:
commands.current(verbose, sql_url=str(dburl)) commands.current(verbose, sql_url=str(dburl))
sync_secret_stores_description = ("Sync secret_stores with " # nosec sync_secret_stores_description = ("Sync secret_stores with " # nosec
"barbican.conf") "barbican.conf")
@args('--db-url', '-d', metavar='<db-url>', dest='dburl', @args('--db-url', '-d', metavar='<db-url>', dest='dburl',
help='barbican database URL') help='barbican database URL')
@args('--verbose', '-V', action='store_true', dest='verbose', @args('--verbose', '-V', action='store_true', dest='verbose',
default=False, help='Show verbose information about the clean up.') default=False, help='Show verbose information about the clean up.')
@args('--log-file', '-L', metavar='<log-file>', type=str, default=None, @args('--log-file', '-L', metavar='<log-file>', type=str, default=None,
dest='log_file', dest='log_file',
help='Set log file location. ' help='Set log file location. '
'Default value for log_file can be found in barbican.conf') 'Default value for log_file can be found in barbican.conf')
def sync_secret_stores(self, dburl=None, verbose=None, log_file=None): def sync_secret_stores(self, conf, dburl=None, verbose=None,
log_file=None):
"""Sync secret_stores table with barbican.conf""" """Sync secret_stores table with barbican.conf"""
if dburl is None: if dburl is None:
dburl = CONF.sql_connection dburl = CONF.sql_connection
if log_file is None: if log_file is None:
log_file = CONF.log_file log_file = CONF.log_file
sync.sync_secret_stores( sync.sync_secret_stores(
sql_url=dburl, sql_url=dburl,
verbose=verbose, verbose=verbose,
log_file=log_file) log_file=log_file)
class HSMCommands(object): class HSMCommands(object):
"""Class for managing HSM/pkcs11 plugin""" """Class for managing HSM/pkcs11 plugin"""
_CKK_AES = 'CKK_AES'
description = "Subcommands for managing HSM/PKCS11" description = "Subcommands for managing HSM/PKCS11"
check_mkek_description = "Checks if a MKEK label is available" check_mkek_description = "Checks if a MKEK label is available"
@args('--library-path', metavar='<library-path>', dest='libpath', @args('--library-path', metavar='<library-path>', dest='libpath',
default='/usr/lib/libCryptoki2_64.so', help='Path to vendor PKCS#11 library')
help='Path to vendor PKCS11 library') @args('--slot-id', metavar='<slot-id>', dest='slotid',
@args('--slot-id', metavar='<slot-id>', dest='slotid', default=1, help='HSM Slot ID containing Token to be used.')
help='HSM Slot id (Should correspond to a configured PKCS11 slot, \ @args('--passphrase', metavar='<passphrase>',
default is 1)') help='Password (PIN) to login to PKCS#11 Token')
@args('--passphrase', metavar='<passphrase>', default=None, required=True, @args('--label', '-L', metavar='<label>',
help='Password to login to PKCS11 session') help='The label of the Master Key Encryption Key')
@args('--label', '-L', metavar='<label>', default='primarymkek',
help='The label of the Master Key Encrypt Key')
@args('--hmac-wrap-mechanism', metavar='<hmac key wrap mechanism>', @args('--hmac-wrap-mechanism', metavar='<hmac key wrap mechanism>',
dest='hmacwrap', default='CKM_SHA256_HMAC', dest='hmacwrap',
help='HMAC Key wrap mechanism, default is CKM_SHA256_HMAC') help='HMAC Key wrap mechanism')
def check_mkek(self, passphrase, libpath=None, slotid=None, label=None, def check_mkek(self, conf, passphrase=None, libpath=None, slotid=None,
hmacwrap=None): label=None, hmacwrap=None):
CKK_AES = 'CKK_AES' self._create_pkcs11_session(conf, passphrase, libpath, slotid,
self._create_pkcs11_session(str(passphrase), str(libpath), hmacwrap)
int(slotid), str(hmacwrap)) if label is None:
handle = self.pkcs11.get_key_handle(CKK_AES, str(label), self.session) label = conf.p11_crypto_plugin.mkek_label
handle = self.pkcs11.get_key_handle(self._CKK_AES, label, self.session)
self.pkcs11.return_session(self.session) self.pkcs11.return_session(self.session)
if not handle: if not handle:
print("Label {label} is not set.".format(label=label)) print("Label {label} is not set.".format(label=label))
sys.exit(1) sys.exit(1)
print("Key labeled {} found!".format(label))
gen_mkek_description = "Generates a new MKEK" gen_mkek_description = "Generates a new MKEK"
@args('--library-path', metavar='<library-path>', dest='libpath', @args('--library-path', metavar='<library-path>', dest='libpath',
default='/usr/lib/libCryptoki2_64.so',
help='Path to vendor PKCS11 library') help='Path to vendor PKCS11 library')
@args('--slot-id', metavar='<slot-id>', dest='slotid', default=1, @args('--slot-id', metavar='<slot-id>', dest='slotid',
help='HSM Slot id (Should correspond to a configured PKCS11 slot, \ help='HSM Slot ID containing Token to be used.')
default is 1)') @args('--passphrase', metavar='<passphrase>',
@args('--passphrase', metavar='<passphrase>', default=None, required=True, help='Password (PIN) to login to PKCS#11 Token')
help='Password to login to PKCS11 session') @args('--label', '-L', metavar='<label>',
@args('--label', '-L', metavar='<label>', default='primarymkek', help='The label of the Master Key Encryption Key')
help='The label of the Master Key Encrypt Key') @args('--length', '-l', metavar='<length>',
@args('--length', '-l', metavar='<length>', default=32,
help='The length in bytes of the Master Key Encryption Key' help='The length in bytes of the Master Key Encryption Key'
' (default is 32)') ' (default is 32)')
@args('--hmac-wrap-mechanism', metavar='<hmac key wrap mechanism>', @args('--hmac-wrap-mechanism', metavar='<hmac key wrap mechanism>',
dest='hmacwrap', default='CKM_SHA256_HMAC', dest='hmacwrap',
help='HMAC Key wrap mechanism, default is CKM_SHA256_HMAC') help='HMAC Key wrap mechanism, default is CKM_SHA256_HMAC')
def gen_mkek(self, passphrase, libpath=None, slotid=None, label=None, def gen_mkek(self, conf, passphrase=None, libpath=None, slotid=None,
length=None, hmacwrap=None): label=None, length=None, hmacwrap=None):
CKK_AES = 'CKK_AES'
CKM_AES_KEY_GEN = 'CKM_AES_KEY_GEN' CKM_AES_KEY_GEN = 'CKM_AES_KEY_GEN'
self._create_pkcs11_session(str(passphrase), str(libpath), self._create_pkcs11_session(conf, passphrase, libpath, slotid,
int(slotid), str(hmacwrap)) hmacwrap)
self._verify_label_does_not_exist(CKK_AES, str(label), self.session) if label is None:
self.pkcs11.generate_key(CKK_AES, int(length), CKM_AES_KEY_GEN, label = conf.p11_crypto_plugin.mkek_label or 'primarymkek'
self.session, str(label), self._verify_label_does_not_exist(self._CKK_AES, label, self.session)
if length is None:
length = conf.p11_crypto_plugin.mkek_length or 32
if type(length) is not int:
length = int(length)
self.pkcs11.generate_key(self._CKK_AES, length, CKM_AES_KEY_GEN,
self.session, label,
encrypt=True, wrap=True, master_key=True) encrypt=True, wrap=True, master_key=True)
self.pkcs11.return_session(self.session) self.pkcs11.return_session(self.session)
print("MKEK successfully generated!") print("MKEK successfully generated!")
check_hmac_description = "Checks if a HMAC key label is available" check_hmac_description = "Checks if a HMAC key label is available"
@args('--library-path', metavar='<library-path>', dest='libpath', @args('--library-path', metavar='<library-path>', dest='libpath',
default='/usr/lib/libCryptoki2_64.so', help='Path to vendor PKCS#11 library')
help='Path to vendor PKCS11 library') @args('--slot-id', metavar='<slot-id>', dest='slotid',
@args('--slot-id', metavar='<slot-id>', dest='slotid', default=1, help='HSM Slot ID containing Token to be used.')
help='HSM Slot id (Should correspond to a configured PKCS11 slot, \ @args('--passphrase', metavar='<passphrase>',
default is 1)') help='Password (PIN) to login to PKCS#11 Token')
@args('--passphrase', metavar='<passphrase>', default=None, required=True, @args('--label', '-L', metavar='<label>',
help='Password to login to PKCS11 session')
@args('--label', '-L', metavar='<label>', default='primarymkek',
help='The label of the Master HMAC key') help='The label of the Master HMAC key')
@args('--key-type', '-t', metavar='<key type>', dest='keytype', @args('--key-type', '-t', metavar='<key type>', dest='keytype',
default='CKK_AES', help='The HMAC Key Type (e.g. CKK_AES)') help='The HMAC Key Type (e.g. CKK_AES)')
@args('--hmac-wrap-mechanism', metavar='<hmac key wrap mechanism>', @args('--hmac-wrap-mechanism', metavar='<hmac key wrap mechanism>',
dest='hmacwrap', default='CKM_SHA256_HMAC', dest='hmacwrap',
help='HMAC Key wrap mechanism, default is CKM_SHA256_HMAC') help='HMAC Key wrap mechanism')
def check_hmac(self, passphrase, libpath=None, slotid=None, label=None, def check_hmac(self, conf, passphrase=None, libpath=None, slotid=None,
keytype=None, hmacwrap=None): label=None, keytype=None, hmacwrap=None):
self._create_pkcs11_session(str(passphrase), str(libpath), self._create_pkcs11_session(conf, passphrase, libpath, slotid,
int(slotid), str(hmacwrap)) hmacwrap)
handle = self.pkcs11.get_key_handle(str(keytype), str(label), if label is None:
self.session) label = conf.p11_crypto_plugin.hmac_label
if keytype is None:
keytype = conf.p11_crypto_plugin.hmac_key_type
handle = self.pkcs11.get_key_handle(keytype, label, self.session)
self.pkcs11.return_session(self.session) self.pkcs11.return_session(self.session)
if not handle: if not handle:
print("Label {label} is not set.".format(label=label)) print("Label {label} is not set.".format(label=label))
sys.exit(1) sys.exit(1)
print("Key labeled {} found!".format(label))
gen_hmac_description = "Generates a new HMAC key" gen_hmac_description = "Generates a new HMAC key"
@args('--library-path', metavar='<library-path>', dest='libpath', @args('--library-path', metavar='<library-path>', dest='libpath',
default='/usr/lib/libCryptoki2_64.so',
help='Path to vendor PKCS11 library') help='Path to vendor PKCS11 library')
@args('--slot-id', metavar='<slot-id>', dest='slotid', default=1, @args('--slot-id', metavar='<slot-id>', dest='slotid',
help='HSM Slot id (Should correspond to a configured PKCS11 slot, \ help='HSM Slot ID containing Token to be used.')
default is 1)') @args('--passphrase', metavar='<passphrase>',
@args('--passphrase', metavar='<passphrase>', default=None, required=True, help='Password (PIN) to login to PKCS#11 Token')
help='Password to login to PKCS11 session') @args('--label', '-L', metavar='<label>',
@args('--label', '-L', metavar='<label>', default='primarymkek',
help='The label of the Master HMAC Key') help='The label of the Master HMAC Key')
@args('--key-type', '-t', metavar='<key type>', dest='keytype', @args('--key-type', '-t', metavar='<key type>', dest='keytype',
default='CKK_AES', help='The HMAC Key Type (e.g. CKK_AES)') help='The HMAC Key Type (e.g. CKK_AES)')
@args('--length', '-l', metavar='<length>', default=32, @args('--length', '-l', metavar='<length>',
help='The length in bytes of the Master HMAC Key (default is 32)') help='The length in bytes of the Master HMAC Key (default is 32)')
@args('--mechanism', '-m', metavar='<mechanism>', @args('--mechanism', '-m', metavar='<mechanism>',
default='CKM_AES_KEY_GEN', help='The HMAC Key Generation mechanism') help='The HMAC Key Generation mechanism')
@args('--hmac-wrap-mechanism', metavar='<hmac key wrap mechanism>', @args('--hmac-wrap-mechanism', metavar='<hmac key wrap mechanism>',
dest='hmacwrap', default='CKM_SHA256_HMAC', dest='hmacwrap',
help='HMAC Key wrap mechanism, default is CKM_SHA256_HMAC') help='HMAC Key wrap mechanism, default is CKM_SHA256_HMAC')
def gen_hmac(self, passphrase, libpath=None, slotid=None, label=None, def gen_hmac(self, conf, passphrase=None, libpath=None, slotid=None,
keytype=None, mechanism=None, length=None, hmacwrap=None): label=None, keytype=None, mechanism=None, length=None,
self._create_pkcs11_session(str(passphrase), str(libpath), int(slotid), hmacwrap=None):
str(hmacwrap)) self._create_pkcs11_session(conf, passphrase, libpath, slotid,
self._verify_label_does_not_exist(str(keytype), str(label), hmacwrap)
self.session) if label is None:
self.pkcs11.generate_key(str(keytype), int(length), str(mechanism), label = conf.p11_crypto_plugin.hmac_label or 'primaryhmac'
self.session, str(label), if keytype is None:
sign=True, master_key=True) keytype = conf.p11_crypto_plugin.hmac_key_type
self._verify_label_does_not_exist(keytype, label, self.session)
if length is None:
# barbican.conf doesn't have an HMAC length
length = 32 # bytes
elif type(length) is not int:
length = int(length)
if mechanism is None:
mechanism = conf.p11_crypto_plugin.hmac_keygen_mechanism
self.pkcs11.generate_key(keytype, length, mechanism, self.session,
label, sign=True, master_key=True)
self.pkcs11.return_session(self.session) self.pkcs11.return_session(self.session)
print("HMAC successfully generated!") print("HMAC successfully generated!")
rewrap_pkek_description = "Re-wrap project MKEKs" rewrap_pkek_description = "Re-wrap project MKEKs"
@args('--dry-run', action="store_true", dest='dryrun', default=False, @args('--dry-run', action="store_true", dest='dryrun', default=False,
help='Displays changes that will be made (Non-destructive)') help='Displays changes that will be made (Non-destructive)')
def rewrap_pkek(self, dryrun=None): def rewrap_pkek(self, conf, dryrun=None):
rewrapper = pkcs11_rewrap.KekRewrap(pkcs11_rewrap.CONF) rewrapper = pkcs11_rewrap.KekRewrap(pkcs11_rewrap.CONF)
rewrapper.execute(dryrun) rewrapper.execute(dryrun)
rewrapper.pkcs11.return_session(rewrapper.hsm_session) rewrapper.pkcs11.return_session(rewrapper.hsm_session)
def _create_pkcs11_session(self, passphrase, libpath, slotid, def _create_pkcs11_session(self, conf, passphrase, libpath, slotid,
hmacwrap): hmacwrap):
if passphrase is None:
passphrase = conf.p11_crypto_plugin.login
if libpath is None:
libpath = conf.p11_crypto_plugin.library_path
if slotid is None:
slotid = conf.p11_crypto_plugin.slot_id
elif type(slotid) is not int:
slotid = int(slotid)
if hmacwrap is None:
hmacwrap = conf.p11_crypto_plugin.hmac_keywrap_mechanism
self.pkcs11 = pkcs11.PKCS11( self.pkcs11 = pkcs11.PKCS11(
library_path=libpath, login_passphrase=passphrase, library_path=libpath, login_passphrase=passphrase,
rw_session=True, slot_id=slotid, rw_session=True, slot_id=slotid,
encryption_mechanism='CKM_AES_CBC', encryption_mechanism='CKM_AES_CBC',
hmac_keywrap_mechanism=hmacwrap hmac_keywrap_mechanism=hmacwrap,
token_serial_number=conf.p11_crypto_plugin.token_serial_number,
token_labels=conf.p11_crypto_plugin.token_labels
) )
self.session = self.pkcs11.get_session() self.session = self.pkcs11.get_session()
def _verify_label_does_not_exist(self, key_type, label, session): def _verify_label_does_not_exist(self, key_type, label, session):
key_handle = self.pkcs11.get_key_handle(key_type, label, session) key_handle = self.pkcs11.get_key_handle(key_type, label, session)
if key_handle: if key_handle:
print("The label {label} already exists!".format(label=label)) print("The label {label} already exists!".format(label=label))
sys.exit(1) sys.exit(1)
CATEGORIES = { CATEGORIES = {
skipping to change at line 379 skipping to change at line 410
# Define subcommand category # Define subcommand category
category_opt = cfg.SubCommandOpt('category', category_opt = cfg.SubCommandOpt('category',
title='Command categories', title='Command categories',
help='Available categories', help='Available categories',
handler=add_command_parsers) handler=add_command_parsers)
def main(): def main():
"""Parse options and call the appropriate class/method.""" """Parse options and call the appropriate class/method."""
CONF = config.new_config() CONF = config.new_config()
CONF.register_cli_opt(category_opt) CONF.register_cli_opt(category_opt)
p11_crypto.register_opts(CONF)
try: try:
logging.register_options(CONF) logging.register_options(CONF)
logging.setup(CONF, "barbican-manage") logging.setup(CONF, "barbican-manage")
cfg_files = cfg.find_config_files(project='barbican') cfg_files = cfg.find_config_files(project='barbican')
CONF(args=sys.argv[1:], CONF(args=sys.argv[1:],
project='barbican', project='barbican',
prog='barbican-manage', prog='barbican-manage',
version=barbican.version.__version__, version=barbican.version.__version__,
skipping to change at line 408 skipping to change at line 440
for k in CONF.category.action_kwargs: for k in CONF.category.action_kwargs:
v = getattr(CONF.category, 'action_kwarg_' + k) v = getattr(CONF.category, 'action_kwarg_' + k)
if v is None: if v is None:
continue continue
if isinstance(v, bytes): if isinstance(v, bytes):
v = v.decode('utf-8') v = v.decode('utf-8')
fn_kwargs[k] = v fn_kwargs[k] = v
# call the action with the remaining arguments # call the action with the remaining arguments
try: try:
return fn(*fn_args, **fn_kwargs) return fn(CONF, *fn_args, **fn_kwargs)
except Exception as e: except Exception as e:
sys.exit("ERROR: %s" % e) sys.exit("ERROR: %s" % e)
if __name__ == '__main__': if __name__ == '__main__':
main() main()
 End of changes. 32 change blocks. 
83 lines changed or deleted 115 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)