CenturyLink's Runner enables teams, developers, and engineers to quickly provision, interact, and modify their environment on the CenturyLink Platform or third-party clouds, as well as on-premise and in private data centers. Runner brings together state-based and parallel job execution with multi-cloud and multi-data center execution. All in one powerful engine.

Our goal is to make automation and orchestration easy and accessible to everyone, from the most advanced users to those new to the Cloud. Runner makes it easy to create jobs and execute them, regardless of your environment or skill level.

Your First Runner Job

This tutorial guides you through the steps necessary to build and execute your first Runner job. Runner works against any publicly accessible system and any system in an environment that supports VPN connectivity. This guide builds a Runner job for systems in the CenturyLink Cloud. This allows us to defer conversations about distributed executions for a later tutorial and just focus on developing the execution job.

Outline

  • How to define a simple playbook
  • How to define a simple Runner Job
  • How to submit a Job and interpret the response

Getting Started

If you don't have a CenturyLink Cloud account, no worries! Start a 30-day Free Trial!

Once your account is set up we will collect a few credential related items before proceeding. We are going to need a Bearer Token to pass in with our job definitions. The Bearer Token provides the user info necessary to authenticate to the CenturyLink Cloud Platform prior to executing any tasks.

To Retrieve your Bearer Token:

The API URL for the request is: https://api.ctl.io/v2/authentication/login

We can get our Bearer Token in an adhoc manner by executing the following CURL command:

`curl -H "Content-Type: application/json" -XPOST https://api.ctl.io/v2/authentication/login --data '{"username":"~your-userid~","password":"~your-password~"}'`

The result is a JSON formated collection of account information. In this collection you will see the Bearer Token we're after:

    {
      "userName":"me-user",
      "accountAlias":"aac",
      "locationAlias":"NY1",
      "roles":["AccountAdmin"],
      "bearerToken":"eyJ0eXAiOi. . . kJWU8EaIgNPmMuJQIjk"
    }

A Simple Playbook: Create a Server in your Account

Our example here creates a simple playbook which uses the CLC Ansible modules to create a server in our default group.

The tutorial assumes that you have some experience with developing Ansible playbooks. So we focus primarily on the CenturyLink Cloud module necessary to create the server without going into any depth on the surrounding playbook.

Here is our playbook:

---
    ---
    - name: Create a Server
        hosts: localhost
        gather_facts: False
        connection: local
        tasks:
        - name: Deploy a new Ubuntu VM to Default Group
            clc_server:
            name: test
            template: ubuntu-14-64
            count: 1
            group: 'Default Group'
           register: clc
        - name: debug
            debug: var=clc.server_ids

Now that the playbook is written, it needs to be stored in a GitHub repo. Please see Github for instructions on creating and publishing a project. We will create a Github project based on the following directory structure for our project:

    runneruprunning/
          first_playbook.yml

The GIT URL for the project, which we make reference to through the tutorial, is [https://github.com/clc-runner/runneruprunning.git]. The project can be found here.

Create a Runner Job

The CenturyLink Runner team has an online utility that helps create playbooks, but for this instance we build ours manually. We start with a basic job skeleton:

    {
          "callbacks": [
            {
                  "level": "DEBUG",
                  "url": "http://3be37ce9.proxy.webhookapp.com/"
            }
          ],
          "description": "First Playbook Sample",
           "repository": {
            "branch": "master",
            "credentials": {
                  "password": "string",
                  "username": "string"
            },
            "defaultPlaybook": "first_playbook.yml",
            "url": "https://github.com/clc-runner/runneruprunning.git"
          },
          "useDynamicInventory": true
    }

The Elements of a Basic Playbook:

Callbacks Callbacks allow you to provide a URL endpoint for a webhook. Each status message that is generated for internal logging will also be sent to the URL.

    . . .
    "callbacks": [
        {
            "level": "DEBUG",
            "url": "http://3be37ce9.proxy.webhookapp.com/"
        }
    ]
    . . .

You can set the level of messages you would like to receive. For example, if you wanted to receive all messages you can set the level to DEBUG. These messages are sent out real-time so you can follow along with the execution of your Job.

TIP: There are several free webhook and debugging sites available. This example uses Webhookapp.

Description The description attribute allows you to provide a detailed description of the purpose of the job.

    . . .
    "description":"My first Playbook which allocates a new VM in my account."
    . . .

Repository The repository section is where you provide the information necessary to retrieve your playbook from Github.

    . . .
    "repository": {
        "url": "https://github.com/clc-runner/runneruprunning.git",
        "branch": "master",
        "defaultPlaybook": "first_playbook.yml",
        "credentials": {
            "password": "string",
            "username": "string"
        }
    }
    . . .

The first item needed is the URL to your Github repository. Next is the branch name where your playbook resides. If you do not provide a branch name, the default branch, as set in GitHub, is used as the branch. You also have to provide the name of the top level playbook you would like to have executed. Last, you have to provide your GitHub credentials, unless the GitHub repo is a public repository. The GitHub repo for this example is public so you don't have to provide the 'credentials' section.

useDynamicInventory

This flag signals the execution-runner to create an inventory of all the items in your account alias at runtime. Setting this flag to True isn't always necessary, especially if you are providing the name of the hosts you would like to execution the playbook against.

    . . .
    "useDynamicInventory":"True"
    . . .

Execution

Next, we ask for an immediate execution of our playbook once we submit the job definition. We are also going to use CURL to submit our Job request so that you can see what HTTP headers are necessary.

Before we move onto submitting our job for execution, let's capture the job definition from above into a local file named JobDef.json. This way, we can reference our job through a file reference, which keeps our CURL command a little cleaner.

So now our job submission request is as follows:

`curl -X PUT
-H "Content-Type: application/json"
-H "Authorization: Bearer eyJ0eXAiOiJ . . . yEbKmNA"
-d @JobDef.json
https://api.runner.ctl.io/jobs/BMHC?immediate=true`

##The Elements of Our Request Are:

The Method

To create a Runner job we use the PUT method:

    . . . -X PUT . . .

The HTTP Headers

As part of the HTTP Headers we specify that the content type of our request is JSON and then pass in our Bearer Token.

    . . .
    -H "Content-Type: application/json"
    -H "Authorization: Bearer eyJ0eXAiOiJ . . . yEbKmNA"
    . . .

Our Job Definition

We captured our job definition into a file so we simply make reference to that file. The file should be local to the directory in which we are running the CURL command.

    . . . -d @JobDef.json . . .

The "URL"

And finally, the URL endpoint:

    . . .
    https://api.runner.ctl.io/jobs/BMHC?immediate=true
    . . .

Note some key elements which we had to reference in the URL. First, we had to identify the service we wanted to process our request:

    .../jobs/...

Next, we had to provide our AccountAlias identifier:

    ... /BMHC ...

And the last bit of the URL signals the Job service to immediately execute the defined Job:

    ... ?immediate=true

And the result from our request is:

    {
        "id":"717e3f60-77f6-4d26-ad12-349e5767bc6c",
        "accountAlias":"BMHC",
        "description":"First Playbook Sample",
        "repository":{
            "url":"https://github.com/clc-runner/runneruprunning.git",
            "branch":"master",
            "defaultPlaybook":"first_playbook.yml",
            "hosts":[],
            "useDynamicInventory":true,
            "properties":{},
            "status":"ACTIVE",
            "callbacks":[
                {
                    "url":"http://3be37ce9.proxy.webhookapp.com/",
                    "level":"DEBUG"
                }
            ],
            "createdTime":1441226804323,
            "lastUpdatedTime":1441226804323,
            "links":[
                {
                    "ref":"self",
                    "id":"717e3f60-77f6-4d26-ad12-349e5767bc6c",
                    "href":"/v2/workflow/BMHC/jobs/717e3f60-77f6-4d26-ad12-349e5767bc6c",
                    "verbs":["GET","POST","DELETE"]
                },
                {
                    "ref":"self","id":"717e3f60-77f6-4d26-ad12-349e5767bc6c",
                    "href":"/v2/workflow/BMHC/jobs/717e3f60-77f6-4d26-ad12-349e5767bc6c/executions",
                    "verbs":["GET"]
                }
            ]
        }

Taking a closer look at the response you can see that it simply echo's back the job definition we just submitted, along with a couple of timestamps, an ID which is unique to this job definition, and some reference links we can use if we want to directly query for the status of the Job.

Validation

Now that the Job has completed you can go into your account where you should see a newly minted VM in your 'Default' group.

Where To Go From Here

  • To learn more on how to integrate Ansible Playbooks and CenturyLink Cloud's Runner, which is an automation and orchestration engine that we exposed as a service, check out How to Ansible with Runner on our CenturyLink Cloud blog.

  • Go to the GitHub repo for Runner playbooks to get started writing more elaborate Playbooks and to learn more about Runner and its use cases.