예제 #1
0
  def testLoadConfigSingleMap(self):
    conf_file = open(self.conf_filename, 'w')
    conf_file.write('[DEFAULT]\n'
                    'source = foo\n'
                    'cache = foo\n'
                    'maps = foo\n'
                    'timestamp_dir = foo\n')
    conf_file.close()

    config.LoadConfig(self.conf)

    self.assertEquals(['foo'], self.conf.maps)
예제 #2
0
  def testLoadConfigMapsWhitespace(self):
    conf_file = open(self.conf_filename, 'w')
    conf_file.write('[DEFAULT]\n'
                    'source = foo\n'
                    'cache = foo\n'
                    'maps = foo,  bar  , baz\n'
                    'timestamp_dir = foo\n')
    conf_file.close()

    config.LoadConfig(self.conf)

    self.assertEquals(['foo', 'bar', 'baz'], self.conf.maps)
예제 #3
0
  def testLoadConfigOptionalDefaults(self):
    conf_file = open(self.conf_filename, 'w')
    conf_file.write('[DEFAULT]\n'
                    'source = foo\n'
                    'cache = foo\n'
                    'maps = foo,  bar  , baz\n'
                    'lockfile = foo\n'
                    'timestamp_dir = foo\n')
    conf_file.close()

    config.LoadConfig(self.conf)

    self.assertEquals(self.conf.lockfile, 'foo')
예제 #4
0
 def testVerifyNoMapConfigurationIsError(self):
   conf_file = open(self.conf_filename, 'w')
   conf_file.write('[DEFAULT]\n'
                   'source = foo\n'
                   'cache = foo\n'
                   'maps = \n'
                   'timestamp_dir = foo\n')
   conf_file.close()
   config.LoadConfig(self.conf)
   nsswitch_filename = os.path.join(self.workdir, 'nsswitch.conf')
   nsswitch_file = open(nsswitch_filename, 'w')
   nsswitch_file.write('passwd: files ldap\n')
   nsswitch_file.close()
   self.assertEquals((0, 1),
                     config.VerifyConfiguration(self.conf,
                                                nsswitch_filename))
   os.unlink(nsswitch_filename)
예제 #5
0
 def testLoadConfigStripQuotesFromStrings(self):
   conf_file = open(self.conf_filename, 'w')
   conf_file.write('[DEFAULT]\n'
                   'source = "ldap"\n'  # needs to be ldap due to magic
                   'cache = \'b\'ar\'\n'
                   'maps = quux\n'
                   'timestamp_dir = foo\n'
                   'ldap_tls_require_cert = \'blah\'\n'
                   '[quux]\n'
                   'ldap_klingon = "qep\'a\' wa\'maH loS\'DIch"\n')
   conf_file.close()
   config.LoadConfig(self.conf)
   self.assertEquals('ldap', self.conf.options['quux'].source['name'])
   self.assertEquals('b\'ar', self.conf.options['quux'].cache['name'])
   self.assertEquals('blah',
                     self.conf.options['quux'].source['tls_require_cert'])
   self.assertEquals('qep\'a\' wa\'maH loS\'DIch',
                     self.conf.options['quux'].source['klingon'])
예제 #6
0
 def testVerifyBadConfigurationIncrementsWarningCount(self):
   conf_file = open(self.conf_filename, 'w')
   conf_file.write('[DEFAULT]\n'
                   'source = foo\n'
                   'cache = foo\n'
                   'maps = passwd, group, shadow\n'
                   'timestamp_dir = foo\n')
   conf_file.close()
   config.LoadConfig(self.conf)
   nsswitch_filename = os.path.join(self.workdir, 'nsswitch.conf')
   nsswitch_file = open(nsswitch_filename, 'w')
   nsswitch_file.write('passwd: files ldap\n')
   nsswitch_file.write('group: files db\n')
   nsswitch_file.write('shadow: files db\n')
   nsswitch_file.close()
   self.assertEquals((1, 0),
                     config.VerifyConfiguration(self.conf,
                                                nsswitch_filename))
   os.unlink(nsswitch_filename)
예제 #7
0
 def testVerifyBadConfigurationWithCache(self):
   conf_file = open(self.conf_filename, 'w')
   conf_file.write('[DEFAULT]\n'
                   'source = foo\n'
                   'cache = files\n'
                   'maps = passwd, group, shadow\n'
                   'timestamp_dir = foo\n'
                   'files_cache_filename_suffix = cache')
   conf_file.close()
   config.LoadConfig(self.conf)
   nsswitch_filename = os.path.join(self.workdir, 'nsswitch.conf')
   nsswitch_file = open(nsswitch_filename, 'w')
   nsswitch_file.write('passwd: files\n')
   nsswitch_file.write('group: files\n')
   nsswitch_file.write('shadow: files\n')
   nsswitch_file.close()
   self.assertEquals((3, 0),
                     config.VerifyConfiguration(self.conf,
                                                nsswitch_filename))
   os.unlink(nsswitch_filename)
예제 #8
0
  def testLoadConfigConvertsNumbers(self):
    conf_file = open(self.conf_filename, 'w')
    conf_file.write('[DEFAULT]\n'
                    'source = foo\n'
                    'cache = foo\n'
                    'maps = foo\n'
                    'timestamp_dir = foo\n'
                    'foo_string = test\n'
                    'foo_float = 1.23\n'
                    'foo_int = 1\n')
    conf_file.close()

    config.LoadConfig(self.conf)

    foo_dict = self.conf.options['foo'].source
    self.assertTrue(isinstance(foo_dict['string'], str))
    self.assertTrue(isinstance(foo_dict['float'], float))
    self.assertTrue(isinstance(foo_dict['int'], int))
    self.assertEquals(foo_dict['string'], 'test')
    self.assertEquals(foo_dict['float'], 1.23)
    self.assertEquals(foo_dict['int'], 1)
예제 #9
0
  def testLoadConfigExample(self):
    """Test that we parse and load the example config.

    Note that this also tests MapOptions() creation and our overriding
    of defaults in LoadConfig.

    This requires that nsscache.conf exists in the top of the source tree.
    Changes to the configuration options may break this test.
    """
    conf = self.conf
    config.LoadConfig(conf)
    passwd = conf.options['passwd']
    group = conf.options['group']
    shadow = conf.options['shadow']
    automount = conf.options['automount']

    self.assertTrue(isinstance(passwd, config.MapOptions))
    self.assertTrue(isinstance(group, config.MapOptions))
    self.assertTrue(isinstance(shadow, config.MapOptions))
    self.assertTrue(isinstance(automount, config.MapOptions))

    self.assertEquals(passwd.source['name'], 'ldap')
    self.assertEquals(group.source['name'], 'ldap')
    self.assertEquals(shadow.source['name'], 'ldap')
    self.assertEquals(automount.source['name'], 'ldap')

    self.assertEquals(passwd.cache['name'], 'files')
    self.assertEquals(group.cache['name'], 'files')
    self.assertEquals(shadow.cache['name'], 'files')
    self.assertEquals(automount.cache['name'], 'files')

    self.assertEquals(passwd.source['base'],
                      'ou=people,dc=example,dc=com')
    self.assertEquals(passwd.source['filter'],
                      '(objectclass=posixAccount)')

    self.assertEquals(group.source['base'],
                      'ou=group,dc=example,dc=com')
    self.assertEquals(group.source['filter'],
                      '(objectclass=posixGroup)')
예제 #10
0
파일: app.py 프로젝트: 3c2b2ff5/nsscache
    def Run(self, args, env):
        """Begin execution of nsscache.

        This method loads our runtime configuration, instantiates the
        appropriate Source and Cache objects, and invokes the
        appropriate method based on the command given.

        NOTE:  We avoid calling sys.exit() and instead return an int
        to our caller, who will exit with that status.

        Args:
          args: list of command line arguments
          env: dictionary of environment variables

        Returns:
          POSIX exit status
        """
        # Parse the commandline.
        try:
            (options, args) = self.parser.parse_args(args)
        except SystemExit as e:
            # OptionParser objects raise SystemExit (error() calls exit()
            # calls sys.exit()) upon a parser error.
            # This can be handled better by overriding error or monkeypatching
            # our parser.
            return e.code
        # Initialize a configuration object.
        conf = config.Config(env)

        # Process the global flags.
        if options.verbose:
            logger = logging.getLogger()
            logger.setLevel(logging.INFO)
        if options.debug:
            logger = logging.getLogger()
            logger.setLevel(logging.DEBUG)
        if options.config_file:
            conf.config_file = options.config_file

        self.log.info('using nss_cache library, version %s',
                      nss_cache.__version__)
        self.log.debug('library path is %r', nss_cache.__file__)

        # Identify the command to dispatch.
        if not args:
            print('No command given')
            self.parser.print_help()
            return os.EX_USAGE
        # print global help if command is 'help' with no argument
        if len(args) == 1 and args[0] == 'help':
            self.parser.print_help()
            return os.EX_OK
        self.log.debug('args: %r' % args)
        command_name = args.pop(0)
        self.log.debug('command: %r' % command_name)

        # Load the configuration from file.
        config.LoadConfig(conf)

        # Dispatch the command.
        try:
            command_callable = getattr(command, command_name.capitalize())
        except AttributeError:
            self.log.warning('%s is not implemented', command_name)
            print(('command %r is not implemented' % command_name))
            self.parser.print_help()
            return os.EX_SOFTWARE

        try:
            retval = command_callable().Run(conf=conf, args=args)
        except error.SourceUnavailable as e:
            self.log.error('Problem with configured data source: %s', e)
            return os.EX_TEMPFAIL

        return retval
예제 #11
0
class NssCacheApp(object):
    """Main application for building/updating NSS caches."""
    def __init__(self):
        """Set up the application.

    See the file README.style for logging policy set up here.
    """
        # default to syslog unless on a tty
        if os.isatty(sys.stdin.fileno()):
            format_str = ('%(levelname)-8s %(asctime)-15s '
                          '%(filename)s:%(lineno)d: '
                          '%(funcName)s: '
                          '%(message)s')
            logging.basicConfig(format=format_str)
            # python2.3's basicConfig doesn't let you set the default level
            logger = logging.getLogger()
            logger.setLevel(logging.WARN)
        else:
            facility = logging.handlers.SysLogHandler.LOG_DAEMON
            try:
                handler = logging.handlers.SysLogHandler(address='/dev/log',
                                                         facility=facility)
            except socket.error:
                print '/dev/log could not be opened; falling back on stderr.'
                # Omitting an argument to StreamHandler results in sys.stderr being
                # used.
                handler = logging.StreamHandler()
            format_str = (os.path.basename(sys.argv[0]) +
                          '[%(process)d]: %(levelname)s %(message)s')
            fmt = logging.Formatter(format_str)
            handler.setFormatter(fmt)
            handler.setLevel(level=logging.INFO)
            logging.getLogger('').addHandler(handler)

        self.log = logging.getLogger('NSSCacheApp')
        self.parser = self._GetParser()

    def _GetParser(self):
        """Sets up our parser for global options.

    Args:  None
    Returns:
    # OptionParser is from standard python module optparse
    OptionParser
    """
        usage = ('nsscache synchronises a local NSS cache against a '
                 'remote data source.\n'
                 '\n'
                 'Usage: nsscache [global options] command [command options]\n'
                 '\n'
                 'commands:\n')
        command_descriptions = []
        for (name, cls) in command.__dict__.items():
            # skip the command base object
            if name == 'Command':
                continue
            if hasattr(cls, 'Help'):
                short_help = cls().Help(short=True)
                command_descriptions.append('  %-21s %.40s' %
                                            (name.lower(), short_help.lower()))

        usage += '\n'.join(command_descriptions)
        version_string = ('nsscache ' + nss_cache.__version__ + '\n'
                          '\n'
                          'Copyright (c) 2007 Google, Inc.\n'
                          'This is free software; see the source for copying '
                          'conditions.  There is NO\n'
                          'warranty; not even for MERCHANTABILITY or FITNESS '
                          'FOR A PARTICULAR PURPOSE.\n'
                          '\n'
                          'Written by Jamie Wilkinson and Vasilios Hoffman.')

        parser = optparse.OptionParser(usage, version=version_string)

        # We do not mix arguments and flags!
        parser.disable_interspersed_args()

        # Add options.
        parser.set_defaults(verbose=False, debug=False)
        parser.add_option('-v',
                          '--verbose',
                          action='store_true',
                          help='enable verbose output')
        parser.add_option('-d',
                          '--debug',
                          action='store_true',
                          help='enable debugging output')
        parser.add_option('-c',
                          '--config-file',
                          type='string',
                          help='read configuration from FILE',
                          metavar='FILE')

        # filthy monkeypatch hack to remove the prepended 'usage: '
        # TODO(jaq): we really ought to subclass OptionParser instead...
        old_get_usage = parser.get_usage

        def get_usage():
            return old_get_usage()[7:]

        parser.get_usage = get_usage

        return parser

    def Run(self, args, env):
        """Begin execution of nsscache.

    This method loads our runtime configuration, instantiates the
    appropriate Source and Cache objects, and invokes the
    appropriate method based on the command given.

    NOTE:  We avoid calling sys.exit() and instead return an int
    to our caller, who will exit with that status.

    Args:
      args: list of command line arguments
      env: dictionary of environment variables

    Returns:
      POSIX exit status
    """
        # Parse the commandline.
        try:
            (options, args) = self.parser.parse_args(args)
        except SystemExit, e:
            # OptionParser objects raise SystemExit (error() calls exit()
            # calls sys.exit()) upon a parser error.
            # This can be handled better by overriding error or monkeypatching
            # our parser.
            return e.code
        # Initialize a configuration object.
        conf = config.Config(env)

        # Process the global flags.
        if options.verbose:
            logger = logging.getLogger()
            logger.setLevel(logging.INFO)
        if options.debug:
            logger = logging.getLogger()
            logger.setLevel(logging.DEBUG)
        if options.config_file:
            conf.config_file = options.config_file

        self.log.info('using nss_cache library, version %s',
                      nss_cache.__version__)
        self.log.debug('library path is %r', nss_cache.__file__)

        # Identify the command to dispatch.
        if not args:
            print 'No command given'
            self.parser.print_help()
            return os.EX_USAGE
        # print global help if command is 'help' with no argument
        if len(args) == 1 and args[0] == 'help':
            self.parser.print_help()
            return os.EX_OK
        self.log.debug('args: %r' % args)
        command_name = args.pop(0)
        self.log.debug('command: %r' % command_name)

        # Load the configuration from file.
        config.LoadConfig(conf)

        # Dispatch the command.
        try:
            command_callable = getattr(command, command_name.capitalize())
        except AttributeError:
            self.log.warn('%s is not implemented', command_name)
            print 'command %r is not implemented' % command_name
            self.parser.print_help()
            return os.EX_SOFTWARE

        try:
            retval = command_callable().Run(conf=conf, args=args)
        except error.SourceUnavailable, e:
            self.log.error('Problem with configured data source: %s', e)
            return os.EX_TEMPFAIL