Role Workflows

Pulp organizes role content into repositories, and you associate the ansible-galaxy client with one or more repositories. From a high level you can:

  1. Create a repo
  2. Create a distribution expose that repository at a URL
  3. Sync content from galaxy.ansible.com
  4. Install content from the repo with ansible-galaxy

API Client Setup

To use the bash examples on this page. Run these basic bash utilities below:

#!/usr/bin/env bash
echo "Setting environment variables for default hostname/port for the API and the Content app"
export BASE_ADDR=${BASE_ADDR:-http://localhost:24817}
export CONTENT_ADDR=${CONTENT_ADDR:-http://localhost:24816}

# Necessary for `django-admin`
export DJANGO_SETTINGS_MODULE=pulpcore.app.settings

# Poll a Pulp task until it is finished.
wait_until_task_finished() {
    echo "Polling the task until it has reached a final state."
    local task_url=$1
    while true
    do
        local response=$(http $task_url)
        local state=$(jq -r .state <<< ${response})
        jq . <<< "${response}"
        case ${state} in
            failed|canceled)
                echo "Task in final state: ${state}"
                exit 1
                ;;
            completed)
                echo "$task_url complete."
                break
                ;;
            *)
                echo "Still waiting..."
                sleep 2
                ;;
        esac
    done
}

Create a Repository

Create a repository and name it the foo repository.

echo "Start by creating a new repository named foo"
http POST $BASE_ADDR/pulp/api/v3/repositories/ansible/ansible/ name=foo

# If you want to copy/paste your way through the guide,
# create an environment variable for the repository URI.
export REPO_HREF=$(http $BASE_ADDR/pulp/api/v3/repositories/ansible/ansible/ | \
  jq -r '.results[] | select(.name == "foo") | .pulp_href')

echo "Inspecting repository."
http $BASE_ADDR$REPO_HREF

Repository GET Response:

{
    "pulp_created": "2019-04-29T15:57:59.763712Z",
    "pulp_href": "/pulp/api/v3/repositories/ansible/ansible/1b2b0af1-5588-4b4b-b2f6-cdd3a3e1cd36/",
    "latest_version_href": null,
    "versions_href": "/pulp/api/v3/repositories/ansible/ansible/1b2b0af1-5588-4b4b-b2f6-cdd3a3e1cd36/versions/",
    "description": "",
    "name": "foo"
}

Reference (pulpcore): Repository API Usage

Create a Distribution for Repository ‘foo’

This will make the latest Repository Version content available for ansible-galaxy` clients. Each distribution names the url it can be accessed from on an attribute called ``client_url. The client_url can be used with the ansible-galaxy client with the -s option. See the Install a Role, hosted by Pulp, using ansible-galaxy docs for more details.

For example a distribution with base_path set to my_content could have a URL like:

http://pulp.example.com/pulp_ansible/galaxy/my_content/
# Distributions are created asynchronously. Create one, and specify the publication that will
# be served at the base path specified.
export TASK_HREF=$(http POST $BASE_ADDR/pulp/api/v3/distributions/ansible/ansible/ \
  name='baz' \
  base_path='my_content' \
  repository=${REPO_HREF} | jq -r '.task')

# Poll the task (here we use a function defined in docs/_scripts/base.sh)
# When the task is complete, it gives us the href for our new Distribution
wait_until_task_finished $BASE_ADDR$TASK_HREF
export DIST_PATH=${CREATED_RESOURCE[0]}

# Lets inspect the Distribution
http $BASE_ADDR$DIST_PATH
{
    "pulp_created": "2019-07-26T16:46:23.666410Z",
    "pulp_href": "/pulp/api/v3/distributions/ansible/ansible/4262ed83-e86c-4a13-baff-fc543c46a391/",
    "base_path": "my_content",
    "base_url": "/pulp/content/foo",
    "content_guard": null,
    "name": "baz",
    "repository": "/pulp/api/v3/repositories/ansible/ansible/301bec4f-c5e7-4a20-a124-f8a1ec1f9229/",
    "repository_version": null
}

Create a Distribution for a RepositoryVersion (optional)

Instead of always distributing the latest RepositoryVersion, you can also specify a specific RepositoryVersion for a Distribution. This should be used in place of the distribution above, not in addition to it.

# Distributions are created asynchronously. Create one, and specify the publication that will
# be served at the base path specified.
export TASK_HREF=$(http POST $BASE_ADDR/pulp/api/v3/distributions/ansible/ansible/ \
  name='baz' \
  base_path='my_content' \
  repository_version=${REPO_HREF}versions/1/ | jq -r '.task')

# Poll the task (here we use a function defined in docs/_scripts/base.sh)
# When the task is complete, it gives us the href for our new Distribution
wait_until_task_finished $BASE_ADDR$TASK_HREF
export DIST_PATH=${CREATED_RESOURCE[0]}

# Lets inspect the Distribution
http $BASE_ADDR$DIST_PATH
{
    "pulp_created": "2019-07-26T16:51:04.803014Z",
    "pulp_href": "/pulp/api/v3/distributions/ansible/ansible/c9879338-8656-46aa-a2b2-46fa5d7b0329/",
    "base_path": "my_content",
    "base_url": "/pulp/content/foo",
    "content_guard": null,
    "name": "baz",
    "repository": null,
    "repository_version": "/pulp/api/v3/repositories/ansible/ansible/301bec4f-c5e7-4a20-a124-f8a1ec1f9229/versions/1/"
}

Create a Remote

Creating a Remote object informs Pulp about an external content source, which most commonly is https://galaxy.ansible.com/ or another pulp_ansible instance. In this case, we will be syncing all Roles where namespace=elastic on Galaxy. You can browse those Roles Pulp will import here.

echo "Create a remote that syncs some versions of django into your repository."
http POST $BASE_ADDR/pulp/api/v3/remotes/ansible/ansible/ \
    name='bar' \
    url='https://galaxy.ansible.com/api/v1/roles/?namespace__name=elastic'

# Export an environment variable for the new remote URI.
export REMOTE_HREF=$(http $BASE_ADDR/pulp/api/v3/remotes/ansible/ansible/ | jq -r '.results[] | select(.name == "bar") | .pulp_href')

echo "Inspecting new Remote."
http $BASE_ADDR$REMOTE_HREF

Remote GET Response:

{
    "pulp_href": "/pulp/api/v3/remotes/ansible/ansible/e1c65074-3a4f-4f06-837e-75a9a90f2c31/",
}

Sync Repository foo with Remote

Use the Remote object to kick off a synchronize task by specifying the Repository to sync with. You are telling Pulp to fetch content from the Remote and add to the Repository.

#!/usr/bin/env bash

# Sync repository foo using remote bar
echo "Create a task to sync the repository using the remote."
export TASK_HREF=$(http POST $BASE_ADDR$REPO_HREF'sync/' \
    remote=$REMOTE_HREF \
    | jq -r '.task')

# Poll the task (here we use a function defined in docs/_scripts/base.sh)
wait_until_task_finished $BASE_ADDR$TASK_HREF

# After the task is complete, it gives us a new repository version
echo "Set REPOVERSION_HREF from finished task."
export REPOVERSION_HREF=$(http $BASE_ADDR$TASK_HREF| jq -r '.created_resources | first')

echo "Inspecting RepositoryVersion."
http $BASE_ADDR$REPOVERSION_HREF

Repository Version GET Response (when complete):

{
    "pulp_href": "/pulp/api/v3/repositories/ansible/ansible/78286e2c-829a-4a8c-a3ca-3a2e490e01a7/versions/1/",
    "base_version": null,
    "content_summary": {
        "added": {
            "ansible.role": {
                "count": 16,
                "href": "/pulp/api/v3/content/ansible/roles/?repository_version_added=/pulp/api/v3/repositories/ansible/ansible/78286e2c-829a-4a8c-a3ca-3a2e490e01a7/versions/1/"
            }
        },
        "present": {
            "ansible.role": {
                "count": 16,
                "href": "/pulp/api/v3/content/ansible/roles/?repository_version=/pulp/api/v3/repositories/ansible/ansible/78286e2c-829a-4a8c-a3ca-3a2e490e01a7/versions/1/"
            }
        },
        "removed": {}
    },
    "number": 1
}

Reference (pulpcore): Repository Version List API Usage

Install a Role, hosted by Pulp, using ansible-galaxy

Using a direct path

Install your role by name by specifying the distribution serving your Repository’s content using the -s option.

ansible-galaxy install elasticsearch,6.2.4 -c -s http://pulp.example.com/pulp_ansible/galaxy/my_content/

Configuring ansible-galaxy Permanently

Use the ansible-galaxy config files to specify the distribution ansible-galaxy should interact with. To use this, set up your distribution in your ansible config (e.g. ~/.ansible.cfg or /etc/ansible/ansible.cfg):

[galaxy]
server: http://pulp.example.com/pulp_ansible/galaxy/my_content/

Then you can install without the -s url

$ ansible-galaxy install elastic.elasticsearch,6.2.4
- downloading role 'elasticsearch', owned by elastic
- downloading role from http://localhost:24816/pulp/content/dev/elastic/elasticsearch/6.2.4.tar.gz
- extracting elastic.elasticsearch to /home/vagrant/.ansible/roles/elastic.elasticsearch
- elastic.elasticsearch (6.2.4) was installed successfully

Add/Remove Content to a Repository

Whether your Role was fetched with a sync or uploaded, any content can also be added/removed to a repository manually:

http POST pulp.example.com/pulp/api/v3/repositories/ansible/ansible/modify/ \
    add_content_units:="['/pulp/api/v3/content/ansible/roles/d2bab58c-50f2-4f1d-9cf0-8ceb1680f31b/']"

This is entirely implemented by pulpcore, please see their reference docs for more information.

Reference (pulpcore): Repository Version Creation API Usage