This section explains how to use the Connect Server APIs to create content in Posit Connect and implement the code associated with that content. These APIs can be used for all types of content powered by Posit Connect.
orstudio/connect-api-deploy-brilliant
The GitHub repository contains a brilliant sample application and uses the recipes in this section in deployment scripts that you can use as examples when creating your own workflows.
oConnect-Server-API-Referencescontains documentation for each of the endpoints used in these recipes.
supervision
Use these recipestried
cut and trustcurling
to execute HTTP requests. we use thatCONNECT_SERVER
miCONNECT_API_KEY
Environment variables introduced infrompart of this cookbook.
supervision
Some examples below simplify processing JSON responses using a command line tool calledjq
. details aboutjq
and installation information can be found on yourproject website.
examples#
These recipes do not prescribe a single workflow. Some example workflows include:
Automate the creation of a new application with a unique name every quarter to analyze sales opportunities. The latest quarter includes new dashboard features, but you can't change previous quarters; These applications need to record this point in time.
An API that receives updates after your continuous integration environment has fully tested the supporting code for that API. These tests confirm that all updates remain backward compatible.
A team collaborates on an app during a two-week sprint cycle. Code is shared with Git and progress is tracked on GitHub issues. The team performs production updates at the end of each sprint using a Docker-based deployment environment.
Your organization doesn't allow data scientists to publish directly to the production server. Production updates are scheduled events triggered by successful user acceptance tests. A deployment engineer who is not an R user uses scripts to create and publish content to production by interacting with the Connect Server APIs.
workflow#
The content delivery workflow consists of several steps:
- Create a new content item; Content can be provided multiple times.
- create a packageCapture your code and its dependencies.
- Upload the package filefor positive connection.
- optional,Set environment variableswhat the content needs at runtime.
- Deploy (activate) this package.and monitor your progress.
- Get updates for a task; Get the latest information on a dispatched operation.
You can create a new piece of content with each deployment or target the same piece of content repeatedly. It's a good idea to reuse existing content as you continue to develop this application or report. Create new content items for new artifacts.
Important
You must create a new content element if you change the content type. For example, you can't wrap an R Markdown document into a content element that already has a Dash application running.
create content#
oPOST /v1/contentThe API is the endpoint used to create a new content item in Posit Connect. A JSON document is used as input. Connect Server APIReference describes the full set of fields that can be provided to this endpoint.
Our example contains only two fields:Name
mititle
:
Name
: This field is required and must be unique across all content in your account. It is a friendly URL-compatible identifier.title
: This field is optional and a user-friendly identifier is defined here. when set,title
is displayed in the Posit Connect panel insteadName
.
Here's an example:
Export DATA='{"name": "shakespeare", "title": "Shakespeare-Wortwolken"}'curl --silent --show-error -L --max-redirs0--fail -X POST\-H"Permission: keypsCONNECT_API_KEY}" \--Data"psDATA}" \ "psCONNECT_SERVER}__api__/v1/content"# => {# => "guid": "ccbd1a41-90a0-4b7b-89c7-16dd9ad47eb5",# => "name": "shakespeare",# => "title": "Shakespeare-Wortwolken",# => ...# => "guid_propietario": "0b609163-aad5-4bfd-a723-444e446344e3",# => }
Additional content fields:
- The JSON response is the complete set of content fields.
- Fields that you did not specify when creating the content receive default values. EITHERConnect-Server-API-Referencesdescribes all the request and response fields for thePOST /v1/contentPoint.
Let's define aCONTENT_GUID
Environment variable that contains theGUID
of the content we just created. We use this variable in the remaining implementation examples:
Export CONTENT_GUID="ccbd1a41-90a0-4b7b-89c7-16dd9ad47eb5"
create a package#
The Posit Connect content pack is a point representation of your code. You can associate multiple packages with your content even if only one package is active. The active package is used to generate your report, run your application, and provide what you see when you visit this content in your browser.
Create packages that fit your workflow:
- As you improve/improve your content
- Equivalent to a Git commit or merge
- After testing is complete, run in your continuous integration environment
- After stakeholder review and approval
The package is uploaded to Posit Connect as.tar.gz
Archive. you will use themTeer
Utility to create this file. Before creating the file, let's think about what it should contain.
All source files used by your content. It is usually a collection of
.R
,.Rmd
,.py
, z.ipynb
files Also add the necessary HTML, CSS and Javascript resources.Data files, images, or other resources loaded when your content is run or viewed. Could be
.png
,.jpg
,.gif
,.csv
files If your report uses an Excel spreadsheet as input, include it!A
manifest.json
. This JSON file describes your content requirements. For R content, this includes a complete snapshot of all your package requirements. EITHERmanifest.json
is created withrsconnect::writeManifest
Function.On the command line:
# This directory should be your current working directory.Rscript -e'rsconnect::writeManifest()'
From an R console:
# This directory should be your current working directory.rsconectar::write a manifesto()
supervision
(Video) Kelly O'Briant | Build Your Ideal Showcase of Data Products | RStudio Connect 1.9.0please use
rsconectar
Version 0.8.15 or later when generating a manifest file.For python-based content, you can use the
rsconnect-python
Package to createmanifest.json
. Make sure the python environment you are using for your project is enabled, and create a manifest specific to your project type (diary
,API
,special feature
,Bokeh
, oilluminated
):rsconnect write manifestpsTYPICAL}./
Watch thersconnect-python-Documentationfor details.
We recommend walking it
manifest.json
in your source control system and regenerate it when you push new versions of your code, especially when you update packages or change their dependencies! Watch theUser's guidefor more information on how to create the manifest.supervision
o
manifest.json
Linked to an R Markdown site (eg.Book) must specify the content category "Website".# From an R console:rsconectar::write a manifesto(content category = "Property")
supervision
If your Posit Connect installation uses off-host content execution with Kubernetes (a feature currently in beta), you can optionally specify which Image Connect to use when creating your content:
# From an R console (this directory should be your current working directory):rsconectar::write a manifesto(image = "ghcr.io/rstudio/content-base:r4.0.5-py3.8.8-bionic")
# Using the `rsconnect-python` package:rsconnect write manifestpsTYPICAL}--Image"ghcr.io/rstudio/content-base:r4.0.5-py3.8.8-bionic"./
You can only use an image configured by your administrator. You can view a list of available images by logging into Posit Connect and clicking
documentation
at the top of the page. Consult the user manual pages foreditor of the RmiPublish from the command linefor more details.
Create your package.tar.gz
File after collecting the set of files to include. Here's an example that archives a simple brilliant app; EITHERApplication.R
contains the source R andData
is a directory with data files loaded by the application:
tar czf bundle.tar.gz manifest.json app.R datos
upload packages#
oCONTENT_GUID
The environment variable is the content into which the package will be loaded. Packets are assigned to exactly one content.
we use thatPOST/v1/content/{guid}/packagesEndpoint for loading content packs using thepackage.tar.gz
Archive as payload:
curl --silent --show-error -L --max-redirs0--fail -X POST\-H"Permission: keypsCONNECT_API_KEY}" \--binary-data @"package.tar.gz" \ "psCONNECT_SERVER}__api__/v1/content/psCONTENT_GUID}/Package"# => {"package_id":"485","package_size":162987}
The response from the upload end includes an identifier for the packet created and the number of bytes received.
Important
OfHE MUSTbenutze o--binary-data
argument in favorcurling
, which sends the data file without further processing. DoNObenutze o--Data
Argument: Send data the same way a browser does when you "submit" a form, and it's not appropriate.
Extract the package ID from the upload response and assign it to aBUNDLE_ID
Environmental variable:
Export BUNDLE_ID="485"
Set environment variables#
If your code depends on environment variables being set at runtime, for example to provide a token confidentially, you can use this recipe to set them:
# Create the JSON input to set the environment variables.SECRET_TOKEN=...DATA='[ {"name": "TAB", "wert": "'"psSECRET_TOKEN}"'"},{"name": "DATA_URL", "value": "https://example.com/data"}]'# Set the environment variables.curl --silent --show-error -L --max-redirs0--make it -X PARCHE\-H"Permission: keypsCONNECT_API_KEY}" \--Data"psDATA}" \ "psCONNECT_SERVER}__api__/v1/content/psCONTENT_GUID}/Surroundings"# => ["DATA_URL","FICHA"]
deploy a package#
This recipe explains how to deploy or activate a loaded package. assume thatCONTENT_GUID
refers to the target content element andBUNDLE_ID
Specifies the package to be deployed.
The package implementation triggers an asynchronous task that makes the loaded data available for viewing. The workflow applied to bundled files varies by content type.
This uses thePOST/v1/content/{guid}/implementarPoint:
Supervision:In this example, the cookie returned by the linked server is stored so that it can be passed to the task probe endpoint below. In a single node connection setup, the cookie can be omitted.
# Create the JSON entry that names the package to deploy.Export DATA='{"package_id":"'"psBUNDLE_ID}"'"}'# Activate an implementation.curl --silent --show-error -L --max-redirs0--fail -X POST\-H"Permission: keypsCONNECT_API_KEY}" \--Data"psDATA}" \-c Cookie.txt\ "psCONNECT_SERVER}__api__/v1/content/psCONTENT_GUID}/implant"# => {"id_tarea":"BkkakQAXicqIGxC1"}
The result of a deploy request includes a task ID that we use to query the progress of that deploy task:
Export TASK="BkkakQAXicqIGxC1"
homework survey#
The recipe explains how to check for updates for a task. It is assumed that the task ID exists in theTASK
environmental variable.
oGET /v1/tasks/{id}endpoint retrieves the latest information about a distributed operation.
Supervision:In high availability deployments of clustered Connect, the task request must be fulfilled by the node running the task. It does this by ensuring that any cookies returned by the provisioning process are included in subsequent requests so that the load balancer can correctly route the request. In a single node setup, the cookie can be omitted.
There are two ways to search for task information:
- You can request the output of the entire tasko
- You can request an incremental task output
oFirst
The URL query argument controls the amount of data that is returned.
This is a typical initial request for the progress of a task. do not specifyFirst
URL query argument, which means that all available results will be returned. YeahFirst
value is not givenfirst = 0
is assumed.
curl --silent --show-error -L --max-redirs0--fail\-H"Permission: keypsCONNECT_API_KEY}" \-b cookie.txt\ "psCONNECT_SERVER}__api__/v1/tasks/psTASK}?wait=1"# => {# => "id": "BkkakQAXicqIGxC1",# => "Salida": [# => "Create shiny app...",# => "Requested package R version 3.5.1; with...",# => ],# => "completed": false,# => "Code": 0,# => "Error": "",# => "last": 2# => }
owait = 1
The argument tells the server to capture output for up to one second. This long query approach is an alternative to explicitly sleeping on your query cycle.
oequipment
field in the response allows us to incrementally get the output of the task. Our original request returned two lines of output; We would like our next application to continue at this point.
Here's a task progress request that doesn't include the first two lines of output:
Export FIRST=2curl --silent --show-error -L --max-redirs0--fail\-H"Permission: keypsCONNECT_API_KEY}" \ "psCONNECT_SERVER}__api__/v1/tasks/psTASK}?wait=1&first=psFIRST}"# => {# => "id": "BkkakQAXicqIGxC1",# => "Salida": [# => "Delete the old manifest.json file for the packrat transform.",# => "Create manifest.json for packrat transformation.",# => ],# => "completed": false,# => "Code": 0,# => "Error": "",# => "last": 4# => }
Get task progress step by step until the answer is marked complete. The last few lines of output are included in this response.
Export FIRST=86curl --silent --show-error -L --max-redirs0--fail\-H"Permission: keypsCONNECT_API_KEY}" \ "psCONNECT_SERVER}__api__/v1/tasks/psTASK}?wait=1&first=psFIRST}"# => {# => "id": "BkkakQAXicqIGxC1",# => "Salida": [# => "Packrat build completed against R version: '3.4.4'",# => "Starting the Shiny application..."# => ],# => "done": true,# => "Code": 0,# => "Error": "",# => "last": 88# => }
Errors are indicated by a non-zero value in the response.Code
It's aError
News. It is likely that thesalida
stream also contains information to help you understand the cause of the error. For example, problems with installing Rpackages are shown in thesalida
.
Access to content provided#
The provided content can be accessed from the Connect panel at the URL returned inpain_url
:
# Get the dashboard URLDASHBOARD_URL=pscurl --silent --show-error -L --max-redirs0--fail\-H"Permission: keypsCONNECT_API_KEY}" \ "psCONNECT_SERVER}__api__/v1/content/psCONTENT_GUID}" |jq -r .dashboard_url)
Content can also be accessed directly, without using the Connect dashboard frameworkcontent url
:
# Get the URL of the contentCONTENT_URL=pscurl --silent --show-error -L --max-redirs0--fail\-H"Permission: keypsCONNECT_API_KEY}" \ "psCONNECT_SERVER}__api__/v1/content/psCONTENT_GUID}" |jq -r .Inhalts-URL)
You can visit the CONTENT_URL in a browser or use it to access content like the Plumber or Flask APIs. For example, if you have implemented a plumber API that responds toCORREO
orders in your/Assess
Point:
curl --silent --show-error -L --max-redirs0--fail -X POST\-H"Permission: keypsCONNECT_API_KEY}" \ "psCONTENT_URL}Assess"
Deploy a new version#
You can deploy a new version of your content using the methods described above:
- load a package
- Deploy the package
- Oversee the deployment task
If you run these tasks a second time, your API client must provide them.content_guid
returned when the content was first created.
Identify content by name#
Clients unable to save contentGUID
can deliver a singleName
to identify the content item to update.
When creating your content, provide unique value in theName
Camping:
Export NAME="my-unique-application-name"Export DATA='{"Name":"'psNAME}'"}'curl --silent --show-error -L --max-redirs0--fail -X POST\-H"Permission: keypsCONNECT_API_KEY}" \--Data"psDATA}" \ "psCONNECT_SERVER}__api__/v1/content"
By deploying an update, you can get the contentGUID
using the name. Content names are guaranteed to be unique within an individual user's account, but it is possible for multiple users to create content with the same name. To ensure that only one piece of content is returned, specify theGUID
of the user account that created the content.
# Get the GUID of the content creator (owner of this API key)curl --silent --show-error -L --max-redirs0--fail -X GET\-H"Permission: keypsCONNECT_API_KEY}" \ "psCONNECT_SERVER}__api__/v1/Benutzer"# => {# => "Email": "user@example.com",# => "username": "username",# => ...# => "guid": "0b609163-aad5-4bfd-a723-444e446344e3",# => }OWNER_GUID=„0b609163-aad5-4bfd-a723-444e446344e3“# Search for the app by name and ownercurl --silent --show-error -L --max-redirs0--fail -X GET\-H"Permission: keypsCONNECT_API_KEY}" \ "psCONNECT_SERVER}__api__/v1/content?name=psNAME}&guid_owner=psOWNER_GUID}"# => [# => {# => "guid": "ccbd1a41-90a0-4b7b-89c7-16dd9ad47eb5",# => "name": "my-unique-application-name",# => ...# => "guid_propietario": "0b609163-aad5-4bfd-a723-444e446344e3",# => }# => ]CONTENT_GUID="ccbd1a41-90a0-4b7b-89c7-16dd9ad47eb5"
Then follow the usual upgrade steps and go through theCONTENT_GUID
when loading and deploying the package.