Пример #1
0
def listservers():

    OUT.notice('\n'.join(['apache',
                          'lighttpd',
                          'cherokee',
                          'nginx',
                          'gatling']))
Пример #2
0
    def read(self,
             config_owned  = 'config-files',
             server_owned  = 'server-owned-files',
             virtual_files = 'virtual',
             default_dirs  = 'default-owned'):
        '''
        Initialize the type cache.
        '''
        import WebappConfig.filetype

        server_files = []
        config_files = []

        if os.access(self.appdir() + '/' + config_owned, os.R_OK):
            flist = open(self.appdir() + '/' + config_owned)
            config_files = flist.readlines()

            OUT.debug('Identified config-protected files.', 7)

            flist.close()

        if os.access(self.appdir() + '/' + server_owned, os.R_OK):
            flist = open(self.appdir() + '/' + server_owned)
            server_files = flist.readlines()

            OUT.debug('Identified server-owned files.', 7)

            flist.close()

        self.__types = WebappConfig.filetype.FileType(config_files,
                                                      server_files,
                                                      virtual_files,
                                                      default_dirs)
Пример #3
0
    def filetype(self, filename, parent_type = ''):
        ''' Determine filetype for the given file.'''
        if self.__types:

            OUT.debug('Returning file type', 7)

            return self.__types.filetype(filename, parent_type)
Пример #4
0
def get_root(config):
    '''Returns the $ROOT variable'''
    if config.config.get('USER', 'package_manager') == "portage":
        try:
            import portage
        except ImportError as e:
            OUT.die("Portage libraries not found, quitting:\n%s" % e)

        return portage.settings['ROOT']

    elif config.config.get('USER', 'package_manager') == "paludis":
        cat = config.maybe_get('cat')
        pn  = config.maybe_get('pn')

        if cat and pn:
            cmd="cave print-id-environment-variable -b --format '%%v\n' --variable-name ROOT %s/%s" % (cat,pn)

            fi, fo, fe = os.popen3(cmd)
            fi.close()
            result_lines = fo.readlines()
            fo.close()
            fe.close()

            if result_lines[0].strip():
                return result_lines[0].strip()
            else:
                return '/'
        else:
            return '/'
    else:
        OUT.die("Unknown package manager: " + pm)
Пример #5
0
    def dirtype(self, directory, parent_type = ''):
        ''' Determine filetype for the given directory.'''
        if self.__types:

            OUT.debug('Returning directory type', 7)

            return self.__types.dirtype(directory, parent_type)
Пример #6
0
    def packageavail(self):
        '''
        Check to see whether the given package has been installed or not.

        These checks are carried out by using wrapper.py to facilitate
        distribution independant handling of the task.

        Outputs:
            0       - on success
            1       - package not found
            2       - no package to find
            3       - package isn't webapp-config compatible          '
        '''

        OUT.debug('Verifying package ' + self.package_name(), 6)

        # package_installed() does not handle "/PN" correctly
        package = self.pn

        if self.category:
            package = self.category + '/' + self.pn

            # not using self.package_name() here as we don't need pvr
            return 1

        # unfortunately, just because a package has been installed, it
        # doesn't mean that the package itself is webapp-compatible
        #
        # we need to check that the package has an entry in the
        # application repository

        if not self.appdb():
            return 3
        else:
            return 0
Пример #7
0
    def filetype(self, filename):
        ''' Determine filetype for the given file.'''
        if self.__types:

            OUT.debug('Returning file type', 7)

            return self.__types.filetype(filename)
Пример #8
0
    def dirisconfigprotected(self, installdir):
        '''
        Traverses the path of parent directories for the
        given install dir and checks if any matches the list
        of config protected files.

        >>> a = Protection('','horde','3.0.5','portage')

        Add a virtual config protected directory:

        >>> a.config_protect += ' /my/strange/htdocs/'
        >>> a.dirisconfigprotected('/my/strange/htdocs/where/i/installed/x')
        True
        >>> a.dirisconfigprotected('/my/strange/htdocs/where/i/installed/x/')
        True
        >>> a.config_protect += ' /my/strange/htdocs'
        >>> a.dirisconfigprotected('/my/strange/htdocs/where/i/installed/x')
        True
        >>> a.dirisconfigprotected('/my/strange/htdocs/where/i/installed/x/')
        True

        >>> a.config_protect += ' bad_user /my/strange/htdocs'
        >>> a.dirisconfigprotected('/my/bad_user/htdocs/where/i/installed/x')
        False
        >>> a.dirisconfigprotected('/my/strange/htdocs/where/i/installed/x/')
        True

        >>> a.dirisconfigprotected('/')
        False
        '''

        my_master = []
        for i in self.config_protect.split(' '):
            if i[0] == '/':
                if i[-1] == '/':
                    my_master.append(i[:-1])
                else:
                    my_master.append(i)

        if installdir[0] != '/':
            OUT.die('BUG! Don\'t call this with a relative path.')

        if installdir[-1] == '/':
            my_dir = installdir[:-1]
        else:
            my_dir = installdir

        while my_dir:

            if my_dir == '.' or my_dir == '/':
                return False

            for x in my_master:
                if my_dir == x:
                    return True

            my_dir = os.path.dirname(my_dir)

        # nope, the directory isn't config-protected at this time
        return False
Пример #9
0
    def how_to_update(self, dirs):
        '''
        Instruct the user how to update the application.
        '''
        my_command = self.update_command

        directories = []

        for i in dirs:
            present = False
            if directories:
                for j in directories:
                    if (i == j[:len(i)] or j == i[:len(j)]):
                        present = True
                        break
            if not present:
                directories.append(i)

        my_command_list = ''

        for i in directories:
            if not self.dirisconfigprotected(i):
                my_command_list += 'CONFIG_PROTECT="' + i + '" ' + my_command + '\n'

        if not my_command_list:
            my_command_list = my_command

        OUT.warn(
            'One or more files have been config protected\nTo comple'
            'te your install, you need to run the following command(s):\n\n' +
            my_command_list)
Пример #10
0
    def read(self,
             config_owned='config-files',
             server_owned='server-owned-files',
             virtual_files='virtual',
             default_dirs='default-owned'):
        '''
        Initialize the type cache.
        '''
        import WebappConfig.filetype

        server_files = []
        config_files = []

        if os.access(self.appdir() + '/' + config_owned, os.R_OK):
            flist = open(self.appdir() + '/' + config_owned)
            config_files = flist.readlines()

            OUT.debug('Identified config-protected files.', 7)

            flist.close()

        if os.access(self.appdir() + '/' + server_owned, os.R_OK):
            flist = open(self.appdir() + '/' + server_owned)
            server_files = flist.readlines()

            OUT.debug('Identified server-owned files.', 7)

            flist.close()

        self.__types = WebappConfig.filetype.FileType(config_files,
                                                      server_files,
                                                      virtual_files,
                                                      default_dirs)
Пример #11
0
    def read(self):
        ''' Read the contents of the dot config file.'''
        dotconfig = self.__dot_config()

        OUT.debug('Checking for dotconfig ', 6)

        if not self.has_dotconfig():
            raise Exception('Cannot read file ' + dotconfig)

        tokens = shlex.shlex(open(dotconfig))

        while True:
            a = tokens.get_token()
            b = tokens.get_token()
            c = tokens.get_token()

            OUT.debug('Reading token', 8)

            if (a in self.__tokens and
                b == '=' and c):

                if c[0] == '"':
                    c = c[1:]

                if c[-1] == '"':
                    c = c[:-1]

                self.__data[a] = c

            else:
                break
Пример #12
0
    def how_to_update(self, dirs):
        '''
        Instruct the user how to update the application.
        '''
        my_command = self.update_command

        directories = []

        for i in dirs:
            present = False
            if directories:
                for j in directories:
                    if (i == j[:len(i)] or 
                        j == i[:len(j)]):
                        present = True
                        break
            if not present:
                directories.append(i)

        my_command_list = ''

        for i in directories:
            if not self.dirisconfigprotected(i):
                my_command_list += 'CONFIG_PROTECT="' + i + '" ' + my_command + '\n'

        if not my_command_list:
            my_command_list = my_command

        OUT.warn('One or more files have been config protected\nTo comple'
                 'te your install, you need to run the following command(s):\n\n'
                 + my_command_list)
Пример #13
0
    def test_add_rm(self):
        OUT.color_off()
        db = WebappDB(root='/'.join((HERE, 'testfiles', 'webapps')),
                      pretend=True,
                      package='horde',
                      version='3.0.5')
        # Test adding:
        db.add('/'.join(('/screwy', 'wonky', 'foobar', 'horde', 'hierarchy')),
               user='******',
               group='me')
        output = sys.stdout.getvalue().split('\n')
        self.assertEqual(output[0], '* Pretended to append installation '\
                                    '/screwy/wonky/foobar/horde/hierarchy')

        # Test deleting a webapp that is actually in the database:
        db.remove('/'.join(('/var', 'www', 'localhost', 'htdocs', 'horde')))
        output = sys.stdout.getvalue().split('\n')
        self.assertEqual(output[6], '* ')

        # And now test deleting one that isn't:
        db.remove('/'.join(
            ('/screwy', 'wonky', 'foobar', 'horde', 'hierarchy')))
        output = sys.stdout.getvalue().split('\n')
        self.assertEqual(output[11], '* 1124612110 root root '\
                                     '/var/www/localhost/htdocs/horde')
Пример #14
0
    def packageavail(self):
        '''
        Check to see whether the given package has been installed or not.

        These checks are carried out by using wrapper.py to facilitate
        distribution independant handling of the task.

        Outputs:
            0       - on success
            1       - package not found
            2       - no package to find
            3       - package isn't webapp-config compatible          '
        '''

        OUT.debug('Verifying package ' + self.package_name(), 6)

        # package_installed() does not handle "/PN" correctly
        package = self.pn

        if self.category:
            package = self.category + '/' + self.pn

        # not using self.package_name() here as we don't need pvr
            return 1

        # unfortunately, just because a package has been installed, it
        # doesn't mean that the package itself is webapp-compatible
        #
        # we need to check that the package has an entry in the
        # application repository

        if not self.appdb():
            return 3
        else:
            return 0
Пример #15
0
    def dirtype(self, directory):
        ''' Determine filetype for the given directory.'''
        if self.__types:

            OUT.debug('Returning directory type', 7)

            return self.__types.dirtype(directory)
Пример #16
0
    def remove(self, entry):
        '''
        Decide whether to delete something - and then go ahead and do so

        Just like portage, we only remove files that have not changed
        from when we installed them.  If the timestamp or checksum is
        different, we leave the file in place.

        Inputs

          entry    - file/dir/sym to remove
        '''

        OUT.debug('Trying to remove file', 6)

        # okay, deal with the file | directory | symlink

        removeable = self.__content.get_canremove(entry)

        if not removeable:

            # Remove directory or file.

            # Report if we are only pretending
            if self.__p:
                OUT.info('    pretending to remove: ' + entry)

            # try to remove the entry
            try:
                entry_type = self.__content.etype(entry)
                if self.__content.etype(entry) == 'dir':
                    # its a directory -> rmdir
                    if not self.__p:
                        os.rmdir(entry)
                else:
                    # its a file -> unlink
                    if not self.__p:
                        os.unlink(entry)
            except:
                # Report if there is a problem
                OUT.notice('!!!      '
                           + self.__content.epath(entry))
                return

            if self.__v and not self.__p:
                # Report successful deletion

                OUT.notice('<<< ' + entry_type + ' '
                           * (5 - len(entry_type))
                           + self.__content.epath(entry))

            self.__content.delete(entry)

            return True

        else:

            OUT.notice(removeable)

            return False
Пример #17
0
    def show_postinst(self, server = None):
        '''
        Display any post-installation instructions, if there are any.
        '''

        OUT.debug('Running show_postinst', 6)

        self.show_post(filename = 'postinst-en.txt', ptype = 'install', server = server)
Пример #18
0
    def test_read_corrupt(self):
        contents = Contents('/'.join((HERE, 'testfiles', 'contents')),
                            package = 'test', version = '1.1')

        OUT.color_off()
        contents.read()
        output = sys.stdout.getvalue().split('\n')
        self.assertEqual(output[12], '* Not enough entries.')
Пример #19
0
    def show_postupgrade(self, server = None):
        '''
        Display any post-upgrade instructions, if there are any.
        '''

        OUT.debug('Running show_postupgrade', 6)

        self.show_post(filename = 'postupgrade-en.txt', ptype = 'upgrade', server = server)
Пример #20
0
    def __init__(self, directories, permissions, handler, flags, pm):

        if self.dep and not self.supported(pm):
            print(self.dep)
            OUT.die('Your configuration file sets the server type "' +
                    self.name +
                    '"\nbut the corresponding package does not seem to be '
                    'installed!\nPlease "emerge ' + self.dep + '" or correct '
                    'your settings.')

        try:
            self.set_server_user()
        except KeyError:
            OUT.die('The user for the server type "' + self.name +
                    '" does not exist!')

        self.__sourced = directories['source']
        self.__destd = directories['destination']
        self.__hostroot = directories['hostroot']
        self.__vhostroot = directories['vhostroot']

        # + server owned
        if permissions['file']['server-owned'][0] == 0:
            permissions['file']['server-owned'][0] = self.vhost_server_uid
            permissions['dir']['server-owned'][0] = self.vhost_server_uid
        if permissions['file']['server-owned'][1] == 0:
            permissions['file']['server-owned'][1] = self.vhost_server_gid
            permissions['dir']['server-owned'][1] = self.vhost_server_gid
            # and config owned directories have server gid
            permissions['dir']['config-owned'][1] = self.vhost_server_gid
            # allows server and config owned
            permissions['file']['config-server-owned'][
                1] = self.vhost_server_gid
            permissions['dir']['config-server-owned'][
                1] = self.vhost_server_gid

        self.__perm = permissions
        self.__handler = handler
        self.__flags = flags

        self.__ws = handler['source']
        self.__content = handler['content']
        self.__protect = handler['protect']
        self.__dotconfig = handler['dotconfig']
        self.__ebuild = handler['ebuild']
        self.__db = handler['db']

        self.__v = flags['verbose']
        self.__p = flags['pretend']

        wd = WebappRemove(self.__content, self.__v, self.__p)

        handler['removal'] = wd

        self.__del = wd

        # Set by the install function
        self.__add = None
Пример #21
0
    def remove(self, entry):
        '''
        Decide whether to delete something - and then go ahead and do so

        Just like portage, we only remove files that have not changed
        from when we installed them.  If the timestamp or checksum is
        different, we leave the file in place.

        Inputs

          entry    - file/dir/sym to remove
        '''

        OUT.debug('Trying to remove file', 6)

        # okay, deal with the file | directory | symlink

        removeable = self.__content.get_canremove(entry)

        if not removeable:

            # Remove directory or file.

            # Report if we are only pretending
            if self.__p:
                OUT.info('    pretending to remove: ' + entry)

            # try to remove the entry
            try:
                entry_type = self.__content.etype(entry)
                if self.__content.etype(entry) == 'dir':
                    # its a directory -> rmdir
                    if not self.__p:
                        os.rmdir(entry)
                else:
                    # its a file -> unlink
                    if not self.__p:
                        os.unlink(entry)
            except:
                # Report if there is a problem
                OUT.notice('!!!      ' + self.__content.epath(entry))
                return

            if self.__v and not self.__p:
                # Report successful deletion

                OUT.notice('<<< ' + entry_type + ' ' * (5 - len(entry_type)) +
                           self.__content.epath(entry))

            self.__content.delete(entry)

            return True

        else:

            OUT.notice(removeable)

            return False
Пример #22
0
    def test_add(self):
        loc = '/'.join((HERE, 'testfiles', 'contents', 'app'))
        contents = Contents(loc, package='test', version='1.0')
        OUT.color_off()
        contents.add('file',
                     'config_owned',
                     destination=loc,
                     path='/test1',
                     real_path=loc + '/test1',
                     relative=True)

        # Now trigger an error by adding a file that doesn't exist!
        contents.add('file',
                     'config_owned',
                     destination=loc,
                     path='/test0',
                     real_path=loc + '/test0',
                     relative=True)

        output = sys.stdout.getvalue().strip('\n')

        self.assertTrue('WebappConfig/tests/testfiles/contents/app/test0 to '\
                        'add it as installation content. This should not '\
                        'happen!' in output)

        # Test adding hardlinks:
        contents.add('hardlink',
                     'config_owned',
                     destination=loc,
                     path='/test2',
                     real_path=loc + '/test2',
                     relative=True)
        self.assertTrue(
            'file 1 config_owned "test2" ' in contents.entry(loc + '/test2'))
        # Test adding dirs:
        contents.add('dir',
                     'default_owned',
                     destination=loc,
                     path='/dir1',
                     real_path=loc + '/dir1',
                     relative=True)
        self.assertTrue(
            'dir 1 default_owned "dir1" ' in contents.entry(loc + '/dir1'))

        # Test adding symlinks:
        contents.add('sym',
                     'virtual',
                     destination=loc,
                     path='/test3',
                     real_path=loc + '/test3',
                     relative=True)
        self.assertTrue('sym 1 virtual "test3" ' in contents.entry(loc +
                                                                   '/test3'))

        # Printing out the db after adding these entries:
        contents.db_print()
        output = sys.stdout.getvalue().split('\n')
        self.assertTrue('file 1 config_owned "test1" ' in output[1])
Пример #23
0
def listservers():

    OUT.notice('\n'.join(['apache',
                          'lighttpd',
                          'cherokee',
                          'nginx',
                          'gatling',
                          'hiawatha',
                          'tracd',]))
Пример #24
0
    def test_read_corrupt(self):
        contents = Contents('/'.join((HERE, 'testfiles', 'contents')),
                            package='test',
                            version='1.1')

        OUT.color_off()
        contents.read()
        output = sys.stdout.getvalue().split('\n')
        self.assertEqual(output[12], '* Not enough entries.')
Пример #25
0
 def db_print(self):
     ''' Print all enties of the contents file.'''
     entries = self.get_sorted_files()
     values = []
     for i in entries:
         # Fix relative entry
         s = self.__content[i]
         s[1] = str(int(s[1]))
         values.append(' '.join(s))
     OUT.notice('\n'.join(values))
Пример #26
0
    def show_postupgrade(self, server=None):
        '''
        Display any post-upgrade instructions, if there are any.
        '''

        OUT.debug('Running show_postupgrade', 6)

        self.show_post(filename='postupgrade-en.txt',
                       ptype='upgrade',
                       server=server)
Пример #27
0
    def show_postinst(self, server=None):
        '''
        Display any post-installation instructions, if there are any.
        '''

        OUT.debug('Running show_postinst', 6)

        self.show_post(filename='postinst-en.txt',
                       ptype='install',
                       server=server)
Пример #28
0
def listservers():

    OUT.notice('\n'.join([
        'apache',
        'lighttpd',
        'cherokee',
        'nginx',
        'gatling',
        'tracd',
    ]))
Пример #29
0
 def db_print(self):
     ''' Print all enties of the contents file.'''
     entries = self.get_sorted_files()
     values = []
     for i in entries:
         # Fix relative entry
         s = self.__content[i]
         s[1] = str(int(s[1]))
         values.append(' '.join(s))
     OUT.notice('\n'.join(values))
Пример #30
0
    def test_add_pretend(self):
        loc = '/'.join((HERE, 'testfiles', 'contents', 'app'))
        contents = Contents(loc, package = 'test', version = '1.0',
                            pretend = True)
        OUT.color_off()
        contents.add('file', 'config_owned', destination = loc, path = '/test1',
                     real_path = loc + '/test1', relative = True)

        output = sys.stdout.getvalue().strip('\n')
        self.assertEqual(output,
                       '*     pretending to add: file 1 config_owned "test1"')
Пример #31
0
    def remove_files(self):
        '''
        It is time to remove the files that we installed originally.
        '''

        OUT.debug('Trying to remove files', 6)

        success = [self.remove(i) for i in self.__content.get_files()]

        # Tell the caller if anything was left behind

        return all(success)
Пример #32
0
    def remove_files(self):
        '''
        It is time to remove the files that we installed originally.
        '''

        OUT.debug('Trying to remove files', 6)

        success = [self.remove(i) for i in self.__content.get_files()]

        # Tell the caller if anything was left behind

        return all(success)
Пример #33
0
    def test_remove_files(self):
        OUT.color_off()
        contents = Contents('/'.join((HERE, 'testfiles', 'contents', 'app2')),
                            package = 'test', version = '1.0', pretend = True)
        contents.read()
        webrm = WebappRemove(contents, True, True)
        webrm.remove_files()

        output = sys.stdout.getvalue().split('\n')
        self.assertEqual(output[3], '*     pretending to remove: ' +
                         '/'.join((HERE, 'testfiles', 'contents', 'app2',
                                   'test3')))
Пример #34
0
    def packagename(self):
        ''' Retrieve the package name from the values specified in the dot
        config file'''

        OUT.debug('Trying to retrieve package name', 6)

        if 'WEB_PN' in list(self.__data.keys()) and 'WEB_PVR' in list(self.__data.keys()):
            if 'WEB_CATEGORY' in list(self.__data.keys()):
                return self.__data['WEB_CATEGORY'] + '/' + \
                    self.__data['WEB_PN'] + '-' + self.__data['WEB_PVR']
            else:
                return self.__data['WEB_PN'] + '-' + self.__data['WEB_PVR']
        return ''
Пример #35
0
def want_category(config):
    '''Check if the package manager requires category info

    Portage: optional
    Paludis: mandatory
    '''

    if config.config.get('USER', 'package_manager') == "portage":
        return
    elif config.config.get('USER', 'package_manager') == "paludis":
        if not config.config.has_option('USER', 'cat'):
            OUT.die("Package name must be in the form CAT/PN")
    else:
        OUT.die("Unknown package manager: " + pm)
Пример #36
0
    def test_write(self):
        contents = Contents('/'.join((HERE, 'testfiles', 'contents')),
                            package = 'test', version = '1.0', pretend = True)
        OUT.color_off()
        contents.read()

        contents.write()
        output = sys.stdout.getvalue().split('\n')

        expected = '* Would have written content file ' + '/'.join((HERE,
                                                          'testfiles',
                                                          'contents',
                                                          '.webapp-test-1.0!'))
        self.assertEqual(output[0], expected)
Пример #37
0
    def has_dotconfig(self):
        ''' Return True if the install location already has a dotconfig
        file.'''
        dotconfig = self.__dot_config()

        OUT.debug('Verifying path', 7)

        if not os.path.isfile(dotconfig):
            return False

        if not os.access(dotconfig, os.R_OK):
            return False

        return True
Пример #38
0
    def test_remove_files(self):
        OUT.color_off()
        contents = Contents('/'.join((HERE, 'testfiles', 'contents', 'app2')),
                            package='test',
                            version='1.0',
                            pretend=True)
        contents.read()
        webrm = WebappRemove(contents, True, True)
        webrm.remove_files()

        output = sys.stdout.getvalue().split('\n')
        self.assertEqual(
            output[3], '*     pretending to remove: ' + '/'.join(
                (HERE, 'testfiles', 'contents', 'app2', 'test3')))
Пример #39
0
    def listunused(self, db):
        '''
        Outputs a list of what has not been installed so far
        '''

        packages = self.list_locations()

        if not packages:
            OUT.die('No packages found!')

        keys = sorted(packages)

        OUT.debug('Check for unused web applications', 7)

        for i in keys:

            db.set_category(packages[i][0])
            db.set_package(packages[i][1])
            db.set_version(packages[i][2])

            if not db.has_installs():
                if packages[i][0]:
                    OUT.notice(packages[i][0] + '/' + packages[i][1] + '-' +
                               packages[i][2])
                else:
                    OUT.notice(packages[i][1] + '-' + packages[i][2])
Пример #40
0
    def listunused(self, db):
        '''
        Outputs a list of what has not been installed so far
        '''

        packages = self.list_locations()

        if not packages:
            OUT.die('No packages found!')

        keys = sorted(packages)

        OUT.debug('Check for unused web applications', 7)

        for i in keys:

            db.set_category(packages[i][0])
            db.set_package (packages[i][1])
            db.set_version (packages[i][2])

            if not db.has_installs():
                if packages[i][0]:
                    OUT.notice(packages[i][0] + '/' + packages[i][1] + '-' + packages[i][2])
                else:
                    OUT.notice(packages[i][1] + '-' + packages[i][2])
Пример #41
0
    def test_add_pretend(self):
        loc = '/'.join((HERE, 'testfiles', 'contents', 'app'))
        contents = Contents(loc, package='test', version='1.0', pretend=True)
        OUT.color_off()
        contents.add('file',
                     'config_owned',
                     destination=loc,
                     path='/test1',
                     real_path=loc + '/test1',
                     relative=True)

        output = sys.stdout.getvalue().strip('\n')
        self.assertEqual(
            output, '*     pretending to add: file 1 config_owned "test1"')
Пример #42
0
    def test_list_installs(self):
        OUT.color_off()
        db = WebappDB(root = '/'.join((HERE, 'testfiles', 'webapps')))

        db.listinstalls()
        output = sys.stdout.getvalue().split('\n')
        self.assertEqual(output[1], '/var/www/localhost/htdocs/horde')

        # Now test the verbosity:
        db = WebappDB(root = '/'.join((HERE, 'testfiles', 'webapps')),
                      verbose = True)
        db.listinstalls()
        output = sys.stdout.getvalue().split('\n')
        self.assertEqual(output[5], '* Installs for horde-3.0.5')
Пример #43
0
    def packageavail(self):
        '''
        Check to see whether the given package has been installed or not.

        These checks are carried out by using wrapper.py to facilitate
        distribution independant handling of the task.

        Outputs:
            0       - on success
            1       - package not found
            2       - no package to find
            3       - package isn't webapp-config compatible          '

        >>> import os.path
        >>> here = os.path.dirname(os.path.realpath(__file__))

        Does not exist:

        >>> a = WebappSource(root = here + '/tests/testfiles/share-webapps',
        ...             category='www-apps',package='nothere', version='1',pm='portage')
        >>> a.packageavail()
        1

        Incompatible cannot be tested since that would require a
        oackage (including version number) that is installed on
        all systems.
        '''

        OUT.debug('Verifying package ' + self.package_name(), 6)

        # package_installed() does not handle "/PN" correctly
        package = self.pn

        if self.category:
            package = self.category + '/' + self.pn

        # not using self.package_name() here as we don't need pvr
        if not wrapper.package_installed(package, self.pm):
            return 1

        # unfortunately, just because a package has been installed, it
        # doesn't mean that the package itself is webapp-compatible
        #
        # we need to check that the package has an entry in the
        # application repository

        if not self.appdb():
            return 3
        else:
            return 0
Пример #44
0
    def test_list_installs(self):
        OUT.color_off()
        db = WebappDB(root='/'.join((HERE, 'testfiles', 'webapps')))

        db.listinstalls()
        output = sys.stdout.getvalue().split('\n')
        self.assertEqual(output[1], '/var/www/localhost/htdocs/horde')

        # Now test the verbosity:
        db = WebappDB(root='/'.join((HERE, 'testfiles', 'webapps')),
                      verbose=True)
        db.listinstalls()
        output = sys.stdout.getvalue().split('\n')
        self.assertEqual(output[5], '* Installs for horde-3.0.5')
Пример #45
0
    def test_write(self):
        contents = Contents('/'.join((HERE, 'testfiles', 'contents')),
                            package='test',
                            version='1.0',
                            pretend=True)
        OUT.color_off()
        contents.read()

        contents.write()
        output = sys.stdout.getvalue().split('\n')

        expected = '* Would have written content file ' + '/'.join(
            (HERE, 'testfiles', 'contents', '.webapp-test-1.0!'))
        self.assertEqual(output[0], expected)
Пример #46
0
    def __init__(self,
                 config_owned,
                 server_owned,
                 server_owned_r,
                 virtual_files = 'virtual',
                 default_dirs  = 'default-owned'):
        '''
        Populates the cache with the file types as provided by the
        ebuild.
        '''

        self.__cache = {}

        # Validity of entries are checked by the command line parser
        self.__virtual_files = virtual_files
        self.__default_dirs  = default_dirs

        # populate cache
        for i in config_owned:

            OUT.debug('Adding config-owned file', 8)

            self.__cache[self.__fix(i)] = 'config-owned'

        for i in server_owned:

            if self.__fix(i) in self.__cache.keys():

                OUT.debug('Adding config-server-owned file', 8)

                self.__cache[self.__fix(i)] = 'config-server-owned'

            else:

                OUT.debug('Adding server-owned file', 8)

                self.__cache[self.__fix(i)] = 'server-owned'

        for i in server_owned_r:

            if self.__fix(i) in self.__cache.keys():

                OUT.die('{} is a the same time recursively server-owned and {}: This case is not supported.'.format(self.__fix(i), self.__cache[self.__fix(i)]))

            else :

                OUT.debug('Adding recursively server-owned file', 8)

                self.__cache[self.__fix(i).strip()] = 'server-owned-dir'
Пример #47
0
 def kill(self):
     ''' Remove the contents file.'''
     if not self.__p:
         try:
             dbpath = self.appdb()
             self.check_installdir()
             os.unlink(dbpath)
             self.__content = {}
             return True
         except:
             OUT.warn('Failed to remove ' + self.appdb() + '!')
             return False
     else:
         OUT.info('Would have removed ' + self.appdb())
         return True
Пример #48
0
 def kill(self):
     ''' Remove the contents file.'''
     if not self.__p:
         try:
             dbpath = self.appdb()
             self.check_installdir()
             os.unlink(dbpath)
             self.__content = {}
             return True
         except:
             OUT.warn('Failed to remove ' + self.appdb() + '!')
             return False
     else:
         OUT.info('Would have removed ' + self.appdb())
         return True
Пример #49
0
    def write(self,
              category,
              package,
              version,
              host,
              original_installdir,
              user_group):
        '''
        Output the .webapp file, that tells us in future what has been installed
        into this directory.
        '''
        self.__data['WEB_CATEGORY']      = category
        self.__data['WEB_PN']            = package
        self.__data['WEB_PVR']           = version
        self.__data['WEB_INSTALLEDBY']   = pwd.getpwuid(os.getuid())[0]
        self.__data['WEB_INSTALLEDDATE'] = strftime('%Y-%m-%d %H:%M:%S')
        self.__data['WEB_INSTALLEDFOR']  = user_group
        self.__data['WEB_HOSTNAME']      = host
        self.__data['WEB_INSTALLDIR']    = original_installdir


        info = ['# ' + self.__file,
                '#	config file for this copy of '
                + package + '-' + version,
                '#',
                '#	automatically created by Gentoo\'s webapp-config',
                '#	do NOT edit this file by hand',
                '',]
        for i in self.__tokens:
            info.append(i + '="' + self.__data[i] + '"')

        if not self.__p:
            try:

                fd = os.open(self.__dot_config(),
                             os.O_WRONLY | os.O_CREAT,
                             self.__perm(0o600))

                os.write(fd, ('\n'.join(info)).encode('utf-8'))
                os.close(fd)

            except Exception as e:

                OUT.die('Unable to write to ' + self.__dot_config()
                        + '\nError was: ' + str(e))
        else:
            OUT.info('Would have written the following information into '
                     + self.__dot_config() + ':\n' + '\n'.join(info))
Пример #50
0
    def dirtype(self, directory, parent_type = ''):
        '''
        Inputs:

          directory     - the directory that we need a decision about

          parent_type  - the type of the parent directory

        returns one of these:

          server-owned         - dir needs to be owned by the webserver user
          config-owned         - dir needs to be owned by the config user
          config-server-owned  - Both the previous cases at the same time
          server-owned-dir     - Directory that contains file/dirs to be owned
                                 by the webserver user
          default-owned        - we need a local copy, owned by root

        NOTE:
          Use get_filetype(filename) for files

        NOTE:
          the user can use --default-dirs on the command-line to change
          what type default directories are really reported as
        '''

        # remove any whitespace and trailing /
        directory = self.__fix(directory)

        # check the cache
        if directory in self.__cache.keys():
            # Check if parent type is recursive
            if parent_type == 'server-owned-dir':
                new_type = self.__cache[directory]
                if new_type == 'config-owned':
                    OUT.die('This version does not support config dirs')
                if new_type == server-owned:
                    OUT.warn('Configuration error: {} is marked server-owned two times'.format(filename))
                return 'server-owned-dir'
            return self.__cache[directory]

        # Check if parent type is recursive
        if parent_type == 'server-owned-dir':
            return 'server-owned-dir'
        # unspecified directories are default-owned
        return self.__default_dirs
Пример #51
0
    def filetype(self, filename, parent_type = ''):
        '''
        Inputs:

          filename      - the file that we need a decision about

          parent_type  - the type of the parent directory

        returns one of these:

          server-owned         - file needs to be owned by the webserver user
                                 (and needs to be a local copy)
          config-owned         - file needs to be owned by the config user
                                 (and needs to be a local copy)
          config-server-owned  - Both the previous cases at the same time
          virtual              - we do not need a local copy of the file

        NOTE:
          Use get_dirtype(directory) for directories

        NOTE:
          the user can use --virtual-files on the command-line to change
          what type virtual files are really reported as
        '''

        # remove any whitespace and trailing /
        filename = self.__fix(filename)

        # check the cache
        if filename in self.__cache.keys():
            # Check if parent type is recursive
            if parent_type == 'server-owned-dir':
                new_type = self.__cache[filename]
                if new_type == 'config-owned':
                    return 'config-server-owned'
                if new_type == 'server-owned':
                    OUT.warn('Configuration error: {} is marked server-owned twice'.format(filename))
                return 'server-owned' 
            return self.__cache[filename]

        # Check if parent type is recursive
        if parent_type == 'server-owned-dir':
            return 'server-owned'
        # unspecified file (and thus virtual)
        return self.__virtual_files
Пример #52
0
    def list_locations(self):
        ''' List all available db files.'''

        OUT.debug('Retrieving hierarchy locations', 6)

        dbpath = self.appdb()

        if dbpath and os.path.isfile(dbpath):
            return {dbpath: [self.category, self.pn, self.pvr]}

        if dbpath and not os.path.isfile(dbpath):
            OUT.debug(
                'Package "' + self.package_name() +
                '" not listed in the hierarchy (file "' + dbpath +
                ' is missing)!', 8)
            return {}

        locations = {}
        packages = []

        if self.pn:
            packages.append(os.path.join(self.root, self.pn))
            if self.category:
                packages.append(os.path.join(self.root, self.category,
                                             self.pn))
        else:
            packages.extend(
                os.path.join(self.root, m) for m in os.listdir(self.root))
            for i in packages:
                if os.path.isdir(i):
                    packages.extend(os.path.join(i, m) for m in os.listdir(i))

        for i in packages:

            OUT.debug('Checking package', 8)

            if os.path.isdir(i):

                OUT.debug('Checking version', 8)

                versions = os.listdir(i)

                for j in versions:
                    appdir = os.path.join(i, j)
                    location = os.path.join(appdir, self.dbfile)
                    if (os.path.isdir(appdir) and os.path.isfile(location)):
                        pn = os.path.basename(i)
                        cat = os.path.basename(os.path.split(i)[0])
                        if cat == "webapps":
                            cat = ""
                        locations[location] = [cat, pn, j]

        return locations
Пример #53
0
    def test_how_to_update(self):
        OUT.color_off()
        pro = Protection('', 'horde', '3.0.5', 'portage')
        strange_htdocs = '/'.join(
            ('/my', 'strange', 'htdocs', 'where', 'i', 'installed', 'x'))
        pro.how_to_update([strange_htdocs])
        output = sys.stdout.getvalue().split('\n')

        self.assertEqual(
            output[3], '* CONFIG_PROTECT="' + strange_htdocs + '" etc-update')

        # Adding a virtual config protected directory:
        i = strange_htdocs.replace('/where/i/instaled/x', '')
        pro.config_protect += ' ' + i

        pro.how_to_update([strange_htdocs])
        output = sys.stdout.getvalue().split('\n')

        self.assertEqual(output[8], '* etc-update')
Пример #54
0
    def mkdirs(self, directory=''):
        '''
        Create a set of directories

        Inputs

        directory   - the directory within the source hierarchy
        '''

        sd = self.__sourced + '/' + directory
        real_dir = re.compile('/+').sub(
            '/',
            self.__ws.appdir() + '/' + self.__sourced + '/' + directory)

        OUT.debug('Creating directories', 6)

        if not self.__ws.source_exists(sd):

            OUT.warn(self.__ws.package_name() +
                     ' does not install any files from ' + real_dir +
                     '; skipping')
            return

        OUT.info('    Installing from ' + real_dir)

        for i in self.__ws.get_source_directories(sd):

            OUT.debug('Handling directory', 7)

            # create directory first
            self.mkdir(directory + '/' + i)

            # then recurse into the directory
            self.mkdirs(directory + '/' + i)

        for i in self.__ws.get_source_files(sd):

            OUT.debug('Handling file', 7)

            # handle the file
            self.mkfile(directory + '/' + i)