Esempio n. 1
0
def purge(opts):
    """Purge environment database and uploaded files

Usage:
  datacats purge [--delete-environment] [ENVIRONMENT]

Options:
  --delete-environment   Delete environment directory as well as its data

ENVIRONMENT may be an environment name or a path to an environment directory.
Default: '.'
"""
    try:
        environment = Environment.load(opts['ENVIRONMENT'])
    except DatacatsError as e:
        environment = Environment.load(opts['ENVIRONMENT'], data_only=True)

    environment.stop_web()
    environment.stop_postgres_and_solr()

    if opts['--delete-environment']:
        if not environment.target:
            print 'Failed to load environment.',
            print 'Not deleting environment directory.'
        else:
            environment.fix_project_permissions()
            rmtree(environment.target)

    environment.purge_data()
Esempio n. 2
0
def purge(opts):
    """Purge environment database and uploaded files

Usage:
  datacats purge [-s NAME | --delete-environment] [-y] [ENVIRONMENT]

Options:
  --delete-environment   Delete environment directory as well as its data, as
                         well as the data for **all** sites.
  -s --site=NAME         Specify a site to be purge [default: primary]
  -y --yes               Respond yes to all prompts (i.e. force)

ENVIRONMENT may be an environment name or a path to an environment directory.
Default: '.'
"""
    old = False
    try:
        environment = Environment.load(opts['ENVIRONMENT'], opts['--site'])
    except DatacatsError:
        environment = Environment.load(opts['ENVIRONMENT'],
                                       opts['--site'],
                                       data_only=True)
        if get_format_version(environment.datadir) == 1:
            old = True
            environment = Environment.load(opts['ENVIRONMENT'],
                                           opts['--site'],
                                           allow_old=True)

    # We need a valid site if they don't want to blow away everything.
    if not opts['--delete-environment'] and not old:
        environment.require_valid_site()

    sites = [opts['--site']
             ] if not opts['--delete-environment'] else environment.sites

    if not opts['--yes']:
        y_or_n_prompt('datacats purge will delete all stored data')

    environment.stop_ckan()
    environment.stop_supporting_containers()

    environment.purge_data(sites)

    if opts['--delete-environment']:
        if environment.target:
            rmtree(environment.target)
        else:
            DatacatsError(
                ("Unable to find the environment source"
                 " directory so that it can be deleted.\n"
                 "Chances are it's because it already does not exist"))
Esempio n. 3
0
def install(environment, opts):
    """Install or reinstall Python packages within this environment

Usage:
  datacats install [-cq] [--address=IP] [ENVIRONMENT]

Options:
  --address=IP          The address to bind to when reloading after install [default: 127.0.0.1]
  -c --clean            Reinstall packages into a clean virtualenv
  -q --quiet            Do not show output from installing packages and requirements.

ENVIRONMENT may be an environment name or a path to an environment directory.
Default: '.'
"""
    environment.require_data()
    install_all(environment, opts['--clean'], verbose=not opts['--quiet'])

    for site in environment.sites:
        environment = Environment.load(environment.name, site)
        if 'web' in environment.containers_running():
            # FIXME: reload without changing debug setting?
            manage.reload_(environment, {
                '--address': opts['--address'],
                '--background': False,
                '--no-watch': False,
                '--production': False,
                'PORT': None,
                '--syslog': False,
                '--site-url': None
                })
Esempio n. 4
0
def paster(opts):
    """Run a paster command from the current directory

Usage:
  datacats paster [-d] [-s NAME] [COMMAND...]

Options:
  -s --site=NAME   Specify a site to run this paster command on [default: primary]
  -d --detach       Run the resulting container in the background

You must be inside a datacats environment to run this. The paster command will
run within your current directory inside the environment. You don't need to
specify the --plugin option. The --config option also need not be specified.
"""
    environment = Environment.load('.')
    environment.require_data()
    environment.start_supporting_containers()

    if not opts['COMMAND']:
        opts['COMMAND'] = ['--', 'help']

    assert opts['COMMAND'][0] == '--'
    return environment.interactive_shell(
        opts['COMMAND'][1:],
        paster=True,
        detach=opts['--detach']
        )
Esempio n. 5
0
def paster(opts):
    """Run a paster command from the current directory

Usage:
  datacats paster [-d] [-s NAME] [COMMAND...]

Options:
  -s --site=NAME   Specify a site to run this paster command on [default: primary]
  -d --detach       Run the resulting container in the background

You must be inside a datacats environment to run this. The paster command will
run within your current directory inside the environment. You don't need to
specify the --plugin option. The --config option also need not be specified.
"""
    environment = Environment.load('.')
    environment.require_data()
    environment.start_supporting_containers()

    if not opts['COMMAND']:
        opts['COMMAND'] = ['--', 'help']

    assert opts['COMMAND'][0] == '--'
    return environment.interactive_shell(opts['COMMAND'][1:],
                                         paster=True,
                                         detach=opts['--detach'])
Esempio n. 6
0
def install(environment, opts):
    """Install or reinstall Python packages within this environment

Usage:
  datacats install [-cq] [--address=IP] [ENVIRONMENT]

Options:
  --address=IP          The address to bind to when reloading after install
  -c --clean            Reinstall packages into a clean virtualenv
  -q --quiet            Do not show output from installing packages and requirements.

ENVIRONMENT may be an environment name or a path to an environment directory.
Default: '.'
"""
    environment.require_data()
    install_all(environment, opts['--clean'], verbose=not opts['--quiet'])

    for site in environment.sites:
        environment = Environment.load(environment.name, site)
        if 'web' in environment.containers_running():
            # FIXME: reload without changing debug setting?
            manage.reload_(environment, {
                '--address': opts['--address'],
                '--background': False,
                '--no-watch': False,
                '--production': False,
                'PORT': None,
                '--syslog': False,
                '--site-url': None
                })
Esempio n. 7
0
def purge(opts):
    """Purge environment database and uploaded files

Usage:
  datacats purge [-s NAME | --delete-environment] [-y] [ENVIRONMENT]

Options:
  --delete-environment   Delete environment directory as well as its data, as
                         well as the data for **all** sites.
  -s --site=NAME         Specify a site to be purge [default: primary]
  -y --yes               Respond yes to all prompts (i.e. force)

ENVIRONMENT may be an environment name or a path to an environment directory.
Default: '.'
"""
    old = False
    try:
        environment = Environment.load(opts['ENVIRONMENT'], opts['--site'])
    except DatacatsError:
        environment = Environment.load(opts['ENVIRONMENT'], opts['--site'], data_only=True)
        if get_format_version(environment.datadir) == 1:
            old = True
            environment = Environment.load(opts['ENVIRONMENT'], opts['--site'], allow_old=True)

    # We need a valid site if they don't want to blow away everything.
    if not opts['--delete-environment'] and not old:
        environment.require_valid_site()

    sites = [opts['--site']] if not opts['--delete-environment'] else environment.sites

    if not opts['--yes']:
        y_or_n_prompt('datacats purge will delete all stored data')

    environment.stop_ckan()
    environment.stop_supporting_containers()

    environment.purge_data(sites)

    if opts['--delete-environment']:
        if environment.target:
            rmtree(environment.target)
        else:
            DatacatsError(("Unable to find the environment source"
            " directory so that it can be deleted.\n"
            "Chances are it's because it already does not exist"))
Esempio n. 8
0
def create_environment(environment_dir, port, ckan_version, create_skin,
        site_name, start_web, create_sysadmin, address, log_syslog=False,
        datapusher=True, quiet=False, site_url=None, interactive=False,
        init_db=True):

    if not init_db:
        print 'Since the database will not be initialized, we will not copy datapusher.'
        datapusher = False
    environment = Environment.new(environment_dir, ckan_version, site_name,
                                  address=address, port=port)

    try:
        # There are a lot of steps we can/must skip if we're making a sub-site only
        making_full_environment = not environment.data_exists()

        if not quiet:
            write('Creating environment "{0}/{1}"'.format(environment.name, environment.site_name))
        steps = [
            lambda: environment.create_directories(making_full_environment),
            environment.create_bash_profile
            ] + \
            ([
                environment.create_virtualenv,
                environment.save,
                lambda: environment.create_source(datapusher),
                environment.create_ckan_ini] if making_full_environment else []
            ) + \
            [
                environment.save_site,
                environment.start_supporting_containers,
                environment.fix_storage_permissions,
                lambda: environment.update_ckan_ini(skin=create_skin),
            ]

        if create_skin and making_full_environment:
            steps.append(environment.create_install_template_skin)

        for fn in steps:
            fn()
            if not quiet:
                write('.')
        if not quiet:
            write('\n')

        return finish_init(environment, start_web, create_sysadmin,
                           log_syslog=log_syslog, site_url=site_url,
                           interactive=interactive, init_db=init_db)
    except:
        # Make sure that it doesn't get printed right after the dots
        # by printing a newline
        # i.e. Creating environment 'hello'.....ERROR MESSAGE
        if not quiet:
            print
        raise
Esempio n. 9
0
def main():
    args = sys.argv[1:]
    help_ = False
    # Find subcommand without docopt so that subcommand options may appear
    # anywhere
    for i, a in enumerate(args):
        if a.startswith('-'):
            continue
        if a == 'help':
            help_ = True
            continue
        command_fn = COMMANDS.get(a)
        break
    else:
        if help_:
            args = ['--help']
        return docopt(__doc__, args,
            version=pkg_resources.require("datacats")[0].version)
    if not command_fn:
        return docopt(__doc__, ['--help'])

    # shell, paster are special: options might belong to the command being
    # executed
    if command_fn == shell.shell:
        # assume commands don't start with '-' and that those options
        # are intended for datacats
        for j, a in enumerate(args[i + 2:], i + 2):
            if not a.startswith('-'):
                # -- makes docopt parse the rest as positional args
                args = args[:j] + ['--'] + args[j:]
                break

    if command_fn == shell.paster:
        args = args[:i + 1] + ['--'] + args[i + 1:]

    if help_:
        args.insert(1, '--help')

    try:
        opts = docopt(command_fn.__doc__, args)

        option_not_yet_implemented(opts, '--ckan')
        option_not_yet_implemented(opts, '--remote')

        # purge handles loading differently
        if command_fn != purge.purge and 'ENVIRONMENT' in opts:
            environment = Environment.load(opts['ENVIRONMENT'] or '.')
            return command_fn(environment, opts)
        return command_fn(opts)
    except DatacatsError as e:
        print e
        return 1
Esempio n. 10
0
def main():
    """
    The main entry point for datacats cli tool

    (as defined in setup.py's entry_points)
    It parses the cli arguments for corresponding options
    and runs the corresponding command
    """
    # pylint: disable=bare-except
    try:
        command_fn, opts = _parse_arguments(sys.argv[1:])
        # purge handles loading differently
        # 1 - Bail and just call the command if it doesn't have ENVIRONMENT.
        if command_fn == purge.purge or 'ENVIRONMENT' not in opts:
            return command_fn(opts)

        environment = Environment.load(
            opts['ENVIRONMENT'] or '.',
            opts['--site'] if '--site' in opts else 'primary')

        if command_fn not in COMMANDS_THAT_USE_SSH:
            return command_fn(environment, opts)

        # for commands that communicate with a remote server
        # we load UserProfile and test our communication
        user_profile = UserProfile()
        user_profile.test_ssh_key(environment)

        return command_fn(environment, opts, user_profile)

    except DatacatsError as e:
        _error_exit(e)
    except SystemExit:
        raise
    except:
        exc_info = "\n".join([line.rstrip()
            for line in traceback.format_exception(*sys.exc_info())])
        user_message = ("Something that should not"
            " have happened happened when attempting"
            " to run this command:\n"
            "     datacats {args}\n\n"
            "It is seems to be a bug.\n"
            "Please report this issue to us by"
            " creating an issue ticket at\n\n"
            "    https://github.com/datacats/datacats/issues\n\n"
            "so that we would be able to look into that "
            "and fix the issue."
            ).format(args=" ".join(sys.argv[1:]))

        _error_exit(DatacatsError(user_message,
            parent_exception=UndocumentedError(exc_info)))
Esempio n. 11
0
        def wrapper():
            if 'name' not in request.values:
                site_name = 'primary'
            else:
                site_name = request.values.get('name')

            try:
                environment = Environment.load(MAIN_ENV_NAME, site_name)

                if require_valid_site:
                    environment.require_valid_site()

                return func(environment)
            except DatacatsError as e:
                return jsonify({'error': str(e)}), CLIENT_ERROR_CODE
Esempio n. 12
0
def paster(opts):
    """Run a paster command from the current directory

Usage:
  datacats paster [COMMAND...]

You must be inside a datacats environment to run this. The paster command will
run within your current directory inside the environment. You don't need to
specify the --plugin option. The --config option also need not be specified.
"""
    environment = Environment.load('.')
    environment.require_data()
    environment.start_postgres_and_solr()

    assert opts['COMMAND'][0] == '--'
    return environment.interactive_shell(opts['COMMAND'][1:], paster=True)
Esempio n. 13
0
    def __init__(self, name, display_name, finished_create=True, sort=True):
        """
        Initializes a site object. Also places it into the global `sites` list.

        :param name: The name of the site to be created.
        :param display_name: The name of the site to be shown to the user.
        :param sort: True if we should maintain the sorted order of the `sites` list.
                     For all uses except internal ones this should ALWAYS be True or
                     Bad Things Will Happen (TM).
        """
        self.name = name
        self.display_name = display_name
        self.environment = Environment.load(MAIN_ENV_NAME, name)
        self.port = self.environment.port
        self.finished_create = finished_create
        self.celery_task = None
Esempio n. 14
0
def init(opts):
    """Initialize a purged environment or copied environment directory

Usage:
  datacats init [-in] [ENVIRONMENT_DIR [PORT]]

Options:
  -i --image-only         Create the environment but don't start containers
  -n --no-sysadmin        Don't prompt for an initial sysadmin user account

ENVIRONMENT_DIR is an existing datacats environment directory. Defaults to '.'
"""
    environment_dir = opts['ENVIRONMENT_DIR']
    port = opts['PORT']
    start_web = not opts['--image-only']
    create_sysadmin = not opts['--no-sysadmin']

    environment_dir = abspath(environment_dir or '.')
    try:
        environment = Environment.load(environment_dir)
        if port:
            environment.port = int(port)
    except DatacatsError as e:
        print e
        return 1

    write('Creating from existing environment directory "{0}"'.format(
        environment.name))
    steps = [
        lambda: environment.create_directories(create_project_dir=False),
        environment.save,
        environment.create_virtualenv,
        environment.start_postgres_and_solr,
        environment.fix_storage_permissions,
        environment.fix_project_permissions,
        ]

    for fn in steps:
        fn()
        write('.')
    write('\n')

    return finish_init(environment, start_web, create_sysadmin)
Esempio n. 15
0
def create_environment(environment_dir, port, ckan_version, create_skin,
        start_web, create_sysadmin):
    try:
        # FIXME: only 2.3 preload supported at the moment
        environment = Environment.new(environment_dir, '2.3', port)
    except DatacatsError as e:
        print e
        return 1

    if not valid_deploy_name(environment.name):
        print "WARNING: When deploying you will need to choose a"
        print "target name that is at least 5 characters long"
        print

    write('Creating environment "{0}"'.format(environment.name))
    steps = [
        environment.create_directories,
        environment.create_bash_profile,
        environment.save,
        environment.create_virtualenv,
        environment.create_source,
        environment.start_postgres_and_solr,
        environment.fix_storage_permissions,
        environment.create_ckan_ini,
        lambda: environment.update_ckan_ini(skin=create_skin),
        environment.fix_project_permissions,
        ]

    if create_skin:
        steps.append(environment.create_install_template_skin)

    steps.append(environment.ckan_db_init)

    for fn in steps:
        fn()
        write('.')
    write('\n')

    return finish_init(environment, start_web, create_sysadmin)
Esempio n. 16
0
def main():
    opts = docopt(__doc__, version=__version__)
    environment = Environment.load(opts['ENVIRONMENT'] or '.')
    env_path = environment.target
    less_paths = [
        path_join(env_path, 'ckan', 'ckan', 'public', 'base', 'less'),
        path_join(env_path, 'ckan', 'ckan', 'public', 'base', 'vendor')
    ]

    if not env_path or not all(exists(less_path) for less_path in less_paths):
        print 'No source code to watch found'
        return

    observer = Observer()
    event_handler = LessCompileEventHandler(environment)
    for less_path in less_paths:
        observer.schedule(event_handler, less_path, recursive=True)
    observer.start()

    # HACK: We make it so that the OS doesn't consult us and just kills us.
    signal.signal(signal.SIGINT, signal.SIG_DFL)

    observer.join()
Esempio n. 17
0
def init(opts, no_install=False, quiet=False):
    """Initialize a purged environment or copied environment directory

Usage:
  datacats init [-in] [--syslog] [-s NAME] [--address=IP]
                [--site-url SITE_URL] [ENVIRONMENT_DIR [PORT]]

Options:
  --address=IP            Address to listen on (Linux-only) [default: 127.0.0.1]
  -i --image-only         Create the environment but don't start containers
  -n --no-sysadmin        Don't prompt for an initial sysadmin user account
  -s --site=NAME          Pick a site to initialize [default: primary]
  --site-url SITE_URL     The site_url to use in API responses (e.g. http://example.org:{port}/)
  --syslog                Log to the syslog

ENVIRONMENT_DIR is an existing datacats environment directory. Defaults to '.'
"""
    environment_dir = opts['ENVIRONMENT_DIR']
    port = opts['PORT']
    address = opts['--address']
    start_web = not opts['--image-only']
    create_sysadmin = not opts['--no-sysadmin']
    site_name = opts['--site']
    site_url = opts['--site-url']

    environment_dir = abspath(environment_dir or '.')
    log_syslog = opts['--syslog']

    environment = Environment.load(environment_dir, site_name)
    environment.address = address
    if port:
        environment.port = int(port)
    if site_url:
        environment.site_url = site_url

    try:
        if environment.sites and site_name in environment.sites:
            raise DatacatsError('Site named {0} already exists.'
                                .format(site_name))
        # There are a couple of steps we can/must skip if we're making a sub-site only
        making_full_environment = not environment.data_exists()

        if not quiet:
            write('Creating environment {0}/{1} '
                  'from existing environment directory "{0}"'
                  .format(environment.name, environment.site_name))
        steps = [
            lambda: environment.create_directories(create_project_dir=False)] + ([
             environment.save,
             environment.create_virtualenv
             ] if making_full_environment else []) + [
                 environment.save_site,
                 environment.start_supporting_containers,
                 environment.fix_storage_permissions,
            ]

        for fn in steps:
            fn()
            if not quiet:
                write('.')
        if not quiet:
            write('\n')
    except:
        if not quiet:
            print
        raise

    return finish_init(environment, start_web, create_sysadmin, address,
                       log_syslog=log_syslog, do_install=not no_install,
                       quiet=quiet, site_url=site_url)