示例#1
0
def write_manifest_notebook(overwrite, python, conda, force_generate, verbose, file, extra_files):
    set_verbosity(verbose)
    with cli_feedback("Checking arguments"):
        validate_file_is_notebook(file)

        base_dir = dirname(file)
        extra_files = validate_extra_files(base_dir, extra_files)
        manifest_path = join(base_dir, "manifest.json")

        if exists(manifest_path) and not overwrite:
            raise api.RSConnectException("manifest.json already exists. Use --overwrite to overwrite.")

    with cli_feedback("Inspecting Python environment"):
        python, environment = get_python_env_info(file, python, conda, force_generate)

    _warn_on_ignored_conda_env(environment)

    with cli_feedback("Creating manifest.json"):
        environment_file_exists = write_notebook_manifest_json(
            file, environment, AppModes.JUPYTER_NOTEBOOK, extra_files
        )

    if environment_file_exists and not force_generate:
        click.secho(
            "    Warning: %s already exists and will not be overwritten." % environment.filename, fg="yellow",
        )
    else:
        with cli_feedback("Creating %s" % environment.filename):
            write_environment_file(environment, base_dir)
示例#2
0
def details(name, server, api_key, insecure, cacert, verbose):
    set_verbosity(verbose)

    with cli_feedback("Checking arguments"):
        connect_server = _validate_deploy_to_args(name, server, api_key, insecure, cacert, api_key_is_required=False)

    click.echo("    RStudio Connect URL: %s" % connect_server.url)

    if not connect_server.api_key:
        return

    with cli_feedback("Gathering details"):
        server_details = gather_server_details(connect_server)

    connect_version = server_details["connect"]
    apis_allowed = server_details["python"]["api_enabled"]
    python_versions = server_details["python"]["versions"]
    conda_details = server_details["conda"]

    click.echo("    RStudio Connect version: %s" % ("<redacted>" if len(connect_version) == 0 else connect_version))

    if len(python_versions) == 0:
        click.echo("    No versions of Python are installed.")
    else:
        click.echo("    Installed versions of Python:")
        for python_version in python_versions:
            click.echo("        %s" % python_version)

    click.echo("    APIs: %sallowed" % ("" if apis_allowed else "not "))

    if future_enabled:
        click.echo("    Conda: %ssupported" % ("" if conda_details["supported"] else "not "))
示例#3
0
def _test_server_and_api(server, api_key, insecure, ca_cert):
    """
    Test the specified server information to make sure it works.  If so, a
    ConnectServer object is returned with the potentially expanded URL.

    :param server: the server URL, which is allowed to be missing its scheme.
    :param api_key: an optional API key to validate.
    :param insecure: a flag noting whether TLS host/validation should be skipped.
    :param ca_cert: the name of a CA certs file containing certificates to use.
    :return: a tuple containing an appropriate ConnectServer object and the username
    of the user the API key represents (or None, if no key was provided).
    """
    ca_data = ca_cert and text_type(ca_cert.read())
    me = None

    with cli_feedback("Checking %s" % server):
        real_server, _ = test_server(api.RSConnectServer(server, None, insecure, ca_data))

    real_server.api_key = api_key

    if api_key:
        with cli_feedback("Checking API key"):
            me = test_api_key(real_server)

    return real_server, me
示例#4
0
def _deploy_bundle(
    connect_server,
    app_store,
    primary_path,
    app_id,
    app_mode,
    name,
    title,
    title_is_default,
    bundle,
):
    """
    Does the work of uploading a prepared bundle.

    :param connect_server: the Connect server information.
    :param app_store: the store where data is saved about deployments.
    :param primary_path: the base path (file or directory) that's being deployed.
    :param app_id: the ID of the app.
    :param app_mode: the mode of the app.
    :param name: the name of the app.
    :param title: the title of the app.
    :param title_is_default: a flag noting whether the title carries a defaulted value.
    :param bundle: the bundle to deploy.
    """
    with cli_feedback("Uploading bundle"):
        app = deploy_bundle(connect_server, app_id, name, title,
                            title_is_default, bundle)

    with cli_feedback("Saving deployment data"):
        app_store.set(
            connect_server.url,
            abspath(primary_path),
            app["app_url"],
            app["app_id"],
            app["app_guid"],
            title,
            app_mode,
        )

    with cli_feedback(""):
        click.secho("\nDeployment log:", fg="bright_white")
        app_url, _ = spool_deployment_log(connect_server, app, click.echo)
        click.secho("Deployment completed successfully.", fg="bright_white")
        click.secho("    Dashboard content URL: %s" % app_url,
                    fg="bright_white")
        click.secho("    Direct content URL: %s" % app["app_url"],
                    fg="bright_white")

        # save the config URL, replacing the old app URL we got during deployment
        # (which is the Open Solo URL).
        app_store.set(
            connect_server.url,
            abspath(primary_path),
            app_url,
            app["app_id"],
            app["app_guid"],
            app["title"],
            app_mode,
        )
示例#5
0
def deploy_manifest(name, server, api_key, insecure, cacert, new, app_id,
                    title, verbose, file):
    set_verbosity(verbose)

    with cli_feedback("Checking arguments"):
        connect_server = _validate_deploy_to_args(name, server, api_key,
                                                  insecure, cacert)
        file = validate_manifest_file(file)
        app_store = AppStore(file)

        (
            app_id,
            deployment_name,
            title,
            default_title,
            app_mode,
            package_manager,
        ) = gather_basic_deployment_info_from_manifest(connect_server,
                                                       app_store, file, new,
                                                       app_id, title)

    click.secho('    Deploying %s to server "%s"' % (file, connect_server.url),
                fg="white")

    if package_manager == "conda":
        with cli_feedback("Ensuring Conda is supported"):
            check_server_capabilities(connect_server,
                                      [is_conda_supported_on_server])

    with cli_feedback("Creating deployment bundle"):
        try:
            bundle = make_manifest_bundle(file)
        except IOError as error:
            msg = "Unable to include the file %s in the bundle: %s" % (
                error.filename,
                error.args[1],
            )
            if error.args[0] == errno.ENOENT:
                msg = "\n".join([
                    msg,
                    "Since the file is missing but referenced in the manifest, "
                    "you will need to\nregenerate your manifest.  See the help "
                    'for the "write-manifest" command or,\nfor non-Python '
                    'content, run the "deploy other-content" command.',
                ])
            raise api.RSConnectException(msg)

    _deploy_bundle(
        connect_server,
        app_store,
        file,
        app_id,
        app_mode,
        deployment_name,
        title,
        default_title,
        bundle,
    )
示例#6
0
def _write_framework_manifest(
    overwrite,
    entrypoint,
    exclude,
    python,
    conda,
    force_generate,
    verbose,
    directory,
    extra_files,
    app_mode,
):
    """
    A common function for writing manifests for APIs as well as Dash, Streamlit, and Bokeh apps.

    :param overwrite: overwrite the manifest.json, if it exists.
    :param entrypoint: the entry point for the thing being deployed.
    :param exclude: a sequence of exclude glob patterns to exclude files from
                    the deploy.
    :param python: a path to the Python executable to use.
    :param conda: a flag to note whether Conda should be used/assumed..
    :param force_generate: a flag to force the generation of manifest and
                           requirements file.
    :param verbose: a flag to produce more (debugging) output.
    :param directory: the directory of the thing to deploy.
    :param extra_files: any extra files that should be included.
    :param app_mode: the app mode to use.
    """
    set_verbosity(verbose)

    with cli_feedback("Checking arguments"):
        entrypoint = validate_entry_point(entrypoint)
        extra_files = validate_extra_files(directory, extra_files)
        manifest_path = join(directory, "manifest.json")

        if exists(manifest_path) and not overwrite:
            raise api.RSConnectException(
                "manifest.json already exists. Use --overwrite to overwrite.")

    with cli_feedback("Inspecting Python environment"):
        _, environment = get_python_env_info(directory, python, conda,
                                             force_generate)

    _warn_on_ignored_conda_env(environment)

    with cli_feedback("Creating manifest.json"):
        environment_file_exists = write_api_manifest_json(
            directory, entrypoint, environment, app_mode, extra_files, exclude)

    if environment_file_exists and not force_generate:
        click.secho(
            "    Warning: %s already exists and will not be overwritten." %
            environment.filename,
            fg="yellow",
        )
    else:
        with cli_feedback("Creating %s" % environment.filename):
            write_environment_file(environment, directory)
示例#7
0
def create_tag(name, server, api_key, insecure, cacert, verbose, tag_array):
    set_verbosity(verbose)

    with cli_feedback("Checking arguments"):
        connect_server = _validate_deploy_to_args(name, server, api_key, insecure, cacert)
        # TODO: check that can write tags...

    connect_client = api.RSConnect(connect_server)

    with cli_feedback("Creating tag tree"):
        tag_tree = api.create_tag_tree(connect_client, *tag_array)
        tag_tree_names = [tag['name'] for tag in tag_tree]

    click.secho("    Tag tree created: %s" % format_tag_tree(tag_tree_names))
示例#8
0
def deploy_notebook(
    name,
    server,
    api_key,
    insecure,
    cacert,
    static,
    new,
    app_id,
    title,
    python,
    conda,
    force_generate,
    verbose,
    file,
    extra_files,
):
    set_verbosity(verbose)

    with cli_feedback("Checking arguments"):
        app_store = AppStore(file)
        connect_server = _validate_deploy_to_args(name, server, api_key, insecure, cacert)
        extra_files = validate_extra_files(dirname(file), extra_files)
        (app_id, deployment_name, title, default_title, app_mode,) = gather_basic_deployment_info_for_notebook(
            connect_server, app_store, file, new, app_id, title, static
        )

    click.secho('    Deploying %s to server "%s"' % (file, connect_server.url), fg="white")

    _warn_on_ignored_manifest(dirname(file))

    with cli_feedback("Inspecting Python environment"):
        python, environment = get_python_env_info(file, python, conda, force_generate)

    if environment.package_manager == "conda":
        with cli_feedback("Ensuring Conda is supported"):
            check_server_capabilities(connect_server, [is_conda_supported_on_server])
    else:
        _warn_on_ignored_conda_env(environment)

    if force_generate:
        _warn_on_ignored_requirements(dirname(file), environment.filename)

    with cli_feedback("Creating deployment bundle"):
        bundle = create_notebook_deployment_bundle(file, extra_files, app_mode, python, environment, False)

    _deploy_bundle(
        connect_server, app_store, file, app_id, app_mode, deployment_name, title, default_title, bundle,
    )
示例#9
0
def info(file):
    with cli_feedback(""):
        for file_name in _get_names_to_check(file):
            app_store = AppStore(file_name)
            deployments = app_store.get_all()

            if len(deployments) > 0:
                break

        if len(deployments) > 0:
            click.echo("Loaded deployment information from %s" % abspath(app_store.get_path()))

            for deployment in deployments:
                # If this deployment was via a manifest, this will get us extra stuff about that.
                file_name = deployment.get("filename")
                entry_point, primary_document = describe_manifest(file_name)
                label = "Directory:" if isdir(file_name) else "Filename: "
                click.echo()
                click.echo("Server URL: %s" % click.style(deployment.get("server_url"), fg="white"))
                click.echo("    App URL:     %s" % deployment.get("app_url"))
                click.echo("    App ID:      %s" % deployment.get("app_id"))
                click.echo("    App GUID:    %s" % deployment.get("app_guid"))
                click.echo('    Title:       "%s"' % deployment.get("title"))
                click.echo("    %s   %s" % (label, file_name))
                if entry_point:
                    click.echo("    Entry point: %s" % entry_point)
                if primary_document:
                    click.echo("    Primary doc: %s" % primary_document)
                click.echo("    Type:        %s" % AppModes.get_by_name(deployment.get("app_mode"), True).desc())
        else:
            click.echo("No saved deployment information was found for %s." % file)
示例#10
0
def remove(name, server, verbose):
    set_verbosity(verbose)

    message = None

    with cli_feedback("Checking arguments"):
        if name and server:
            raise api.RSConnectException("You must specify only one of -n/--name or -s/--server.")

        if not (name or server):
            raise api.RSConnectException("You must specify one of -n/--name or -s/--server.")

        if name:
            if server_store.remove_by_name(name):
                message = 'Removed nickname "%s".' % name
            else:
                raise api.RSConnectException('Nickname "%s" was not found.' % name)
        else:  # the user specified -s/--server
            if server_store.remove_by_url(server):
                message = 'Removed URL "%s".' % server
            else:
                raise api.RSConnectException('URL "%s" was not found.' % server)

    if message:
        click.echo(message)
示例#11
0
def deploy_git(name, server, api_key, insecure, cacert, verbose, app_name, repository, branch, subdirectory):
    set_verbosity(verbose)

    with cli_feedback("Checking arguments"):
        connect_server = _validate_deploy_to_args(name, server, api_key, insecure, cacert)

    connect_client = api.RSConnect(connect_server)

    with cli_feedback("Deploying git repository"):
        app = connect_client.deploy_git(app_name, repository, branch, subdirectory)

    with cli_feedback(""):
        click.secho("\nDeployment log:", fg="bright_white")
        app_url, _ = spool_deployment_log(connect_server, app, click.echo)
        click.secho("Deployment completed successfully.", fg="bright_white")
        click.secho("    Dashboard content URL: %s" % app_url, fg="bright_white")
        click.secho("    Direct content URL: %s" % app["app_url"], fg="bright_white")


    click.secho("Git deployment completed successfully.", fg="bright_white")
    click.secho("App available as %s" % app_name, fg="bright_white")
示例#12
0
def content_tag(name, server, api_key, insecure, cacert, app_id, verbose, app, tag_array):

    set_verbosity(verbose)

    with cli_feedback("Checking arguments"):
        if isdir(app):
            module_file = fake_module_file_from_directory(app)
            app_store = AppStore(module_file)
        else:
            app_store = AppStore(app)
        connect_server = _validate_deploy_to_args(name, server, api_key, insecure, cacert)
        app_id = gather_app_id(connect_server, app_store, app_id)

    connect_client = api.RSConnect(connect_server)
    with cli_feedback("Tagging content"):
        new_tag = api.get_tag_tree(connect_client, *tag_array)
        connect_server.handle_bad_response_generic(new_tag)
        connect_client.app_tag(app_id, new_tag["id"])
        # TODO: some type of error handling...

    click.secho("    Successfully tagged app %s : %s" % (app_id, format_tag_tree(tag_array)))
示例#13
0
def list_servers(verbose):
    set_verbosity(verbose)
    with cli_feedback(""):
        servers = server_store.get_all_servers()

        click.echo("Server information from %s" % server_store.get_path())

        if not servers:
            click.echo("No servers are saved. To add a server, see `rsconnect add --help`.")
        else:
            click.echo()
            for server in servers:
                click.echo('Nickname: "%s"' % server["name"])
                click.echo("    URL: %s" % server["url"])
                click.echo("    API key is saved")
                if server["insecure"]:
                    click.echo("    Insecure mode (TLS host/certificate validation disabled)")
                if server["ca_cert"]:
                    click.echo("    Client TLS certificate data provided")
                click.echo()
示例#14
0
def _deploy_by_framework(
    name,
    server,
    api_key,
    insecure,
    cacert,
    entrypoint,
    exclude,
    new,
    app_id,
    title,
    python,
    conda,
    force_generate,
    verbose,
    directory,
    extra_files,
    gatherer,
):
    """
    A common function for deploying APIs, as well as Dash, Streamlit, and Bokeh apps.

    :param name: the nickname of the Connect server to use.
    :param server: the URL of the Connect server to use.
    :param api_key: the API key to use to authenticate with Connect.
    :param insecure: a flag noting whether insecure TLS should be used.
    :param cacert: a path to a CA certificates file to use with TLS.
    :param entrypoint: the entry point for the thing being deployed.
    :param exclude: a sequence of exclude glob patterns to exclude files
                    from the deploy.
    :param new: a flag to force the deploy to be new.
    :param app_id: the ID of the app to redeploy.
    :param title: the title to use for the app.
    :param python: a path to the Python executable to use.
    :param conda: a flag to note whether Conda should be used/assumed..
    :param force_generate: a flag to force the generation of manifest and
                           requirements file.
    :param verbose: a flag to produce more (debugging) output.
    :param directory: the directory of the thing to deploy.
    :param extra_files: any extra files that should be included.
    :param gatherer: the function to use to gather basic information.
    """
    set_verbosity(verbose)

    with cli_feedback("Checking arguments"):
        connect_server = _validate_deploy_to_args(name, server, api_key, insecure, cacert)
        module_file = fake_module_file_from_directory(directory)
        extra_files = validate_extra_files(directory, extra_files)
        app_store = AppStore(module_file)
        entrypoint, app_id, deployment_name, title, default_title, app_mode = gatherer(
            connect_server, app_store, directory, entrypoint, new, app_id, title
        )

    click.secho('    Deploying %s to server "%s"' % (directory, connect_server.url), fg="white")

    _warn_on_ignored_manifest(directory)

    with cli_feedback("Inspecting Python environment"):
        _, environment = get_python_env_info(module_file, python, conda, force_generate)

    with cli_feedback("Checking server capabilities"):
        checks = [are_apis_supported_on_server]
        if environment.package_manager == "conda":
            checks.append(is_conda_supported_on_server)
        check_server_capabilities(connect_server, checks)

    _warn_on_ignored_conda_env(environment)

    if force_generate:
        _warn_on_ignored_requirements(directory, environment.filename)

    with cli_feedback("Creating deployment bundle"):
        bundle = create_api_deployment_bundle(directory, extra_files, exclude, entrypoint, app_mode, environment, False)

    _deploy_bundle(
        connect_server, app_store, directory, app_id, app_mode, deployment_name, title, default_title, bundle,
    )