Example #1
0
def upload(**kwargs):
    _ensure_logged_in(kwargs["stolos_url"])
    public_key_path = kwargs["public_key_path"]
    if not public_key_path.endswith(".pub"):
        click.confirm(
            ("Key {} appears to be a private, not a public key. "
             "Are you sure you want to continue?").format(public_key_path),
            abort=True,
        )
    expanded_public_key_path = os.path.expanduser(public_key_path)
    if not os.path.exists(expanded_public_key_path):
        raise click.exceptions.ClickException(
            "File {} does not exist".format(public_key_path))

    cnf = config.get_config()
    stolos_url = kwargs.pop("stolos_url")
    if not stolos_url:
        stolos_url = cnf["user"]["default-api-server"]

    name = kwargs.get("name")
    if not name:
        name = platform.node()

    with open(expanded_public_key_path, "r") as fin:
        resp = api.keys_create(cnf["user"][_get_hostname(stolos_url)],
                               ssh_public_key=fin.read(),
                               name=name)

    updated_conf = cnf["user"][_get_hostname(stolos_url)]
    updated_conf["identity-file"] = os.path.abspath(
        re.sub(".pub$", "", expanded_public_key_path))
    config.update_user_config({"user": {stolos_url: updated_conf}})
    if resp.ok:
        click.echo(
            "Public key {} uploaded successfully".format(public_key_path))
Example #2
0
def _sync(repeat):
    """
    Starts a project sync using Unison. Takes an extra parameter, which makes
    the synchronization repeat using Unison `-repeat` or not.
    """
    cnf = config.get_config()
    _config_environ(cnf)
    identity_file = cnf["user"][cnf["user"]["default-api-server"]].get(
        "identity-file")
    if identity_file is None:
        click.echo(
            click.style("[WARNING] ", bold=True) +
            "No public key was found. Your user's default key will be used.")
        click.echo("To upload a public ssh key, use the following command:")
        click.secho("\tstolos keys upload [PUBLIC_KEY_PATH]\n", bold=True)
        home = os.path.expanduser("~")
        identity_file = os.path.join(home, ".ssh", "id_rsa")
    args = []
    args.insert(0, "-i {}".format(identity_file))
    args.insert(0, "-sshargs")
    if repeat:
        args.insert(0, "2")
        args.insert(0, "-repeat")
    else:
        args.insert(0, "false")
        args.insert(0, "-fastcheck")
    if _is_windows():
        args.insert(0, "win")
    p = subprocess.Popen(["unison"] + args,
                         stdout=sys.stdout,
                         stderr=sys.stderr,
                         stdin=sys.stdin)
    return p
Example #3
0
def sync(repeat):
    _ensure_stolos_directory()
    cnf = config.get_config()
    _config_environ(cnf)
    click.echo("Syncing...")
    _sync(repeat).wait()
    if not repeat:
        click.echo("Okay.")
Example #4
0
def env(**kwargs):
    _ensure_stolos_directory()
    cnf = config.get_config()
    stolos_url = cnf["user"]["default-api-server"]
    _ensure_logged_in(stolos_url)
    env_dict = _get_environ(cnf)
    command = "stolos env"
    if kwargs["shell"]:
        command = "stolos env --shell={}".format(kwargs["shell"])
    shell.print_env_eval(command, kwargs["shell"], env_dict)
Example #5
0
def keys_delete(**kwargs):
    _ensure_logged_in(kwargs["stolos_url"])
    public_key_uuid = kwargs.get("public_key_uuid")
    cnf = config.get_config()
    stolos_url = kwargs.pop("stolos_url")
    if not stolos_url:
        stolos_url = cnf["user"]["default-api-server"]
    click.echo('Deleting SSH public key "{}"...'.format(public_key_uuid),
               nl=False)
    api.keys_remove(cnf["user"][_get_hostname(stolos_url)], public_key_uuid)
    click.echo("\t\tOkay.")
Example #6
0
def stacks_list(**kwargs):
    _ensure_logged_in(kwargs["stolos_url"])
    cnf = config.get_config()
    stolos_url = kwargs.get("stolos_url")
    if not stolos_url:
        stolos_url = cnf["user"]["default-api-server"]
    headers = ["Stack name", "Slug", "Description"]
    stacks = [
        (stack["name"], stack["slug"], stack.get("description"))
        for stack in api.stacks_list(cnf["user"][_get_hostname(stolos_url)])
    ]
    click.echo(tabulate(stacks, headers=headers))
Example #7
0
def password(**kwargs):
    cnf = config.get_config()
    stolos_url = kwargs.get("stolos_url")
    if not stolos_url:
        stolos_url = cnf["user"]["default-api-server"]
    _ensure_logged_in(stolos_url)
    api.change_password(
        cnf["user"][_get_hostname(stolos_url)],
        kwargs["password"],
        kwargs["new_password"],
    )
    click.echo("Password successfully updated.")
Example #8
0
def _ensure_logged_in(stolos_url=None):
    """
    Ensures the user is logged in, at the given `stolos_url` Stolos server.
    Raises an exception if not.
    """
    cnf = config.get_config()
    if "user" not in cnf:
        raise exceptions.NotLoggedInException()
    if "default-api-server" not in cnf["user"] and not stolos_url:
        raise exceptions.NotLoggedInException()
    stolos_url = stolos_url or cnf["user"]["default-api-server"]
    if stolos_url not in cnf["user"]:
        raise exceptions.NotLoggedInException()
Example #9
0
def keys_list(**kwargs):
    _ensure_logged_in(kwargs["stolos_url"])
    cnf = config.get_config()
    stolos_url = kwargs.get("stolos_url")
    if not stolos_url:
        stolos_url = cnf["user"]["default-api-server"]
    algorithm = "md5"
    if not kwargs["md5"]:
        algorithm = "sha256"
    headers = ["UUID", "Name", algorithm.upper()]
    keys = [(key["uuid"], key["name"], key[algorithm])
            for key in api.keys_list(cnf["user"][_get_hostname(stolos_url)])]
    click.echo(tabulate(keys, headers=headers))
Example #10
0
def _config_environ(cnf):
    """
    Configures the environment with any needed environment variables for compose
    and Unison. Also updates the docker certificates to the latest valid from
    user config.
    """
    cnf = config.get_config()
    server = cnf["user"]["default-api-server"]
    with open(".stolos/cert.pem", "w+") as cert_pem:
        cert_pem.write(cnf["user"][server].get("cert-pem", ""))
        os.chmod(".stolos/cert.pem", 0o600)
    with open(".stolos/key.pem", "w+") as key_pem:
        key_pem.write(cnf["user"][server].get("key-pem", ""))
    os.environ.update(_get_environ(cnf))
Example #11
0
def connect(**kwargs):
    _ensure_logged_in(kwargs["stolos_url"])
    cnf = config.get_config()
    stolos_url = kwargs.pop("stolos_url")
    project_uuid = kwargs.pop("project_uuid")
    if not stolos_url:
        stolos_url = cnf["user"]["default-api-server"]
    click.echo('Connecting to project "{}"...'.format(project_uuid), nl=False)
    project = api.projects_retrieve(cnf["user"][_get_hostname(stolos_url)],
                                    project_uuid)
    _initialize_project(stolos_url, project)
    _initialize_services()
    click.echo("\t\tOkay.")
    click.echo('Your project is ready! Run "stolos up" to launch it!')
Example #12
0
def info(**kwargs):
    _ensure_stolos_directory()
    cnf = config.get_config()
    stolos_url = cnf["user"]["default-api-server"]
    _ensure_logged_in(stolos_url)
    headers = ["UUID", "Stack", "Public URL"]
    project = api.projects_retrieve(cnf["user"][_get_hostname(stolos_url)],
                                    cnf["project"]["uuid"])
    uuid = project["uuid"]
    stack = "-"
    if project["stack"]:
        stack = project["stack"]["slug"]
    domain = project["routing_config"]["domain"]
    projects = [(uuid, stack, domain)]
    click.echo(tabulate(projects, headers=headers))
Example #13
0
def projects_list(**kwargs):
    _ensure_logged_in(kwargs["stolos_url"])
    cnf = config.get_config()
    stolos_url = kwargs.get("stolos_url")
    if not stolos_url:
        stolos_url = cnf["user"]["default-api-server"]
    headers = ["UUID", "Stack", "Public URL"]
    projects = []
    for project in api.projects_list(cnf["user"][_get_hostname(stolos_url)]):
        uuid = project["uuid"]
        stack = "-"
        if project["stack"]:
            stack = project["stack"]["slug"]
        domain = project["routing_config"]["domain"]
        projects.append((uuid, stack, domain))
    click.echo(tabulate(projects, headers=headers))
Example #14
0
def up(detach, logs, build):
    _ensure_stolos_directory()
    _ensure_logged_in()
    cnf = config.get_config()
    _config_environ(cnf)
    click.echo("Syncing...")
    if _sync(False).wait() != 0:
        click.echo("There was an error with the sync")
        return
    click.echo("Okay.")
    click.echo("Starting services...")
    compose_args = ["up", "-d", "--remove-orphans"]
    if build:
        compose_args.append("--build")
    if _compose(compose_args).wait() != 0:
        click.echo("There was an error with starting your services")
        return
    click.echo("Started services at {}".format(cnf["project"]["public-url"]))
    if detach:
        return
    handler = InteruptHandler()
    signal.signal(signal.SIGINT, handler)
    processes = [("Syncing", _sync(True))]
    if logs:
        compose_args = ["logs", "--tail=20", "-f"]
        if _is_windows():
            compose_args.append("--no-color")
        processes.append(("Services", _compose(compose_args)))
    exit = ""
    while not exit:
        for process_name, process in processes:
            if process.poll():
                if handler.state == 0:
                    exit = '{} exited with exit code "{}"'.format(
                        process_name, process.returncode)
                    for _, p in processes:
                        if p is not process:
                            p.terminate()
                else:
                    exit = "Terminated by user"
                    break
        time.sleep(1)
    for _, p in processes:
        p.wait()
    click.echo(exit)
Example #15
0
def create(**kwargs):
    _ensure_logged_in(kwargs["stolos_url"])
    cnf = config.get_config()
    stolos_url = kwargs.pop("stolos_url")
    project_directory = kwargs.pop("project_directory")
    if not stolos_url:
        stolos_url = cnf["user"]["default-api-server"]
    if not kwargs["public_url"]:
        if kwargs["stack"]:
            company, stack_name = kwargs["stack"].split("/")
            fmt_str = "{company}-{stack_name}-{username}-{hex}.{server}"
            kwargs["public_url"] = fmt_str.format(
                company=company,
                stack_name=stack_name,
                username=cnf["user"][_get_hostname(stolos_url)]["username"],
                hex="".join(
                    [random.choice(string.ascii_lowercase) for _ in range(6)]),
                server=stolos_url,
            )
        else:
            fmt_str = "{username}-{hex}.{server}"
            kwargs["public_url"] = fmt_str.format(
                username=cnf["user"][_get_hostname(stolos_url)]["username"],
                hex="".join(
                    [random.choice(string.ascii_lowercase) for _ in range(6)]),
                server=stolos_url,
            )
        click.echo('Assigning random public URL "{}"'.format(
            kwargs["public_url"]))
    click.echo('Creating project "{}"...'.format(project_directory), nl=False)
    project = api.projects_create(cnf["user"][_get_hostname(stolos_url)],
                                  **kwargs)
    if not os.path.exists(project_directory):
        os.makedirs(project_directory)
    os.chdir(project_directory)
    _initialize_project(stolos_url, project)
    click.echo("\t\tOk.")
    _initialize_services()
    if project_directory == ".":
        click.echo('Your project is ready! Run "stolos up" to launch it!')
        return
    click.echo(
        ('Your project is ready! Change directory with "cd {0}" and run '
         '"stolos up" to launch it!').format(project_directory))
Example #16
0
def delete(**kwargs):
    _ensure_logged_in(kwargs["stolos_url"])
    project_uuid = kwargs.pop("project_uuid")
    if (not project_uuid and not _ensure_stolos_directory(base_directory=None,
                                                          raise_exc=False)):
        raise exceptions.CLIRequiredException("project-uuid")
    cnf = config.get_config()
    stolos_url = kwargs.pop("stolos_url")
    remove_directory = False
    if not project_uuid:
        project_uuid = cnf["project"]["uuid"]
        remove_directory = True
    if not stolos_url:
        stolos_url = cnf["user"]["default-api-server"]
    click.echo('Deleting project "{}"...'.format(project_uuid), nl=False)
    api.projects_remove(cnf["user"][_get_hostname(stolos_url)], project_uuid)
    click.echo("\t\tOkay.")
    if remove_directory:
        click.echo("Clearing up Docker resources...")
        # Also, remove any leftover project resources.
        _config_environ(cnf)
        _compose(["down"]).wait()
        _deinitialize_project()
        click.echo("Okay.")
Example #17
0
def compose(ctx):
    _ensure_stolos_directory()
    cnf = config.get_config()
    _config_environ(cnf)
    _compose(ctx.args).wait()
Example #18
0
def launch(**kwargs):
    _ensure_stolos_directory()
    cnf = config.get_config()
    public_url = _get_url_for_service_port(cnf, **kwargs)
    click.echo("Opening http://{}...".format(public_url))
    click.launch("http://{}".format(public_url))