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)
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 "))
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
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, )
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, )
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)
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))
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, )
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)
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)
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")
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)))
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()
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, )