Practical examples of dci-pipeline usage to speed up your OCP cluster testing
Back to all posts

Introduction

We have been talking about dci-pipeline in different blog posts already published here. Starting with a soft introduction about this tool, continuing with some tips to expand your knowledge to a higher level, and now it takes the time to put into practice all what you've learned with all these resources (and of course, don't forget the official documentation!).

This blog post will show you practical examples about the usage of dci-pipeline, including tools such as dci-queue, dci-pipeline-schedule and dci-pipeline-check, so that you can have some useful references for your future interactions with dci-pipeline.

Environment used for the examples

For the commands to be presented in this blog post, let's assume we have the following resources available:

In this example, we're deploying the latest OCP 4.12 release available, exposing an extravars called variable and the kubeconfig as output. Also, we're using dci_config_dirs variable to include a directory from which we will load hooks.

Note that both pipelines requires an OCP installation to be launched, since they have prev_stages: [ocp]. They also inherit the topic used in the OCP installation (in our case, OCP 4.12), and can also retrieve the kubeconfig exposed by the OCP installation pipeline by using the inputs field. Apart from this, each pipeline uses a different component, different extravars, and different inventories.

Just another thing: the pipeline names and the name field are different on purpose, just to clarify the syntax for the examples we'll see next.

Running pipelines

Let's start with the simplest: just run a pipeline (or set of pipelines) that are already defined, using the stable version of the DCI agents and the hooks. For this, we have two options:

Let's see what we can do with this tool.

Running an ocp pipeline

This is the simplest example we can have:

    $ dci-pipeline-schedule ocp-vanilla

With dci-pipeline-schedule, this is as simple as running the command by providing the pipeline file name, but removing -pipeline.yml. That's all. This will schedule a new job in your default queue, and will be launched in any resource available. If all resources are busy, this will be queued and assigned to the first available resource in the queue.

The very same instruction with dci-pipeline command would be the following (among other variables that can be used):

    $ dci-pipeline openshift-vanilla:ansible_inventory=/etc/dci-pipeline/inventory /path/to/ocp-vanilla-pipeline.yml

This is just to highlight the simplicity of using dci-pipeline-schedule instead of dci-pipeline. Then, for the remaining examples, we will make use of dci-pipeline-schedule, as it's simpler and more concise.

Running an ocp pipeline on an already reserved cluster with some custom variables

This becomes more complicated, but not impossible :)

    $ DCI_QUEUE_RESOURCE=cluster2 dci-pipeline-schedule ocp-vanilla openshift-vanilla:ansible_extravars=dci_tags:daily,variable:another_value,dci_teardown_on_success:false

Here, we are adding the following arguments:

Also, if you want to change a different field from the pipeline, you can also do it by following the same structure. For example, to update the inventory, you can do it by using openshift-vanilla:ansible_inventory=/path/to/new/inventory.

Note that the order of the arguments is not relevant. You can specify the custom variables firstly, then the pipeline to use (but always use dci-pipeline-schedule first or after env variables only).

Running multiple pipelines, ocp and cnf

Now, we have the case where we want to execute multiple pipelines sequentially; in our case, the three pipelines we have defined previously. We can do it in the following way:

    $ dci-pipeline-schedule ocp-vanilla cnf1 cnf2

This implies that ocp-vanilla pipeline will be launched firstly, then cnf1, and then cnf2. Since cnf1 and cnf2 depends on an ocp job, if ocp-vanilla fails, cnf1 and cnf2 will not be launched, but if it passes, then both jobs will be launched sequentially; cnf1 firstly, then cnf2, regardless of the result of cnf1 job (since cnf2 depends on ocp jobs, not on cnf jobs).

If you need to run it in a specific cluster, just use DCI_QUEUE_RESOURCE as done in the previous example.

And what about providing custom variables? Same syntax:

    $ dci-pipeline-schedule ocp-vanilla cnf1 cnf2 openshift-vanilla:ansible_extravars=dci_tags:daily first-cnf:ansible_inventory=/path/to/new/inventory

Here, we're providing a new extravars for the ocp-vanilla pipeline, and overriding ansible_inventory variable in cnf1 pipeline. Again, to refer to the pipeline, you have to use the value of the name field from the pipeline; so, for cnf1, we use first-cnf. And again, the order of the arguments is not relevant.

Scheduling a cnf job on top of a running cluster

Imagine you already have an up-and-running OCP cluster (e.g. with OCP 4.13), and you only want to run a CNF job (e.g. cnf1) in that cluster (e.g. cluster2). You can do it!

    $ DCI_QUEUE_RESOURCE=cluster2 dci-pipeline-schedule cnf1

For this case, you just need to provide the cluster you want to use (remember to reserve it). The dci-pipeline-schedule command will retrieve the kubeconfig_path from your pipeline or your inventory file (so don't forget to define it in any of these files), and will infer the OCP topic based on the OCP version running in the cluster.

Scheduling a job in a resource from a different queue

Now, we want to deploy a job in a resource from a different queue, e.g. queue2. How to do it? Just use DCI_QUEUE env var, and dci-pipeline-schedule will schedule the job in a free resource from that queue:

    $ DCI_QUEUE=queue2 dci-pipeline-schedule ocp-vanilla

Selecting specific job stages to be run

In this case, let's suppose you want to launch specific stages from a job (i.e. pre-run, install, tests, teardown...). The DCI agents make use of ansible_tags for that purpose. For example, if you want to just launch the teardown for an OCP installation, you need to instruct ansible_tags in the following way (job and dci tags are used to create the job on DCI):

    $ dci-pipeline-schedule ocp-vanilla openshift-vanilla:ansible_tags=dci,job,success

And of course, you can combine this with the features presented before. If you want to pass some extravars, e.g. to make sure that you're deleting the existing resources:

    $ dci-pipeline-schedule ocp-vanilla openshift-vanilla:ansible_tags=dci,job,success openshift-vanilla:ansible_extravars=dci_teardown_on_success:true openshift-vanilla:ansible_extravars=dci_teardown_on_failure:true

For the opposite case (avoid running a particular stage), you can use then ansible_skip_tags. For example, if you want to run an OCP installation but without running the tests stage, you can do this:

    $ dci-pipeline-schedule ocp-vanilla openshift-vanilla:ansible_skip_tags=testing

Same format is followed for CNF jobs managed by dci-openshift-app-agent, but using the corresponding tags that are defined in that agent.

Testing changes

Now, we have the case where we want to run a pipeline, but to test changes that have been made in any of the repositories that are under usage when launching the DCI job. The change may come from any of the DCI agents used (dci-openshift-agent or dci-openshift-app-agent), which are created in Gerrit, or by any private repository where you define hooks, pipelines, etc., where we typically use Github.

The tool to use for this case is dci-pipeline-check, which more or less follows the same syntax than dci-pipeline-schedule, but with some differences, mainly related to the definition of the change to check.

Note you also have available dci-check-change, but that's a different tool, not related to dci-pipeline, and it's mainly related to the testing of changes on DCI agents. You can check some information about it in these blog posts already published: (1) and (2).

Test a new deployment of OCP with a Gerrit change on a specific cluster

Imagine you have a change on dci-openshift-agent, created on Gerrit (id = 123456789), that you want to test on a specific cluster from your queue (e.g. cluster2). This can be done in the following way:

    $ DCI_QUEUE_RESOURCE=cluster2 dci-pipeline-check 123456789 ocp-vanilla

The only difference with dci-pipeline-schedule is that we're including, after the command, the ID of the change we want to test. The rest is exactly the same: you need to reserve your cluster to avoid issues with new jobs that may come (or if you don't need to select a specific resource, just remove DCI_QUEUE_RESOURCE and the job will be scheduled in any available resource), you can define custom variables, etc. But here, the order matters: the change ID must always come after the dci-pipeline-check command name.

What about Github PRs?

For Github PRs, it's just the same, but you need to pass to dci-pipeline-check the URL of the PR:

    $ DCI_QUEUE_RESOURCE=cluster2 dci-pipeline-check https://github.com/<org>/<repo>/pull/<id> ocp-vanilla

Test a cnf change on top of a running cluster

For this case, the format changes a little bit, compared to dci-pipeline-schedule, because you need to pass the kubeconfig path after the change reference. Also, note that you don't need to specify DCI_QUEUE_RESOURCE in this case, since the kubeconfig will always redirect you to the proper cluster (but don't forget to remove the resource from the queue to avoid issues, as usual). For example, to launch cnf1 under these conditions:

    $ dci-pipeline-check <Gerrit change ID/Github PR URL> /path/to/kubeconfig cnf1

And again, everything we've explained before can be used here: you can define extravars, you can schedule multiple pipelines sequentially, you can use ansible_tags to execute specific stages, etc.

Conclusion

We hope these examples are useful for you when testing and troubleshooting changes on OCP deployments using dci-pipeline. If you need support on any of these cases, don't hesitate to reach us, we'll be glad to help!