Exemplo n.º 1
0
    async def copy(ctx, stay, name_to_copy, name_new):
        """ Copy an existing database environment """
        load_riptide_core(ctx)
        cmd_constraint_has_db(ctx)

        project = ctx.system_config["project"]
        engine = ctx.engine
        dbenv = DbEnvironments(project, engine)

        echo("Copying... this may take a while...")
        try:
            dbenv.new(name_new, copy_from=name_to_copy)
            echo()
            echo("New environment created: " + style(name_new, bold=True))
            echo()
        except FileExistsError:
            raise RiptideCliError("Envrionment with this name already exists.", ctx)
        except FileNotFoundError:
            raise RiptideCliError("Envrionment to copy from not found.", ctx)
        except NameError:
            raise RiptideCliError("Invalid name for new environment, do not use special characters", ctx)
        except Exception as ex:
            raise RiptideCliError("Error creating environment", ctx) from ex

        if not stay:
            await switch_impl(ctx, name_new)
Exemplo n.º 2
0
    async def export(ctx, file):
        """
        Export database dump from the current environment.
        The format of the dump depends on the database driver.
        """
        load_riptide_core(ctx)
        cmd_constraint_has_db(ctx)

        project = ctx.system_config["project"]
        engine = ctx.engine
        dbenv = DbEnvironments(project, engine)
        db_name = dbenv.db_service["$name"]
        env_name = dbenv.currently_selected_name()
        db_driver = db_driver_for_service.get(dbenv.db_service)

        # 1. If not running, start database
        was_running = engine.status(project)[db_name]
        if not was_running:
            await start_project(ctx, [db_name], show_status=False)

        # 2. Export
        echo(f"Exporting from {env_name}... this may take a while...")
        try:
            db_driver.export(engine, os.path.abspath(file))
            echo()
            echo(f"Environment {env_name} exported.")
            echo()
        except FileNotFoundError:
            raise RiptideCliError("Environment does not exist. Create it first with db-create", ctx)
        except Exception as ex:
            raise RiptideCliError("Error exporting environment", ctx) from ex
Exemplo n.º 3
0
async def importt_impl(ctx, file):
    project = ctx.system_config["project"]
    engine = ctx.engine
    dbenv = DbEnvironments(project, engine)
    db_name = dbenv.db_service["$name"]
    env_name = dbenv.currently_selected_name()
    db_driver = db_driver_for_service.get(dbenv.db_service)

    if not file or file == "":
        raise RiptideCliError("Please specify a path.", ctx)

    if not os.path.exists(os.path.abspath(file)):
        raise RiptideCliError("The path does not exist.", ctx)

    # 1. If not running, start database
    was_running = engine.status(project)[db_name]
    if not was_running:
        await start_project(ctx, [db_name], show_status=False)
        # TODO: Some databases need a while. How to do this better? mysqladmin for example doesn't help :(
        await sleep(15)

    # 2. Import
    echo(f"Importing into database environment {env_name}... this may take a while...")
    try:
        db_driver.importt(engine, os.path.abspath(file))
        echo()
        echo(f"Database environment {env_name} imported.")
        echo()
        return True
    except FileNotFoundError:
        raise RiptideCliError("Environment does not exist. Create it first with db:create", ctx)
    except Exception as ex:
        raise RiptideCliError("Error importing database environment", ctx) from ex
Exemplo n.º 4
0
async def switch_impl(ctx, name):
    project = ctx.system_config["project"]
    engine = ctx.engine
    dbenv = DbEnvironments(project, engine)
    db_name = dbenv.db_service["$name"]

    # 1. If running, stop database
    was_running = engine.status(project)[db_name]
    if was_running:
        await stop_project(ctx, [db_name], show_status=False)

    # 2. Switch environment
    try:
        dbenv.switch(name)
        echo()
        echo("Environment switched to: " + style(name, bold=True))
        echo()
    except FileNotFoundError:
        raise RiptideCliError("Environment does not exist. Create it with db-new or db-copy.", ctx)
    except Exception as ex:
        raise RiptideCliError("Error switching environments", ctx) from ex

    # 3. If was running: start database again
    if was_running:
        await start_project(ctx, [db_name])
Exemplo n.º 5
0
    def cmd(ctx, command, arguments):
        """
        Executes a project command.
        Project commands are specified in the project configuration.
        The commands are run interactively (Stdout/Stderr/Stdin are attached).
        If you are currently in a subdirectory of 'src' (see project configuration), then the command
        will be executed inside of this directory. Otherwise the command will be executed in the root
        of the 'src' directory. All commands are executed as the current user + group.

        When command is not specified, all commands will be listed.
        """
        load_riptide_core(ctx)
        cmd_constraint_project_set_up(ctx)

        project = ctx.system_config["project"]
        engine = ctx.engine

        if command is None:
            click.echo(click.style("Commands:", bold=True))
            if "commands" not in project["app"] or len(
                    project["app"]["commands"]) < 1:
                click.echo(TAB + "No commands specified.")
                return
            for name, cmd in project["app"]["commands"].items():
                if "aliases" in cmd:
                    # alias
                    click.echo(TAB + "- " + click.style(name, bold=True) +
                               " (alias for " + cmd["aliases"] + ")")
                else:
                    # normal / in service cmd
                    click.echo(TAB + "- " + click.style(name, bold=True))
            return

        if "commands" not in project["app"] or command not in project["app"][
                "commands"]:
            raise RiptideCliError("Command not found.", ctx)

        # check if command is actually an alias
        command = project["app"]["commands"][command].resolve_alias()["$name"]
        cmd_obj = project["app"]["commands"][command]

        # Run Command
        try:
            if KEY_IDENTIFIER_IN_SERVICE_COMMAND in cmd_obj:
                # In Service comamnd
                sys.exit(in_service.run(engine, project, command, arguments))
            else:
                # Normal command
                sys.exit(engine.cmd(project, command, arguments))
        except (ExecError, ValueError) as err:
            raise RiptideCliError(str(err), ctx) from err
Exemplo n.º 6
0
    def exec_cmd(ctx, service, root, command):
        """
        Opens a shell into a service container.
        The shell is run interactively (Stdout/Stderr/Stdin are attached).
        If you are currently in a subdirectory of 'src' (see project configuration), then the shell
        will be executed inside of this directory. Otherwise the shell will be executed in the root
        of the 'src' directory. Shell is executed as the current user + group (may be named differently inside the container).

        If --command is given, a command will be executed in the shell. Riptide will not return the exit code of the
        command. Please consider using Command objects instead (riptide cmd). A warning will be printed to stderr first,
        when using this option.
        """
        load_riptide_core(ctx)
        cmd_constraint_project_set_up(ctx)

        project = ctx.system_config["project"]
        engine: AbstractEngine = ctx.engine

        if service is None:
            if project["app"].get_service_by_role('main') is None:
                raise RiptideCliError("Please specify a service", ctx)
            service = project["app"].get_service_by_role('main')["$name"]

        try:
            cols, lines = os.get_terminal_size()
            if not command:
                engine.exec(project,
                            service,
                            cols=cols,
                            lines=lines,
                            root=root)
            else:
                if 'RIPTIDE_DONT_SHOW_EXEC_WARNING' not in os.environ:
                    warn(
                        f"""Using exec --command is not recommended. Please consider creating a Command object instead.

Please see the documentation for more information. 
To suppress this warning, set the environment variable RIPTIDE_DONT_SHOW_EXEC_WARNING."""
                    )

                engine.exec_custom(project,
                                   service,
                                   command,
                                   cols=cols,
                                   lines=lines,
                                   root=root)
        except ExecError as err:
            raise RiptideCliError(str(err), ctx) from err
Exemplo n.º 7
0
    def update(ctx):
        """
        Update repositories and current project images
        """
        # Load only the system config
        system_config = load_riptide_system_config(None,
                                                   skip_project_load=True)

        # Update the repositories
        echo(header("Updating Riptide repositories..."))
        repositories.update(system_config,
                            update_text_func=lambda msg: echo(TAB + msg))

        # Reload system config + project config
        load_riptide_core(ctx)

        # If update is set, also pull images. Repositories are updated above (see load_config())
        if ctx.system_config is not None and 'project' in ctx.system_config:
            echo(header("Updating images..."))
            try:
                ctx.engine.pull_images(
                    ctx.system_config["project"],
                    line_reset="\033[2K\r" + TAB,
                    update_func=lambda msg: echo(TAB + msg, nl=False))
            except Exception as ex:
                raise RiptideCliError('Error updating an image', ctx) from ex
Exemplo n.º 8
0
async def stop_project(ctx, services: List[str], show_status=True):
    """
    Stops a project by stopping all it's services (or a subset).
    If show_status is true, shows status after that.
    """
    project = ctx.system_config["project"]
    engine = ctx.engine

    if len(services) < 1:
        return

    echo("Stopping services...")
    echo()

    ctx.progress_bars = _build_progress_bars(services)
    ctx.start_stop_errors = []

    try:
        async for service_name, status, finished in engine.stop_project(
                project, services):
            _handle_progress_bar(service_name, status, finished,
                                 ctx.progress_bars, ctx.start_stop_errors)
    except Exception as err:
        raise RiptideCliError("Error stopping the services", ctx) from err

    for bar in reversed(ctx.progress_bars.values()):
        bar.close()
        echo()

    display_errors(ctx.start_stop_errors, ctx)

    if show_status:
        status_project(ctx)
Exemplo n.º 9
0
    async def start(ctx, default, all, services, cmd):
        """
        Starts services.

        By default (or if --default/-d is explicitly set) services defined in `default_services` of the project
        will be started. If none are defined, all services are started.

        If the --all/-a flag is passed, all services are started.

        If --service/-s is passed, a comma-separated list of services is started.

        --default, --service and --all can not be used together.
        """
        load_riptide_core(ctx)
        cmd_constraint_project_set_up(ctx)

        if sum([bool(v) for v in [default, all, services]]) > 1:
            raise RiptideCliError(
                "--all, --service and --default can not be used together", ctx)
        project = ctx.system_config["project"]

        # Default:
        services_to_start = None
        if "default_services" in project:
            services_to_start = project["default_services"]

        if services is not None:
            services_to_start = services.split(",")
        elif all or services_to_start is None:
            services_to_start = project["app"]["services"].keys()

        await start_project(ctx, services_to_start, command_group=cmd)
Exemplo n.º 10
0
    async def stop(ctx, default, all, services):
        """
        Stops services.

        By default (or if the --all/-a option is explicitly set) all running services are stopped.

        If the --default/-d flag is set, only services defined in the `default_services` of the project are stopped.
        If this field is not set, all services are stopped.

        If --service/-s is passed, a comma-separated list of services is stopped.

        --default, --service and --all can not be used together.
        """
        load_riptide_core(ctx)
        cmd_constraint_project_set_up(ctx)

        if sum([bool(v) for v in [default, all, services]]) > 1:
            raise RiptideCliError(
                "--all, --service and --default can not be used together", ctx)

        project = ctx.system_config["project"]

        # Default: All
        services_to_stop = list(project["app"]["services"].keys())
        if default and "default_services" in project:
            services_to_stop = project["default_services"]
        elif services is not None:
            services_to_stop = services.split(",")

        await stop_project(ctx, services_to_stop)
Exemplo n.º 11
0
    async def restart(ctx, default, all, services, cmd):
        """
        Stops and then starts services.

        By default all running services are restarted.

        If the --all/-a flag is set, all services are restarted, even if they were not running.

        If the --default/-d flag is set, only services defined in the `default_services` of the project are restarted,
        including services that were not running. If this field is not set, all services are restarted.

        If --service/-s is passed, a comma-separated list of services is restarted.

        --default, --service and --all can not be used together.

        """
        load_riptide_core(ctx)
        cmd_constraint_project_set_up(ctx)

        if sum([bool(v) for v in [default, all, services]]) > 1:
            raise RiptideCliError(
                "--all, --service and --default can not be used together", ctx)

        project = ctx.system_config["project"]

        # Get running services:
        running_services = [
            k for (k, v) in ctx.engine.status(project).items() if v
        ]
        # Default (running services):
        services_to_restart = running_services
        if default and "default_services" in project:
            services_to_restart = project["default_services"]
        elif all or (default and "default_services" not in project):
            services_to_restart = project["app"]["services"].keys()
        elif services is not None:
            services_to_restart = services.split(",")

        if len(services_to_restart) < 1:
            raise RiptideCliError(
                "No services were running. "
                "If you want to restart all, set the flag -a. See help page.",
                ctx)

        await stop_project(ctx, services_to_restart, show_status=False)
        await start_project(ctx, services_to_restart, command_group=cmd)
Exemplo n.º 12
0
    def drop(ctx, name):
        """ Delete a database environment """
        load_riptide_core(ctx)
        cmd_constraint_has_db(ctx)

        project = ctx.system_config["project"]
        engine = ctx.engine
        dbenv = DbEnvironments(project, engine)

        echo("Deleting... this may take a while...")
        try:
            dbenv.drop(name)
            echo()
            echo("Environment deleted: " + style(name, bold=True))
            echo()
        except FileNotFoundError:
            raise RiptideCliError("Envrionment with this name does not exist.", ctx)
        except OSError:
            raise RiptideCliError("Can not delete the environment that is currently active.", ctx)
        except Exception as ex:
            raise RiptideCliError("Error deleting environment", ctx) from ex
Exemplo n.º 13
0
def files_impl(ctx, key, path_to_import):
    project = ctx.system_config["project"]

    if key not in project["app"]["import"]:
        raise RiptideCliError("Import key not found. Valid keys are: " + ",".join(project["app"]["import"].keys()), ctx)

    if not os.path.exists(path_to_import):
        raise RiptideCliError("The file or directory to import doesn't exist", ctx)

    import_spec = project["app"]["import"][key]
    if os.path.isabs(import_spec["target"]):
        raise RiptideCliError(f"The import key {key} contains an absolute target path. All target paths must be relative to project", ctx)

    destination = os.path.join(project.folder(), import_spec["target"])
    source_is_file = os.path.isfile(path_to_import)

    if os.path.exists(destination) and os.path.isfile(destination):
        raise RiptideCliError(f"The target file ({import_spec['target']}) already exists", ctx)

    if source_is_file and os.path.exists(destination):  # implict: target is directory
        raise RiptideCliError("The target is a diretory, but the path to import points to a file. Can't continue.", ctx)

    echo(f"Importing {key} ({import_spec['target']}) from {path_to_import}")
    echo("Copying... this can take some time...")
    os.makedirs(os.path.dirname(destination ), exist_ok=True)
    try:
        if source_is_file:
            shutil.copy2(path_to_import, destination)
        else:
            copy_tree(path_to_import, destination)
    except Exception as ex:
        raise RiptideCliError("Error while copying", ctx) from ex

    echo("Done!")
Exemplo n.º 14
0
 def config_get(ctx, template):
     """
     Obtain configuration from riptide using a template. Supports helper functions e.g. riptide config-get -v
     "project.app.get_service_by_role('the_role').domain()"
     """
     load_riptide_core(ctx)
     try:
         echo(
             ctx.system_config.process_vars_for("{{ " + template + " }}",
                                                additional_helpers=[]))
     except Exception as error:
         raise RiptideCliError('Error processing the variable.',
                               ctx) from error
Exemplo n.º 15
0
    async def new(ctx, stay, name):
        """ Create a new (blank) database environment """
        load_riptide_core(ctx)
        cmd_constraint_has_db(ctx)

        project = ctx.system_config["project"]
        engine = ctx.engine
        dbenv = DbEnvironments(project, engine)

        try:
            dbenv.new(name, copy_from=None)
            echo()
            echo("New environment created: " + style(name, bold=True))
            echo()
        except FileExistsError:
            raise RiptideCliError("Envrionment with this name already exists.", ctx)
        except NameError:
            raise RiptideCliError("Invalid name for new environment, do not use special characters", ctx)
        except Exception as ex:
            raise RiptideCliError("Error creating environment", ctx) from ex

        if not stay:
            await switch_impl(ctx, name)
Exemplo n.º 16
0
async def start_project(ctx,
                        services: List[str],
                        show_status=True,
                        quick=False,
                        *,
                        command_group: str = "default"):
    """
    Starts a project by starting all it's services (or a subset).
    If show_status is true, shows status after that.
    If quick is True, pre_start and post_start commands are skipped.
    """
    project = ctx.system_config["project"]
    engine = ctx.engine

    if len(services) < 1:
        return

    echo("Starting services...")
    echo()

    ctx.progress_bars = _build_progress_bars(services)
    ctx.start_stop_errors = []

    try:
        async for service_name, status, finished in engine.start_project(
                project, services, quick=quick, command_group=command_group):
            _handle_progress_bar(service_name, status, finished,
                                 ctx.progress_bars, ctx.start_stop_errors)
    except Exception as err:
        raise RiptideCliError("Error starting the services", ctx) from err

    for bar in reversed(ctx.progress_bars.values()):
        bar.close()
        echo()

    display_errors(ctx.start_stop_errors, ctx)

    if show_status:
        status_project(ctx)
Exemplo n.º 17
0
def cmd_constraint_has_import(ctx):
    cmd_constraint_project_loaded(ctx)
    if "import" not in ctx.system_config["project"]["app"]:
        raise RiptideCliError("The project's app has no import paths defined."
                              "This is required to use this command.", ctx)
Exemplo n.º 18
0
async def setup_assistant(ctx, force, skip):
    project = ctx.system_config["project"]
    engine = ctx.engine

    if ctx.project_is_set_up and not force:
        raise RiptideCliError(
            "The project is already set up. If you still want to run this command, pass --force.",
            ctx)

    if skip:
        echo("Project was marked as set up.")
        finish(ctx)
        return

    echo(style("Thank you for using Riptide!", fg='cyan', bold=True))
    echo(
        f"This command will guide you through the initial setup for {project['name']}."
    )
    echo(
        style("Please follow it very carefully, it won't take long!",
              bold=True))
    echo(style("> Press any key to continue...", fg='magenta'))
    getchar()
    echo()
    echo(header("> BEGIN SETUP"))
    if "notices" in project["app"] and "usage" in project["app"]["notices"]:
        echo()
        echo(
            style(f"Usage notes for running {project['app']['name']}",
                  bold=True) + " with Riptide:")
        echo(TAB +
             TAB.join(project["app"]["notices"]["usage"].splitlines(True)))
    echo()

    # Q1
    echo(style("> Do you wish to run this interactive setup? [Y/n] ",
               fg='magenta'),
         nl=False)
    if getchar(True).lower() == 'n':
        echo()
        echo()
        echo(header("> END SETUP"))
        echo("Okay! To re-run this setup, pass the --force option.")
        finish(ctx)
        return
    echo()
    echo()
    echo(header("> INTERACTIVE SETUP"))

    # Q2: New or existing?
    echo(style("> Are you working on a ", fg='magenta') +
         style("n", bold=True, fg="cyan") +
         style("ew project that needs to be installed or do you want to ",
               fg='magenta') + style("I", bold=True, fg="cyan") +
         style("mport existing data? [n/I] ", fg='magenta'),
         nl=False)
    if getchar(True).lower() == 'n':
        # New project
        if "notices" in project["app"] and "installation" in project["app"][
                "notices"]:
            echo()
            echo()
            echo(header("> NEW PROJECT"))
            echo(
                "Okay! Riptide can't guide you through the installation automatically."
            )
            echo(
                f"Please read these notes on how to run a first-time-installation for {project['app']['name']}."
            )
            echo()
            echo(style("Installation instructions:", bold=True))
            echo(TAB + TAB.join(project["app"]["notices"]
                                ["installation"].splitlines(True)))
            finish(ctx)
            return

    # Existing project
    echo()
    echo()
    echo(header("> EXISTING PROJECT"))

    db_can_be_imported = DbEnvironments.has_db(project)
    files_can_be_imported = 'import' in project['app']

    if not db_can_be_imported and not files_can_be_imported:
        # Nothing to import
        echo(
            f"The app {project['app']['name']} does not specify a database or files to import. You are already done!"
        )
        finish(ctx)
        return

    # Import db
    if db_can_be_imported:
        dbenv = DbEnvironments(project, engine)
        db_driver = db_driver_for_service.get(dbenv.db_service)
        echo(TAB + header("> DATABASE IMPORT"))
        echo(style(
            f"> Do you want to import a database (format {dbenv.db_service['driver']['name']})? [Y/n] ",
            fg='magenta'),
             nl=False)
        if getchar(True).lower() != 'n':
            # Import db
            echo()
            exit_cmd = False
            while not exit_cmd:
                echo(db_driver.ask_for_import_file() + " ", nl=False)
                path = stdin.readline().rstrip('\r\n')
                try:
                    echo(CMD_SEP)
                    await importt_impl(ctx, path)
                    exit_cmd = True
                    echo(CMD_SEP)
                except RiptideCliError as err:
                    echo("Error: " + style(str(err), fg='red'))
                    echo(CMD_SEP)
                    echo(style("> Do you want to try again? [y/N] ",
                               fg='magenta'),
                         nl=False)
                    if getchar(True).lower() != 'y':
                        exit_cmd = True
                    echo()

        else:
            echo()
            echo(
                "Skipping database import. If you change your mind, run db:import."
            )

    if files_can_be_imported:
        echo(TAB + header("> FILE IMPORT"))
        for key, entry in project['app']['import'].items():
            echo(TAB + TAB + header(f"> {key} IMPORT"))
            echo(style(
                f"> Do you wish to import {entry['name']} to <project>/{entry['target']}? [Y/n] ",
                fg='magenta'),
                 nl=False)
            if getchar(True).lower() != 'n':
                # Import files
                echo()
                exit_cmd = False
                while not exit_cmd:
                    echo("Enter path of files or directory to copy: ",
                         nl=False)
                    path = stdin.readline().rstrip('\r\n')
                    try:
                        echo(CMD_SEP)
                        files_impl(ctx, key, path)
                        exit_cmd = True
                        echo(CMD_SEP)
                    except RiptideCliError as err:
                        echo("Error: " + style(str(err), fg='red'))
                        echo(CMD_SEP)
                        echo(style("> Do you want to try again? [y/N] ",
                                   fg='magenta'),
                             nl=False)
                        if getchar(True).lower() != 'y':
                            exit_cmd = True
                        echo()
            else:
                echo()
    echo()
    echo(header("> IMPORT DONE!", bold=True))
    echo("All files were imported.")
    finish(ctx)
Exemplo n.º 19
0
    async def start_fg(ctx, default, all, services, interactive_service,
                       arguments, cmd):
        """
        Starts services and then runs a service in foreground.

        When using this command, Riptide will start all your services
        as normal except for one service you specify.

        This one service will be started in foreground mode. Input and Outputs
        will be attached to the current console.
        You can pass additional arguments to add to the service command.
        This will basically run the service as it were a command.
        This allows for interactive debugging of services.

        If the INTERACTIVE_SERVICE is already started, it is stopped first.

        When running a service in foreground mode the logging options
        for stdout and stderr are ignored.
        stdout and stderr are printed to console instead.

        Following options are also ignored:

        - pre_start

        - post_start

        - roles.src (is set)

        - working_directory (is set to current working directory)

        For --service/--all/--default flags and default behaviour, see the start command.

        """
        load_riptide_core(ctx)
        cmd_constraint_project_set_up(ctx)

        project = ctx.system_config["project"]
        engine = ctx.engine

        if sum([bool(v) for v in [default, all, services]]) > 1:
            raise RiptideCliError(
                "--all, --service and --default can not be used together", ctx)

        if "services" not in project[
                "app"] or interactive_service not in project["app"]["services"]:
            raise RiptideCliError(
                f"The service {interactive_service} was not found.", ctx=ctx)

        project = ctx.system_config["project"]

        # Default:
        normal_services = None
        if "default_services" in project:
            normal_services = project["default_services"]

        if all or normal_services is None:
            normal_services = list(project["app"]["services"].keys())
        elif services is not None:
            normal_services = services.split(",")

        # Remove interactive service from normal service list
        if interactive_service in normal_services:
            normal_services.remove(interactive_service)

        echo(style("(1/3) Starting other services...", bg='cyan', fg='white'))
        await start_project(ctx,
                            normal_services,
                            show_status=False,
                            command_group=cmd)

        echo(
            style(f"(2/3) Stopping {interactive_service}...",
                  bg='cyan',
                  fg='white'))
        await stop_project(ctx, [interactive_service], show_status=False)

        echo(
            style(
                f"(3/3) Starting in {interactive_service} foreground mode...",
                bg='cyan',
                fg='white'))
        engine.service_fg(project, interactive_service, arguments, cmd)
Exemplo n.º 20
0
def cli(ctx,
        version=False,
        update=False,
        ignore_shell=False,
        project=None,
        project_file=None,
        verbose=False,
        **kwargs):
    """
    Define development environments for web applications.
    See full documentation at: https://riptide-docs.readthedocs.io/en/latest/
    """
    SystemFlag.IS_CLI = True

    # Print version if requested
    if version:
        print_version()
        exit()

    ctx.riptide_options = {"verbose": verbose}

    # Don't allow running as root.
    try:
        if os.getuid() == 0 and 'RIPTIDE_ALLOW_ROOT' not in os.environ:
            raise RiptideCliError("riptide must not be run as the root user.",
                                  ctx=ctx)
    except AttributeError:
        # Windows. Ignore.
        pass

    if project and project_file:
        raise RiptideCliError(
            "--project and --project-file can not be used together.", ctx)

    if update:
        raise RiptideCliError(
            "--update/-u is deprecated. Please run 'riptide update' instead.",
            ctx)

    new_versions = check_for_update()
    if new_versions:
        new_versions = '\n'.join([
            f"    {pkg:<22}: {version}"
            for pkg, version in new_versions.items()
        ])
        warn(
            f"A new Riptide version is available:\n"
            f"{new_versions}\n\n"
            f"Use riptide_upgrade to upgrade. You may NEED to use sudo, see:\n"
            f"    https://riptide-docs.readthedocs.io/en/latest/user_docs/2a_linux.html#updating-riptide\n",
            False)

    if 'RIPTIDE_SHELL_LOADED' not in os.environ and not ctx.resilient_parsing and not ignore_shell:
        warn("Riptide shell integration not enabled.")
        echo()

    if project:
        projects = load_projects()
        if project in projects:
            project_file = projects[project]
        else:
            raise RiptideCliError(
                f"Project {project} not found. --project/-P "
                f"can only be used if the project was loaded with Riptide at least once.",
                ctx)

    # Setup basic variables
    ctx.riptide_options = {
        "project": project_file,
        "verbose": verbose,
        "rename": False
    }
    ctx.riptide_options.update(kwargs)
Exemplo n.º 21
0
def cmd_constraint_has_db(ctx):
    cmd_constraint_project_loaded(ctx)
    if not DbEnvironments.has_db(ctx.system_config["project"]):
        raise RiptideCliError("The project doesn't have a service with the role 'db'. "
                              "This is required to use this command.", ctx)