[stable/2023.1] [ATMOSPHERE-595] update libvirt-tls-sidecar image tag to latest (#2171)
fix #2167
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index a62b4d5..0000000
--- a/Dockerfile
+++ /dev/null
@@ -1,18 +0,0 @@
-# SPDX-License-Identifier: Apache-2.0
-# Atmosphere-Rebuild-Time: 2024-06-25T22:49:25Z
-
-ARG RELEASE
-
-FROM golang:1.22 AS go-builder
-COPY go.mod go.sum /src/
-WORKDIR /src
-RUN go mod download
-
-FROM go-builder AS libvirt-tls-sidecar-builder
-COPY cmd/ /src/cmd/
-COPY internal/ /src/internal/
-RUN go build -o main ./cmd/libvirt-tls-sidecar/main.go
-
-FROM registry.atmosphere.dev/library/ubuntu:${RELEASE} AS libvirt-tls-sidecar
-COPY --from=libvirt-tls-sidecar-builder /src/main /usr/bin/libvirt-tls-sidecar
-ENTRYPOINT ["/usr/bin/libvirt-tls-sidecar"]
diff --git a/cmd/libvirt-tls-sidecar/main.go b/cmd/libvirt-tls-sidecar/main.go
deleted file mode 100644
index c94f5c8..0000000
--- a/cmd/libvirt-tls-sidecar/main.go
+++ /dev/null
@@ -1,97 +0,0 @@
-// 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.
-
-package main
-
-import (
- "context"
- "fmt"
- "os"
-
- cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
- log "github.com/sirupsen/logrus"
- "k8s.io/client-go/rest"
-
- "github.com/vexxhost/atmosphere/internal/tls"
-)
-
-const (
- EnvVarApiIssuerKind = "API_ISSUER_KIND"
- EnvVarApiIssuerName = "API_ISSUER_NAME"
- EnvVarVncIssuerKind = "VNC_ISSUER_KIND"
- EnvVarVncIssuerName = "VNC_ISSUER_NAME"
-)
-
-func main() {
- config, err := rest.InClusterConfig()
- if err != nil {
- log.Fatal(err)
- }
-
- required := []string{
- EnvVarApiIssuerKind,
- EnvVarApiIssuerName,
- EnvVarVncIssuerKind,
- EnvVarVncIssuerName,
- }
-
- for _, env := range required {
- if os.Getenv(env) == "" {
- log.Fatal(fmt.Sprintf("missing required environment variable: %s", env))
- }
- }
-
- ctx := context.Background()
- go createCertificateSpec(ctx, config, tls.LibvirtCertificateTypeAPI)
- go createCertificateSpec(ctx, config, tls.LibvirtCertificateTypeVNC)
-
- <-ctx.Done()
-}
-
-func createCertificateSpec(ctx context.Context, config *rest.Config, certificateType tls.LibvirtCertificateType) {
- var issuerRef cmmeta.ObjectReference
- switch certificateType {
- case tls.LibvirtCertificateTypeAPI:
- issuerRef = cmmeta.ObjectReference{
- Kind: os.Getenv(EnvVarApiIssuerKind),
- Name: os.Getenv(EnvVarApiIssuerName),
- }
- case tls.LibvirtCertificateTypeVNC:
- issuerRef = cmmeta.ObjectReference{
- Kind: os.Getenv(EnvVarVncIssuerKind),
- Name: os.Getenv(EnvVarVncIssuerName),
- }
- }
-
- spec := &tls.LibvirtCertificateSpec{
- Type: certificateType,
- IssuerRef: issuerRef,
- }
-
- manager, err := tls.NewLibvirtManager(config, spec)
- if err != nil {
- log.Fatal(err)
- }
-
- err = manager.Create(ctx)
- if err != nil {
- log.Fatal(err)
- }
-
- log.WithFields(log.Fields{
- "certificateType": certificateType,
- }).Info("certificate created")
-
- go manager.Watch(ctx)
-}
diff --git a/go.mod b/go.mod
index 62527e1..9917561 100644
--- a/go.mod
+++ b/go.mod
@@ -5,8 +5,7 @@
toolchain go1.22.3
require (
- github.com/cert-manager/cert-manager v1.14.5
- github.com/containers/image/v5 v5.30.0
+ github.com/containers/image/v5 v5.30.1
github.com/erikgeiser/promptkit v0.9.0
github.com/goccy/go-yaml v1.11.3
github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1
@@ -47,6 +46,7 @@
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
+ github.com/cert-manager/cert-manager v1.14.5 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/chai2010/gettext-go v1.0.2 // indirect
github.com/charmbracelet/bubbles v0.16.1 // indirect
@@ -193,7 +193,6 @@
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect
oras.land/oras-go v1.2.5 // indirect
sigs.k8s.io/controller-runtime v0.17.0 // indirect
- sigs.k8s.io/gateway-api v1.0.0 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/kustomize/api v0.17.2 // indirect
sigs.k8s.io/kustomize/kyaml v0.17.1 // indirect
diff --git a/go.sum b/go.sum
index c6e4df1..caac830 100644
--- a/go.sum
+++ b/go.sum
@@ -82,8 +82,8 @@
github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
-github.com/containers/image/v5 v5.30.0 h1:CmHeSwI6W2kTRWnUsxATDFY5TEX4b58gPkaQcEyrLIA=
-github.com/containers/image/v5 v5.30.0/go.mod h1:gSD8MVOyqBspc0ynLsuiMR9qmt8UQ4jpVImjmK0uXfk=
+github.com/containers/image/v5 v5.30.1 h1:AKrQMgOKI1oKx5FW5eoU2xoNyzACajHGx1O3qxobvFM=
+github.com/containers/image/v5 v5.30.1/go.mod h1:gSD8MVOyqBspc0ynLsuiMR9qmt8UQ4jpVImjmK0uXfk=
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA=
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
github.com/containers/ocicrypt v1.1.9 h1:2Csfba4jse85Raxk5HIyEk8OwZNjRvfkhEGijOjIdEM=
@@ -638,8 +638,6 @@
oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo=
sigs.k8s.io/controller-runtime v0.17.0 h1:fjJQf8Ukya+VjogLO6/bNX9HE6Y2xpsO5+fyS26ur/s=
sigs.k8s.io/controller-runtime v0.17.0/go.mod h1:+MngTvIQQQhfXtwfdGw/UOQ/aIaqsYywfCINOtwMO/s=
-sigs.k8s.io/gateway-api v1.0.0 h1:iPTStSv41+d9p0xFydll6d7f7MOBGuqXM6p2/zVYMAs=
-sigs.k8s.io/gateway-api v1.0.0/go.mod h1:4cUgr0Lnp5FZ0Cdq8FdRwCvpiWws7LVhLHGIudLlf4c=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/kustomize/api v0.17.2 h1:E7/Fjk7V5fboiuijoZHgs4aHuexi5Y2loXlVOAVAG5g=
diff --git a/internal/net/hostname.go b/internal/net/hostname.go
deleted file mode 100644
index a2a7c96..0000000
--- a/internal/net/hostname.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package net
-
-import (
- "os"
- "os/exec"
- "strings"
-)
-
-func Hostname() (string, error) {
- return os.Hostname()
-}
-
-func FQDN() (string, error) {
- cmd := exec.Command("/bin/hostname", "--fqdn")
- out, err := cmd.Output()
- if err != nil {
- return "", err
- }
-
- return strings.TrimSpace(string(out)), nil
-}
diff --git a/internal/tls/libvirt.go b/internal/tls/libvirt.go
deleted file mode 100644
index 227dd6f..0000000
--- a/internal/tls/libvirt.go
+++ /dev/null
@@ -1,317 +0,0 @@
-package tls
-
-import (
- "bytes"
- "context"
- "encoding/json"
- "fmt"
- "os"
- "time"
-
- cmv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
- cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
- cmclient "github.com/cert-manager/cert-manager/pkg/client/clientset/versioned/typed/certmanager/v1"
- log "github.com/sirupsen/logrus"
- "github.com/vexxhost/atmosphere/internal/net"
- v1 "k8s.io/api/core/v1"
- "k8s.io/apimachinery/pkg/api/errors"
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "k8s.io/apimachinery/pkg/fields"
- "k8s.io/apimachinery/pkg/runtime"
- "k8s.io/apimachinery/pkg/types"
- "k8s.io/apimachinery/pkg/util/wait"
- "k8s.io/apimachinery/pkg/watch"
- kubernetes "k8s.io/client-go/kubernetes/typed/core/v1"
- "k8s.io/client-go/rest"
- "k8s.io/client-go/tools/cache"
-)
-
-type LibvirtCertificateType string
-
-const (
- LibvirtCertificateTypeAPI LibvirtCertificateType = "api"
- LibvirtCertificateTypeVNC LibvirtCertificateType = "vnc"
-)
-
-const (
- EnvVarPodUID = "POD_UID"
- EnvVarPodName = "POD_NAME"
- EnvVarPodNamespace = "POD_NAMESPACE"
- EnvVarPodIP = "POD_IP"
-)
-
-type LibvirtCertificateSpec struct {
- Type LibvirtCertificateType
- IssuerRef cmmeta.ObjectReference
-}
-
-type LibvirtManager struct {
- logger *log.Entry
- spec *LibvirtCertificateSpec
- certificate *cmv1.Certificate
- certificateName string
- certificateClient cmclient.CertificateInterface
- secretClient kubernetes.SecretInterface
-}
-
-func NewLibvirtManager(config *rest.Config, spec *LibvirtCertificateSpec) (*LibvirtManager, error) {
- required := []string{
- EnvVarPodName,
- EnvVarPodNamespace,
- EnvVarPodUID,
- EnvVarPodIP,
- }
-
- for _, env := range required {
- if os.Getenv(env) == "" {
- return nil, fmt.Errorf("missing required environment variable: %s", env)
- }
- }
-
- mgr := &LibvirtManager{}
-
- hostname, err := net.Hostname()
- if err != nil {
- return nil, err
- }
-
- fqdn, err := net.FQDN()
- if err != nil {
- return nil, err
- }
-
- clientset, err := kubernetes.NewForConfig(config)
- if err != nil {
- return nil, err
- }
-
- cmClient, err := cmclient.NewForConfig(config)
- if err != nil {
- return nil, err
- }
-
- podUID := types.UID(os.Getenv(EnvVarPodUID))
- podNamespace := os.Getenv(EnvVarPodNamespace)
- podName := os.Getenv(EnvVarPodName)
- podIP := os.Getenv(EnvVarPodIP)
-
- mgr.spec = spec
- mgr.secretClient = clientset.Secrets(podNamespace)
- mgr.certificateClient = cmClient.Certificates(podNamespace)
- mgr.certificateName = fmt.Sprintf("%s-%s", podName, spec.Type)
-
- mgr.logger = log.WithFields(log.Fields{
- "certificateName": mgr.certificateName,
- "podName": podName,
- "podNamespace": podNamespace,
- "podUID": podUID,
- "podIP": podIP,
- "hostname": hostname,
- "fqdn": fqdn,
- "issuerKind": spec.IssuerRef.Kind,
- "issuerName": spec.IssuerRef.Name,
- })
-
- mgr.certificate = &cmv1.Certificate{
- ObjectMeta: metav1.ObjectMeta{
- Name: mgr.certificateName,
- Namespace: podNamespace,
- OwnerReferences: []metav1.OwnerReference{
- {
- APIVersion: "v1",
- Kind: "Pod",
- Name: podName,
- UID: podUID,
- },
- },
- },
- Spec: cmv1.CertificateSpec{
- SecretName: mgr.certificateName,
- CommonName: podIP,
- Usages: []cmv1.KeyUsage{
- cmv1.UsageClientAuth,
- cmv1.UsageServerAuth,
- },
- DNSNames: []string{hostname, fqdn},
- IPAddresses: []string{podIP},
- IssuerRef: spec.IssuerRef,
- },
- }
-
- return mgr, nil
-}
-
-func (m *LibvirtManager) Create(ctx context.Context) error {
- // Create certificate
- _, err := m.certificateClient.Create(ctx, m.certificate, metav1.CreateOptions{})
- if err != nil && !errors.IsAlreadyExists(err) {
- return err
- }
-
- m.logger.Info("certificate created")
-
- // Wait for certificate to become ready
- err = wait.PollUntilContextTimeout(ctx, 5*time.Second, 300*time.Second, true, func(ctx context.Context) (bool, error) {
- certificate, err := m.certificateClient.Get(ctx, m.certificateName, metav1.GetOptions{})
- if err != nil {
- return false, err
- }
-
- for _, condition := range certificate.Status.Conditions {
- if condition.Type == cmv1.CertificateConditionReady {
- if condition.Status == cmmeta.ConditionTrue {
- return true, nil
- }
-
- m.logger.WithFields(log.Fields{
- "reason": condition.Reason,
- "message": condition.Message,
- }).Info("certificate not ready")
- }
- }
-
- return false, nil
- })
- if err != nil {
- return err
- }
-
- m.logger.Info("certificate ready")
-
- // Create patch with ownerReference so the secret is garbage collected
- patch := []map[string]interface{}{
- {
- "op": "add",
- "path": "/metadata/ownerReferences",
- "value": m.certificate.OwnerReferences,
- },
- }
- patchBytes, err := json.Marshal(patch)
- if err != nil {
- return err
- }
-
- m.logger.Info("patching secret")
-
- // Patch secret with ownerReference
- _, err = m.secretClient.Patch(ctx, m.certificateName, types.JSONPatchType, patchBytes, metav1.PatchOptions{})
- return err
-}
-
-func (m *LibvirtManager) Watch(ctx context.Context) {
- for {
- m.watch(ctx)
- m.logger.Info("watch closed or disconnected, retrying in 5 seconds")
-
- time.Sleep(5 * time.Second)
- }
-}
-
-func (m *LibvirtManager) watch(ctx context.Context) {
- fieldSelector := fields.OneTermEqualSelector("metadata.name", m.certificateName).String()
-
- listWatcher := &cache.ListWatch{
- ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
- options.FieldSelector = fieldSelector
- return m.secretClient.List(ctx, options)
- },
- WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
- options.FieldSelector = fieldSelector
- return m.secretClient.Watch(ctx, options)
- },
- }
-
- _, controller := cache.NewInformer(
- listWatcher,
- &v1.Secret{},
- time.Minute,
- cache.ResourceEventHandlerFuncs{
- AddFunc: func(obj interface{}) {
- secret := obj.(*v1.Secret)
- m.write(secret)
- },
- UpdateFunc: func(oldObj, newObj interface{}) {
- secret := newObj.(*v1.Secret)
- m.write(secret)
- },
- DeleteFunc: func(obj interface{}) {
- m.logger.Fatal("secret deleted")
- },
- },
- )
-
- stop := make(chan struct{})
- defer close(stop)
- controller.Run(stop)
-}
-
-func (m *LibvirtManager) write(secret *v1.Secret) {
- switch m.spec.Type {
- case LibvirtCertificateTypeAPI:
- m.createDirectory("/etc/pki/libvirt/private")
- m.writeFile("/etc/pki/CA/cacert.pem", secret.Data["ca.crt"])
- m.writeFile("/etc/pki/libvirt/servercert.pem", secret.Data["tls.crt"])
- m.writeFile("/etc/pki/libvirt/private/serverkey.pem", secret.Data["tls.key"])
- m.writeFile("/etc/pki/libvirt/clientcert.pem", secret.Data["tls.crt"])
- m.writeFile("/etc/pki/libvirt/private/clientkey.pem", secret.Data["tls.key"])
- m.createDirectory("/etc/pki/qemu")
- m.writeFile("/etc/pki/qemu/ca-cert.pem", secret.Data["ca.crt"])
- m.writeFile("/etc/pki/qemu/server-cert.pem", secret.Data["tls.crt"])
- m.writeFile("/etc/pki/qemu/server-key.pem", secret.Data["tls.key"])
- m.writeFile("/etc/pki/qemu/client-cert.pem", secret.Data["tls.crt"])
- m.writeFile("/etc/pki/qemu/client-key.pem", secret.Data["tls.key"])
- case LibvirtCertificateTypeVNC:
- m.createDirectory("/etc/pki/libvirt-vnc")
- m.writeFile("/etc/pki/libvirt-vnc/ca-cert.pem", secret.Data["ca.crt"])
- m.writeFile("/etc/pki/libvirt-vnc/server-cert.pem", secret.Data["tls.crt"])
- m.writeFile("/etc/pki/libvirt-vnc/server-key.pem", secret.Data["tls.key"])
- }
-}
-
-func (m *LibvirtManager) createDirectory(path string) {
- if _, err := os.Stat(path); !os.IsNotExist(err) {
- return
- }
-
- m.logger.WithFields(log.Fields{
- "path": path,
- }).Info("creating directory")
-
- err := os.MkdirAll(path, 0755)
- if err != nil {
- m.logger.Fatal(err)
- }
-}
-
-func (m *LibvirtManager) writeFile(path string, data []byte) {
- log := m.logger.WithFields(log.Fields{
- "path": path,
- })
-
- existingData, err := os.ReadFile(path)
- if err != nil {
- if os.IsNotExist(err) {
- log.Info("file does not exist, creating file")
-
- err = os.WriteFile(path, data, 0644)
- if err != nil {
- log.Fatal(err)
- }
-
- return
- }
-
- m.logger.Fatal(err)
- }
-
- if bytes.Equal(existingData, data) {
- return
- }
-
- log.Info("file contents changed, updating file")
-
- err = os.WriteFile(path, data, 0644)
- if err != nil {
- log.Fatal(err)
- }
-}
diff --git a/roles/defaults/vars/main.yml b/roles/defaults/vars/main.yml
index bae7f04..b977649 100644
--- a/roles/defaults/vars/main.yml
+++ b/roles/defaults/vars/main.yml
@@ -120,7 +120,7 @@
kube_vip: ghcr.io/kube-vip/kube-vip:v0.6.4
kubectl: docker.io/bitnami/kubectl:1.27.3
libvirt: "registry.atmosphere.dev/library/libvirtd:{{ atmosphere_release }}"
- libvirt_tls_sidecar: "registry.atmosphere.dev/library/libvirt-tls-sidecar:{{ atmosphere_release }}"
+ libvirt_tls_sidecar: registry.atmosphere.dev/library/libvirt-tls-sidecar:latest
libvirt_exporter: registry.atmosphere.dev/library/libvirtd-exporter:latest
local_path_provisioner_helper: docker.io/library/busybox:1.36.0
local_path_provisioner: docker.io/rancher/local-path-provisioner:v0.0.24
diff --git a/zuul.d/container-images/libvirt-tls-sidecar.yaml b/zuul.d/container-images/libvirt-tls-sidecar.yaml
deleted file mode 100644
index 93d997f..0000000
--- a/zuul.d/container-images/libvirt-tls-sidecar.yaml
+++ /dev/null
@@ -1,71 +0,0 @@
-# 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.
-
-- project:
- check:
- jobs:
- - atmosphere-build-container-image-libvirt-tls-sidecar
- gate:
- jobs:
- - atmosphere-upload-container-image-libvirt-tls-sidecar
- promote:
- jobs:
- - atmosphere-promote-container-image-libvirt-tls-sidecar
-
-- job:
- name: atmosphere-build-container-image-libvirt-tls-sidecar
- parent: atmosphere-build-container-image
- dependencies:
- - name: atmosphere-buildset-registry
- soft: false
- - name: atmosphere-build-container-image-ubuntu
- soft: true
- vars: &container_image_vars
- promote_container_image_job: atmosphere-upload-container-image-libvirt-tls-sidecar
- container_images:
- - context: .
- target: libvirt-tls-sidecar
- registry: registry.atmosphere.dev
- repository: registry.atmosphere.dev/library/libvirt-tls-sidecar
- arch:
- - linux/amd64
- - linux/arm64
- build_args:
- - "RELEASE={{ zuul.branch | replace('stable/', '') }}"
- tags:
- - "{{ zuul.branch | replace('stable/', '') }}"
- files: &container_image_files
- - images/ubuntu/.*
- - cmd/.*
- - internal/.*
- - Dockerfile
- - go.mod
- - go.sum
-
-- job:
- name: atmosphere-upload-container-image-libvirt-tls-sidecar
- parent: atmosphere-upload-container-image
- dependencies:
- - name: atmosphere-buildset-registry
- soft: false
- - name: atmosphere-upload-container-image-ubuntu
- soft: true
- vars: *container_image_vars
- files: *container_image_files
-
-- job:
- name: atmosphere-promote-container-image-libvirt-tls-sidecar
- parent: atmosphere-promote-container-image
- vars: *container_image_vars
- files: *container_image_files
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index d19341f..6a06bbe 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -44,8 +44,6 @@
soft: true
- name: atmosphere-build-container-image-kubernetes-entrypoint
soft: true
- - name: atmosphere-build-container-image-libvirt-tls-sidecar
- soft: true
- name: atmosphere-build-container-image-libvirtd
soft: true
- name: atmosphere-build-container-image-magnum
@@ -114,8 +112,6 @@
soft: true
- name: atmosphere-upload-container-image-kubernetes-entrypoint
soft: true
- - name: atmosphere-upload-container-image-libvirt-tls-sidecar
- soft: true
- name: atmosphere-upload-container-image-libvirtd
soft: true
- name: atmosphere-upload-container-image-magnum