ci: add image build jobs (#1051)
Signed-off-by: Mohammed Naser <mnaser@vexxhost.com>
diff --git a/Earthfile b/Earthfile
index acfb0a6..e418ea9 100644
--- a/Earthfile
+++ b/Earthfile
@@ -128,7 +128,6 @@
images:
ARG REGISTRY=ghcr.io/vexxhost/atmosphere
BUILD +libvirt-tls-sidecar.image --REGISTRY=${REGISTRY}
- BUILD ./images/barbican+image --REGISTRY=${REGISTRY}
BUILD ./images/cinder+image --REGISTRY=${REGISTRY}
BUILD ./images/cluster-api-provider-openstack+image --REGISTRY=${REGISTRY}
BUILD ./images/designate+image --REGISTRY=${REGISTRY}
diff --git a/docker-bake.hcl b/docker-bake.hcl
new file mode 100644
index 0000000..5094d56
--- /dev/null
+++ b/docker-bake.hcl
@@ -0,0 +1,197 @@
+variable "REGISTRY" {
+ default = "registry.atmosphere.dev/library"
+}
+
+variable "CACHE_REGISTRY" {
+ default = "registry.atmosphere.dev/cache"
+}
+
+variable "PUSH_TO_CACHE" {
+ default = false
+}
+
+function "cache_from" {
+ params = [image]
+ result = ["type=registry,ref=${CACHE_REGISTRY}/${image}"]
+}
+
+function "cache_to" {
+ params = [image]
+ result = PUSH_TO_CACHE ? [format("%s,%s", cache_from(image)[0], "mode=max,image-manifest=true,oci-mediatypes=true,compression=zstd")] : []
+}
+
+target "ubuntu" {
+ context = "./images/ubuntu"
+
+ cache-from = cache_from("ubuntu")
+ cache-to = cache_to("ubuntu")
+
+ contexts = {
+ ubuntu = "docker-image://ubuntu:jammy-20240227"
+ }
+}
+
+target "git" {
+ context = "./images/git"
+
+ cache-from = cache_from("git")
+ cache-to = cache_to("git")
+}
+
+target "ubuntu-cloud-archive" {
+ name = "ubuntu-cloud-archive-${release.tgt}"
+ context = "./images/ubuntu-cloud-archive"
+
+ cache-from = cache_from("ubuntu-cloud-archive:${release.name}")
+ cache-to = cache_to("ubuntu-cloud-archive:${release.name}")
+
+ matrix = {
+ release = [
+ {
+ tgt = "zed",
+ name = "zed",
+ },
+ {
+ tgt = "bobcat",
+ name = "2023.2",
+ }
+ ]
+ }
+
+ contexts = {
+ ubuntu = "target:ubuntu"
+ }
+
+ args = {
+ RELEASE = release.name
+ }
+}
+
+target "requirements" {
+ name = "requirements-${release.tgt}"
+ context = "./images/requirements"
+
+ cache-from = cache_from("requirements:${release.name}")
+ cache-to = cache_to("requirements:${release.name}")
+
+ matrix = {
+ release = [
+ {
+ tgt = "zed",
+ name = "zed",
+ },
+ {
+ tgt = "bobcat",
+ name = "2023.2",
+ }
+ ]
+ }
+
+ contexts = {
+ ubuntu = "target:ubuntu"
+ }
+
+ args = {
+ RELEASE = release.name
+ }
+}
+
+target "openstack-venv-builder" {
+ name = "openstack-venv-builder-${release.tgt}"
+ context = "./images/openstack-venv-builder"
+
+ cache-from = cache_from("openstack-venv-builder:${release.name}")
+ cache-to = cache_to("openstack-venv-builder:${release.name}")
+
+ matrix = {
+ release = [
+ {
+ tgt = "zed",
+ name = "zed",
+ },
+ {
+ tgt = "bobcat",
+ name = "2023.2",
+ }
+ ]
+ }
+
+ contexts = {
+ ubuntu-cloud-archive = "target:ubuntu-cloud-archive-${release.tgt}",
+ requirements = "target:requirements-${release.tgt}",
+ }
+
+ args = {
+ RELEASE = release.name
+ }
+}
+
+target "openstack-runtime" {
+ name = "openstack-runtime-${release.tgt}"
+ context = "./images/openstack-runtime"
+
+ cache-from = cache_from("openstack-runtime:${release.name}")
+ cache-to = cache_to("openstack-runtime:${release.name}")
+
+ matrix = {
+ release = [
+ {
+ tgt = "zed",
+ name = "zed",
+ },
+ {
+ tgt = "bobcat",
+ name = "2023.2",
+ }
+ ]
+ }
+
+ contexts = {
+ ubuntu-cloud-archive = "target:ubuntu-cloud-archive-${release.tgt}",
+ }
+
+ args = {
+ RELEASE = release.name
+ }
+}
+
+target "barbican" {
+ name = "barbican-${release.tgt}"
+ context = "./images/barbican"
+
+ cache-from = cache_from("barbican:${release.name}")
+ cache-to = cache_to("barbican:${release.name}")
+
+ tags = [
+ "${REGISTRY}/barbican:${release.name}",
+ "${REGISTRY}/barbican:${release.ref}"
+ ]
+
+ matrix = {
+ release = [
+ {
+ tgt = "bobcat",
+ name = "2023.2",
+ ref = "a00fcade4138ffc52cd9c84b5999297966f019b5"
+ }
+ ]
+ }
+
+ contexts = {
+ openstack-venv-builder = "target:openstack-venv-builder-${release.tgt}"
+ openstack-runtime = "target:openstack-runtime-${release.tgt}",
+ git = "target:git"
+ }
+
+ args = {
+ RELEASE = release.name
+ PROJECT = "barbican"
+ BARBICAN_GIT_REF = release.ref
+ }
+}
+
+group "default" {
+ targets = [
+ "barbican"
+ ]
+}
diff --git a/images/barbican/Dockerfile b/images/barbican/Dockerfile
new file mode 100644
index 0000000..046f67e
--- /dev/null
+++ b/images/barbican/Dockerfile
@@ -0,0 +1,19 @@
+FROM git AS barbican
+ARG BARBICAN_GIT_REF
+ADD --keep-git-dir=true https://opendev.org/openstack/barbican.git#${BARBICAN_GIT_REF} /src
+RUN git fetch --unshallow
+
+FROM openstack-venv-builder AS build
+COPY --from=barbican --link /src /src/barbican
+ARG TARGETARCH
+ARG TARGETVARIANT
+RUN \
+ --mount=type=cache,id=pip-$TARGETARCH$TARGETVARIANT-$RELEASE-cache,sharing=locked,target=/root/.cache/pip <<EOF bash -xe
+pip3 install \
+ --constraint /upper-constraints.txt \
+ /src/barbican \
+ pykmip
+EOF
+
+FROM openstack-runtime
+COPY --from=build --link /var/lib/openstack /var/lib/openstack
diff --git a/images/barbican/Earthfile b/images/barbican/Earthfile
deleted file mode 100644
index 55f4d5d..0000000
--- a/images/barbican/Earthfile
+++ /dev/null
@@ -1,20 +0,0 @@
-VERSION 0.7
-
-ARG --global PROJECT=barbican
-ARG --global RELEASE=2023.2
-ARG --global PROJECT_REF=a00fcade4138ffc52cd9c84b5999297966f019b5
-
-build:
- FROM ../openstack-service+builder --RELEASE=${RELEASE}
- DO ../openstack-service+BUILD_VENV \
- --PROJECT=${PROJECT} \
- --PROJECT_REF=${PROJECT_REF} \
- --PIP_PACKAGES="pykmip"
-
-image:
- FROM ../openstack-service+image --RELEASE ${RELEASE} --PROJECT ${PROJECT}
- COPY +build/venv /var/lib/openstack
- ARG REGISTRY=ghcr.io/vexxhost/atmosphere
- SAVE IMAGE --push \
- ${REGISTRY}/${PROJECT}:${RELEASE} \
- ${REGISTRY}/${PROJECT}:${PROJECT_REF}
diff --git a/images/build.sh b/images/build.sh
new file mode 100755
index 0000000..d93f853
--- /dev/null
+++ b/images/build.sh
@@ -0,0 +1,43 @@
+#!/bin/bash -xe
+
+TARGET=""
+PUSH=false
+
+while [[ $# -gt 0 ]]; do
+ key="$1"
+
+ case $key in
+ --push)
+ PUSH=true
+ shift
+ ;;
+ *)
+ if [ -z "$TARGET" ]; then
+ TARGET="$1"
+ else
+ echo "Invalid argument: $1"
+ exit 1
+ fi
+ shift
+ ;;
+ esac
+done
+
+if [ -z "$TARGET" ]; then
+ echo "Usage: $0 [--push] <target>"
+ exit 1
+fi
+
+docker buildx create --name=atmosphere --driver=docker-container || true
+
+if [ "$PUSH" = true ]; then
+ docker buildx bake --builder=atmosphere --provenance --sbom=true --push $TARGET
+
+ # Sign all images
+ export COSIGN_PASSWORD=""
+ for IMAGE in $(docker buildx bake --print ${TARGET} | jq -r '.target[].tags | select(. != null)[]'); do
+ cosign sign -y --recursive --key cosign.key ${IMAGE}
+ done
+else
+ docker buildx bake --builder=atmosphere --provenance --sbom=true $TARGET
+fi
diff --git a/images/git/Dockerfile b/images/git/Dockerfile
new file mode 100644
index 0000000..af8b7e4
--- /dev/null
+++ b/images/git/Dockerfile
@@ -0,0 +1,2 @@
+FROM alpine/git:latest
+WORKDIR /src
diff --git a/images/openstack-runtime/Dockerfile b/images/openstack-runtime/Dockerfile
new file mode 100644
index 0000000..2df606c
--- /dev/null
+++ b/images/openstack-runtime/Dockerfile
@@ -0,0 +1,24 @@
+FROM ubuntu-cloud-archive
+ARG TARGETARCH
+ARG TARGETVARIANT
+ARG RELEASE
+RUN \
+ --mount=type=cache,id=apt-$TARGETARCH$TARGETVARIANT-$RELEASE-var-cache-apt,sharing=locked,target=/var/cache/apt \
+ --mount=type=cache,id=apt-$TARGETARCH$TARGETVARIANT-$RELEASE-var-lib-apt-lists,sharing=locked,target=/var/lib/apt/lists <<EOF bash -xe
+apt-get update -qq
+apt-get install -qq -y --no-install-recommends \
+ ca-certificates \
+ libpython3.10 \
+ lsb-release \
+ python3-distutils \
+ sudo
+EOF
+
+ONBUILD ARG PROJECT
+ONBUILD ARG SHELL=/usr/sbin/nologin
+ONBUILD RUN \
+ groupadd -g 42424 ${PROJECT} && \
+ useradd -u 42424 -g 42424 -M -d /var/lib/${PROJECT} -s ${SHELL} -c "${PROJECT} User" ${PROJECT} && \
+ mkdir -p /etc/${PROJECT} /var/log/${PROJECT} /var/lib/${PROJECT} /var/cache/${PROJECT} && \
+ chown -Rv ${PROJECT}:${PROJECT} /etc/${PROJECT} /var/log/${PROJECT} /var/lib/${PROJECT} /var/cache/${PROJECT}
+ONBUILD ENV PATH=/var/lib/openstack/bin:$PATH
diff --git a/images/openstack-venv-builder/Dockerfile b/images/openstack-venv-builder/Dockerfile
new file mode 100644
index 0000000..4ceb97f
--- /dev/null
+++ b/images/openstack-venv-builder/Dockerfile
@@ -0,0 +1,38 @@
+FROM ubuntu-cloud-archive
+ARG TARGETARCH
+ARG TARGETVARIANT
+ARG RELEASE
+RUN \
+ --mount=type=cache,id=apt-$TARGETARCH$TARGETVARIANT-$RELEASE-var-cache-apt,sharing=locked,target=/var/cache/apt \
+ --mount=type=cache,id=apt-$TARGETARCH$TARGETVARIANT-$RELEASE-var-lib-apt-lists,sharing=locked,target=/var/lib/apt/lists <<EOF bash -xe
+apt-get update -qq
+apt-get install -qq -y --no-install-recommends \
+ build-essential \
+ git \
+ libldap2-dev \
+ libpcre3-dev \
+ libsasl2-dev \
+ libssl-dev \
+ lsb-release \
+ openssh-client \
+ python3 \
+ python3-dev \
+ python3-pip \
+ python3-venv
+EOF
+RUN \
+ --mount=type=cache,id=pip-$TARGETARCH$TARGETVARIANT-$RELEASE-cache,sharing=locked,target=/root/.cache/pip <<EOF bash -xe
+python3 -m venv --upgrade-deps --system-site-packages /var/lib/openstack
+EOF
+ENV PATH=/var/lib/openstack/bin:$PATH
+COPY --link --from=requirements /src/upper-constraints.txt /upper-constraints.txt
+RUN \
+ --mount=type=cache,id=pip-$TARGETARCH$TARGETVARIANT-$RELEASE-cache,sharing=locked,target=/root/.cache/pip <<EOF bash -xe
+pip3 install \
+ --constraint /upper-constraints.txt \
+ cryptography \
+ pymysql \
+ python-binary-memcached \
+ python-memcached \
+ uwsgi
+EOF
diff --git a/images/requirements/Dockerfile b/images/requirements/Dockerfile
new file mode 100644
index 0000000..fe201f0
--- /dev/null
+++ b/images/requirements/Dockerfile
@@ -0,0 +1,45 @@
+FROM ubuntu
+ARG TARGETARCH
+ARG TARGETVARIANT
+RUN \
+ --mount=type=cache,id=apt-$TARGETARCH$TARGETVARIANT-var-cache-apt,sharing=locked,target=/var/cache/apt \
+ --mount=type=cache,id=apt-$TARGETARCH$TARGETVARIANT-var-lib-apt-lists,sharing=locked,target=/var/lib/apt/lists <<EOF bash -xe
+apt-get update -qq
+apt-get install -qq -y --no-install-recommends ca-certificates git
+EOF
+
+ARG RELEASE
+RUN <<EOF bash -xe
+BRANCH=stable/${RELEASE}
+if [ "${RELEASE}" = "master" ]; then
+ BRANCH=master
+fi
+
+git clone --branch \$BRANCH https://github.com/openstack/requirements /src
+EOF
+
+RUN <<EOF sh -xe
+sed -i 's/cryptography===36.0.2/cryptography===42.0.4/' /src/upper-constraints.txt
+sed -i 's/cryptography===40.0.2/cryptography===42.0.4/' /src/upper-constraints.txt
+sed -i 's/cryptography===41.0.7/cryptography===42.0.4/' /src/upper-constraints.txt
+sed -i 's/Django===3.2.18/Django===3.2.24/' /src/upper-constraints.txt
+sed -i 's/Flask===2.2.3/Flask===2.2.5/' /src/upper-constraints.txt
+sed -i 's/Jinja2===3.1.2/Jinja2===3.1.3/' /src/upper-constraints.txt
+sed -i 's/oauthlib===3.2.0/oauthlib===3.2.2/' /src/upper-constraints.txt
+sed -i 's/paramiko===2.11.0/paramiko===3.4.0/' /src/upper-constraints.txt
+sed -i 's/paramiko===3.1.0/paramiko===3.4.0/' /src/upper-constraints.txt
+sed -i 's/protobuf===4.21.5/protobuf===4.21.6/' /src/upper-constraints.txt
+sed -i 's/pyOpenSSL===22.0.0/pyOpenSSL===24.0.0/' /src/upper-constraints.txt
+sed -i 's/pyOpenSSL===23.1.1/pyOpenSSL===24.0.0/' /src/upper-constraints.txt
+sed -i 's/requests===2.28.1/requests===2.31.0/' /src/upper-constraints.txt
+sed -i 's/requests===2.28.2/requests===2.31.0/' /src/upper-constraints.txt
+sed -i 's/sqlparse===0.4.2/sqlparse===0.4.4/' /src/upper-constraints.txt
+sed -i 's/urllib3===1.26.12/urllib3===1.26.18/' /src/upper-constraints.txt
+sed -i 's/urllib3===1.26.15/urllib3===1.26.18/' /src/upper-constraints.txt
+sed -i 's/Werkzeug===2.2.2/Werkzeug===2.3.8/' /src/upper-constraints.txt
+sed -i 's/Werkzeug===2.2.3/Werkzeug===2.3.8/' /src/upper-constraints.txt
+sed -i 's/zstd===1.5.2.5/zstd===1.5.4.0/' /src/upper-constraints.txt
+
+sed -i '/glance-store/d' /src/upper-constraints.txt
+sed -i '/horizon/d' /src/upper-constraints.txt
+EOF
diff --git a/images/ubuntu-cloud-archive/Dockerfile b/images/ubuntu-cloud-archive/Dockerfile
new file mode 100644
index 0000000..31ab98e
--- /dev/null
+++ b/images/ubuntu-cloud-archive/Dockerfile
@@ -0,0 +1,28 @@
+FROM ubuntu
+COPY trusted.gpg.d/* /etc/apt/trusted.gpg.d/
+
+ARG RELEASE
+RUN <<EOF bash -xe
+source /etc/os-release
+
+if [ "\${VERSION_CODENAME}" = "jammy" ]; then \
+ if [ "${RELEASE}" = "yoga" ]; then \
+ # NOTE: Yoga shipped with 22.04, so no need to add an extra repository.
+ echo "" > /etc/apt/sources.list.d/cloudarchive.list; \
+ elif [ "${RELEASE}" = "zed" ]; then \
+ echo "deb http://ubuntu-cloud.archive.canonical.com/ubuntu \${VERSION_CODENAME}-updates/${RELEASE} main" > /etc/apt/sources.list.d/cloudarchive.list; \
+ elif [ "${RELEASE}" = "2023.1" ]; then \
+ echo "deb http://ubuntu-cloud.archive.canonical.com/ubuntu \${VERSION_CODENAME}-updates/antelope main" > /etc/apt/sources.list.d/cloudarchive.list; \
+ elif [ "${RELEASE}" = "2023.2" ]; then \
+ echo "deb http://ubuntu-cloud.archive.canonical.com/ubuntu \${VERSION_CODENAME}-updates/bobcat main" > /etc/apt/sources.list.d/cloudarchive.list; \
+ elif [ "${RELEASE}" = "master" ]; then \
+ echo "deb http://ubuntu-cloud.archive.canonical.com/ubuntu \${VERSION_CODENAME}-updates/caracal main" > /etc/apt/sources.list.d/cloudarchive.list; \
+ else \
+ echo "${RELEASE} is not supported on \${VERSION_CODENAME}"; \
+ exit 1; \
+ fi; \
+else
+ echo "Unsupported release"; \
+ exit 1; \
+fi
+EOF
diff --git a/images/ubuntu-cloud-archive/trusted.gpg.d/cloud-archive.gpg b/images/ubuntu-cloud-archive/trusted.gpg.d/cloud-archive.gpg
new file mode 100644
index 0000000..f902962
--- /dev/null
+++ b/images/ubuntu-cloud-archive/trusted.gpg.d/cloud-archive.gpg
Binary files differ
diff --git a/images/ubuntu/Dockerfile b/images/ubuntu/Dockerfile
new file mode 100644
index 0000000..46a9164
--- /dev/null
+++ b/images/ubuntu/Dockerfile
@@ -0,0 +1,16 @@
+FROM ubuntu
+LABEL org.opencontainers.image.source=https://github.com/vexxhost/atmosphere
+RUN <<EOF
+rm -f /etc/apt/apt.conf.d/docker-clean
+echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
+EOF
+
+# ARG TARGETARCH
+# ARG TARGETVARIANT
+# RUN \
+# --mount=type=cache,id=apt-$TARGETARCH$TARGETVARIANT-var-cache-apt,sharing=locked,target=/var/cache/apt \
+# --mount=type=cache,id=apt-$TARGETARCH$TARGETVARIANT-var-lib-apt-lists,sharing=locked,target=/var/lib/apt/lists <<EOF bash -xe
+# apt-get update -qq
+# apt-get install -qq -y --no-install-recommends \
+# # CVE-XXXX
+# EOF
diff --git a/zuul.d/jobs.yaml b/zuul.d/jobs.yaml
index 30f6b93..8130aa7 100644
--- a/zuul.d/jobs.yaml
+++ b/zuul.d/jobs.yaml
@@ -13,6 +13,17 @@
# under the License.
- job:
+ name: atmosphere-build-images
+ pre-run: zuul.d/playbooks/build-images/pre.yml
+ run: zuul.d/playbooks/build-images/run.yml
+
+- job:
+ name: atmosphere-upload-images
+ parent: atmosphere-build-images
+ secrets:
+ - registry_credentials
+
+- job:
name: atmosphere-molecule
parent: tox
abstract: true
diff --git a/zuul.d/playbooks/build-images/pre.yml b/zuul.d/playbooks/build-images/pre.yml
new file mode 100644
index 0000000..ab0c6e1
--- /dev/null
+++ b/zuul.d/playbooks/build-images/pre.yml
@@ -0,0 +1,18 @@
+# Copyright (c) 2024 VEXXHOST, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+- name: Prepare host for Keycloak tests
+ hosts: all
+ roles:
+ - ensure-docker
diff --git a/zuul.d/playbooks/build-images/run.yml b/zuul.d/playbooks/build-images/run.yml
new file mode 100644
index 0000000..c82be02
--- /dev/null
+++ b/zuul.d/playbooks/build-images/run.yml
@@ -0,0 +1,33 @@
+# Copyright (c) 2024 VEXXHOST, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+- name: Build images
+ hosts: all
+ tasks:
+ - name: Create builder
+ ansible.builtin.shell: docker buildx create --name=atmosphere --driver=docker-container
+
+ - name: Login to registry
+ when: zuul.pipeline == 'post'
+ no_log: true
+ ansible.builtin.shell: |
+ docker login -u '{{ registry_credentials.username }}' -p '{{ registry_credentials.password }}' registry.atmosphere.dev
+
+ - name: Build images
+ ansible.builtin.shell: |
+ docker buildx bake --builder=atmosphere --provenance --sbom=true {% if zuul.pipeline == 'post' %}--push{% endif %}
+ args:
+ chdir: "{{ zuul.project.src_dir }}"
+ environment:
+ PUSH_TO_CACHE: "{{ zuul.pipeline == 'post' }}"
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index a94f6dc..6f3f0a9 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -15,8 +15,12 @@
- project:
check:
jobs:
+ - atmosphere-build-images
- atmosphere-molecule-aio-openvswitch
- atmosphere-molecule-aio-ovn
- atmosphere-molecule-csi-local-path-provisioner
- atmosphere-molecule-csi-rbd
- atmosphere-molecule-keycloak
+ post:
+ jobs:
+ - atmosphere-upload-images
diff --git a/zuul.d/secrets.yaml b/zuul.d/secrets.yaml
new file mode 100644
index 0000000..232d7d5
--- /dev/null
+++ b/zuul.d/secrets.yaml
@@ -0,0 +1,29 @@
+# Copyright (c) 2024 VEXXHOST, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+- secret:
+ name: registry_credentials
+ data:
+ username: robot$zuul
+ password: !encrypted/pkcs1-oaep
+ - OOykjodZE21qsYYLpzplp+PV0QbsKQ1B3+kI7bY97VQI/d5RlewqlNABc10eQnyYFSDvq
+ z2gSigSHxaVcV5qKJLTNVDgzSBHBj349OaTh6dXsxplvoArehfYMMZGuNmFlucoeN8K6w
+ yLRViN7tCS39CAYdjeNX1X7mQ7gBC61jUQ++JB+R5MhXmALJxzPfQRl9jsYmjx9ZXjEwE
+ tjKLSyQifQU20eXbhZOUW2nr+ItTikS3AOSo6Ja6jCI1c9lj6mJtUOorGsuxfdhEigPws
+ Qnz539imGcyqySSxvbJvgoEYxhE3dHFV5cJkomoHHHwLH0wbjAgBQtCMX3CvpxNX8sBfJ
+ MxvUkxY8VWt3CtJkdq+/eaCovCRn6GN5enI5tlUJgpAyV+PO6PvkTan6yC8lHMM5pD4jX
+ Hdo6gt6m9WyA5VxUHdoYYMaDO/rvCxxrUevzPn8do5I96madr9S9lFARqw74mgXG5I6pZ
+ M7zDXnorUFyv9dUIB2rOZrp7o0OC2thujjDTKXb4qfmfXGOwlkNmtCLo6BaDo9pSdRN8p
+ k0YnUAItZ64qUR7paEUKGy4rzsZjDYvIj7DrCFvLL2CXcyjPGcmcblpSHe5vJ15CFVH8X
+ o39FIIhSmehvrYJziGYUgf4JY1B6ktBtFc9l78WeoJRHNce+viSSkBj1fhbUaI=