Contexts¶
About¶
Contexts are top-level objects that allow dr-provision to support tasks for machines that run somewhere other than on the machines. The docker-context plugin utilizes several common container engines (currently podman and docker) to manage containers by attaching drp tools to an existing, standard container.
Changes¶
Prior to v4.8.0, containers needed to be built with drpcli added to the container and set to
run drpcli machines processjobs
as the endpoint in the Dockerfile. Now, the docker-context plugin bind-mounts drpcli
and sets the endpoint automatically.
Previous versions of context content used Meta.Dockerfile
to build a new container, Meta.Dockerepull
to pull via
podman/docker pull, and Meta.Imagepull
to upload from a URL. Now, Meta.Dockerfile
and Meta.Dockerpull
not used.
The plugin checks Image
with Meta.Checksum
against the image found in the default catalog.
It is now best practice to provide a version with Image
in the form of $(Image)_v1.2.0
where _v1.2.0
is an
arbitrary, incremental version (preferably semver) of the context content or container image (such as
ansible-runner_v1.2.0).
Declaring Meta.Imagepull
with or without the use of Meta.Checksum
is also supported for custom Contexts. If you do
not provide a Meta.Checksum
(sha256sum
is used to verify the checksum), it will overwrite the image every time the
task is run. If Meta.Checksum
is provided, the existing Meta.Image
will be verified. If the checksum is correct, the
plguin will not attempt to fetch the image, otherwise it will fetch and overwrite the image.
Images are saved to files/docker-contexts/$(meta.Image)
.
Setup¶
When running the suggested install of dr-provision, the install will run the universal-bootstrap
workflow on the
endpoint. It includes the bootstrap-drp-endpoint
task to install podman or docker and the bootstrap-contexts
task
to upload the images needed for universal workflows.
If upgrading from 4.7.0 or newer, run the universal-bootstrap
workflow on the endpoint after adding
the boostrap-drp-endpoint
profile to it.
Create Custom Context Content¶
Before creating custom contexts, review the example-content
repo to understand how to create content for drp.
Contexts are placed in the content tree under contexts
, which is found at the same level as workflows
, params
, stages
, etc. It is good practice to name the context file as context-name.yaml
. The most basic content needed to
declare a context is similar to the example below.
---
Name: alpine-runner
Engine: docker-context
Image: alpine-runner_v0.0.1
Meta:
Imagepull: https://localhost:8090/files/alpine-runner_v0.0.1.tar.gz
Checksum: 0d42767249b3bc02c337e4c45f4383c0091f4430e735c7e25990616a757d5c1b
The following example adds bash as a requirement since alpine doesn't come with bash by default. Build the new container, save it locally, upload it to our file server and get the sha256sum. Information from these commands to were used to create the content above.
$ echo -e "FROM alpine:latestnRUN apk add --no-cache bash curl" > Dockerfile
$ cat Dockerfile
FROM alpine:latest
RUN apk add --no-cache bash curl
$ docker build --rm -t drpcli-alpine:latest .
STEP 1/2: FROM alpine:latest
STEP 2/2: RUN apk add --no-cache bash
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/community/x86_64/APKINDEX.tar.gz
(1/4) Installing ncurses-terminfo-base (6.2_p20210612-r0)
(2/4) Installing ncurses-libs (6.2_p20210612-r0)
(3/4) Installing readline (8.1.0-r0)
(4/4) Installing bash (5.1.4-r0)
Executing bash-5.1.4-r0.post-install
Executing busybox-1.33.1-r3.trigger
OK: 8 MiB in 18 packages
COMMIT drpcli-alpine:latest
--> 14a89913f41
Successfully tagged localhost/drpcli-alpine:latest
14a89913f4168a31e86f82536b0a3effb5e96f2f84ea03e0138a7358a33bf90e
$ docker save localhost/drpcli-alpine:latest -o drp-alpine_v0.0.1.tar.gz
Copying blob e2eb06d8af82 done
Copying blob e6aede22edd1 done
Copying config 14a89913f4 done
Writing manifest to image destination
Storing signatures
$ sha256sum drp-alpine_v0.0.1.tar.gz
0d42767249b3bc02c337e4c45f4383c0091f4430e735c7e25990616a757d5c1b drp-alpine_v0.0.1.tar.gz
$ drpcli files upload drp-alpine_v0.0.1.tar.gz as drp-alpine_v0.0.1.tar.gz
{
"Path": "/drp-alpine_v0.0.1.tar.gz",
"Size": 10477568
}
The sums come from sha256sum
on the tarball saved locally. Do not use the signatures from docker pull or docker
inspect.
The image should be hosted somewhere accessible to the endpoint. This example uses https://drp:8092/files
(drp itself)
as the file server. Using drp to host the image is not necessary.
Instead of bundlind and uploading the context content, the context can be created using drpcli directly as shown below.
$ drpcli contexts create '{"Name": "alpine-runner", "Engine": "docker-context", "Image": "drp-alpine_v0.0.1", "Meta": {"Checksum": "0d42767249b3bc02c337e4c45f4383c0091f4430e735c7e25990616a757d5c1b", "Imagepull": "https://localhost:8090/files/drp-apline_v0.0.1.tar.gz"}}'
{
"Available": true,
"Bundle": "",
"Description": "",
"Documentation": "",
"Endpoint": "",
"Engine": "docker-context",
"Errors": [],
"Image": "drp-alpine_v0.0.1",
"Meta": {
"Checksum": "0d42767249b3bc02c337e4c45f4383c0091f4430e735c7e25990616a757d5c1b",
"Imagepull": "https://localhost:8090/files/drp-apline_v0.0.1.tar.gz"
},
"Name": "alpine-runner",
"ReadOnly": false,
"Validated": true
}
The context has been created, but the image hasn't been uploaded to the correct location. It can be uploaded from the UX
by selecting the download icon for the context, run universal-bootstrap on the endpoint, or manually upload the image to
the correct location. For the last option, the following example is provided. Note the as drp-alpine_v0.0.1
without
the .tar.gz
.
$ drpcli files upload https://localhost:8090/files/drp-alpine_v0.0.1.tar.gz as contexts/docker-context/drp-alpine_v0.0.1
{
"Path": "/contexts/docker-context/drp-alpine_v0.0.1",
"Size": 10477568
}
It is important to note that docker-context does not manage the images once it has been added to the container engine
locally (i.e. podman images
. If you are working on the container image, you need to declare the new version label. You
will need to manually remove the image from the container engine.
It is also important to understand what user docker-context is running as when using podman or rootless docker.
Using Custom Contexts¶
In order to use the custom context, create a machine that uses the new context.
$ drpcli contexts list | jq '.[] | select(.Name == "alpine-runner")'
{
"Available": true,
"Bundle": "",
"Description": "",
"Documentation": "",
"Endpoint": "",
"Engine": "docker-context",
"Errors": [],
"Image": "drp-alpine_v0.0.1",
"Meta": {
"Checksum": "0d42767249b3bc02c337e4c45f4383c0091f4430e735c7e25990616a757d5c1b",
"Imagepull": "https://localhost:8092/files/drp-apline_v0.0.1.tar.gz"
},
"Name": "alpine-runner",
"ReadOnly": false,
"Validated": true
}
$ drpcli machines create '{"Name": "alpine-machine", "Meta": {"BaseContext": "alpine-runner"}}'
{
"Address": "",
"Arch": "amd64",
"Available": true,
"BootEnv": "sledgehammer",
"Bundle": "",
"Context": "alpine-runner",
"CurrentJob": "",
"CurrentTask": -1,
"Description": "",
"Endpoint": "",
"Errors": [],
"Fingerprint": {
"CSNHash": "",
"CloudInstanceID": "",
"MemoryIds": [],
"SSNHash": "",
"SystemUUID": ""
},
"HardwareAddrs": [],
"Locked": false,
"Meta": {
"BaseContext": "alpine-runner",
"feature-flags": "change-stage-v2",
"machine-role": "machine"
},
"Name": "alpine-machine",
"OS": "",
"Params": {},
"Partial": false,
"PendingWorkOrders": 0,
"Pool": "default",
"PoolAllocated": false,
"PoolStatus": "Free",
"Profiles": [],
"ReadOnly": false,
"RetryTaskAttempt": 0,
"Runnable": true,
"Secret": "Y1GLuGVCndn-RO4t",
"Stage": "discover",
"TaskErrorStacks": [],
"Tasks": [
"stage:discover",
"bootenv:sledgehammer",
"update-pipeline",
"enforce-sledgehammer",
"set-machine-ip-in-sledgehammer",
"reserve-dhcp-address",
"ssh-access",
"stage:universal-discover-start-callback",
"callback-task",
"stage:universal-discover-pre-flexiflow",
"flexiflow-start",
"flexiflow-stop",
"stage:inventory-minimal",
"inventory-minimal",
"stage:centos-setup-repos",
"centos-drp-only-repos",
"stage:cloud-inventory",
"cloud-inventory",
"stage:raid-inventory",
"raid-tools-install",
"raid-inventory",
"stage:ipmi-inventory",
"ipmi-install",
"ipmi-discover",
"ipmi-inventory",
"stage:bios-inventory",
"bios-tools-install",
"bios-current-config",
"stage:network-lldp",
"network-lldp",
"gohai",
"stage:inventory",
"inventory-check",
"stage:universal-discover-post-flexiflow",
"flexiflow-start",
"flexiflow-stop",
"stage:universal-discover-classification",
"classify-stage-list-start",
"classify-stage-list-stop",
"stage:universal-discover-post-validation",
"validation-start",
"validation-stop",
"stage:universal-discover-complete-callback",
"callback-task",
"stage:universal-chain-workflow",
"universal-chain-workflow",
"stage:complete-nobootenv"
],
"Uuid": "cfb152f3-9c50-4baa-8d74-b7148da8b083",
"Validated": true,
"WorkOrderMode": false,
"Workflow": "universal-discover",
"WorkflowComplete": false
}
The new machine is discovered and workflows can be run against it like any other machine.