mirror of
https://github.com/stakater/Reloader.git
synced 2026-02-14 18:09:50 +00:00
1361 lines
49 KiB
Go
1361 lines
49 KiB
Go
package testutil
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"math/rand"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
argorolloutv1alpha1 "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1"
|
|
argorollout "github.com/argoproj/argo-rollouts/pkg/client/clientset/versioned"
|
|
openshiftv1 "github.com/openshift/api/apps/v1"
|
|
appsclient "github.com/openshift/client-go/apps/clientset/versioned"
|
|
"github.com/sirupsen/logrus"
|
|
"github.com/stakater/Reloader/internal/pkg/callbacks"
|
|
"github.com/stakater/Reloader/internal/pkg/constants"
|
|
"github.com/stakater/Reloader/internal/pkg/crypto"
|
|
"github.com/stakater/Reloader/internal/pkg/metrics"
|
|
"github.com/stakater/Reloader/internal/pkg/options"
|
|
"github.com/stakater/Reloader/internal/pkg/util"
|
|
"github.com/stakater/Reloader/pkg/common"
|
|
"github.com/stakater/Reloader/pkg/kube"
|
|
appsv1 "k8s.io/api/apps/v1"
|
|
batchv1 "k8s.io/api/batch/v1"
|
|
v1 "k8s.io/api/core/v1"
|
|
"k8s.io/apimachinery/pkg/api/meta"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/client-go/kubernetes"
|
|
core_v1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
|
csiv1 "sigs.k8s.io/secrets-store-csi-driver/apis/v1"
|
|
csiclient "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned"
|
|
csiclient_v1 "sigs.k8s.io/secrets-store-csi-driver/pkg/client/clientset/versioned/typed/apis/v1"
|
|
)
|
|
|
|
var (
|
|
letters = []rune("abcdefghijklmnopqrstuvwxyz")
|
|
// ConfigmapResourceType is a resource type which controller watches for changes
|
|
ConfigmapResourceType = "configMaps"
|
|
// SecretResourceType is a resource type which controller watches for changes
|
|
SecretResourceType = "secrets"
|
|
// SecretproviderclasspodstatusResourceType is a resource type which controller watches for changes
|
|
SecretProviderClassPodStatusResourceType = "secretproviderclasspodstatuses"
|
|
)
|
|
|
|
var (
|
|
Clients = kube.GetClients()
|
|
Pod = "test-reloader-" + RandSeq(5)
|
|
Namespace = "test-reloader-" + RandSeq(5)
|
|
ConfigmapNamePrefix = "testconfigmap-reloader"
|
|
SecretNamePrefix = "testsecret-reloader"
|
|
Data = "dGVzdFNlY3JldEVuY29kaW5nRm9yUmVsb2FkZXI="
|
|
NewData = "dGVzdE5ld1NlY3JldEVuY29kaW5nRm9yUmVsb2FkZXI="
|
|
UpdatedData = "dGVzdFVwZGF0ZWRTZWNyZXRFbmNvZGluZ0ZvclJlbG9hZGVy"
|
|
Collectors = metrics.NewCollectors()
|
|
SleepDuration = 3 * time.Second
|
|
)
|
|
|
|
// CreateNamespace creates namespace for testing
|
|
func CreateNamespace(namespace string, client kubernetes.Interface) {
|
|
_, err := client.CoreV1().Namespaces().Create(context.TODO(), &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}}, metav1.CreateOptions{})
|
|
if err != nil {
|
|
logrus.Fatalf("Failed to create namespace for testing %v", err)
|
|
} else {
|
|
logrus.Infof("Creating namespace for testing = %s", namespace)
|
|
}
|
|
}
|
|
|
|
// DeleteNamespace deletes namespace for testing
|
|
func DeleteNamespace(namespace string, client kubernetes.Interface) {
|
|
err := client.CoreV1().Namespaces().Delete(context.TODO(), namespace, metav1.DeleteOptions{})
|
|
if err != nil {
|
|
logrus.Fatalf("Failed to delete namespace that was created for testing %v", err)
|
|
} else {
|
|
logrus.Infof("Deleting namespace for testing = %s", namespace)
|
|
}
|
|
}
|
|
|
|
func getObjectMeta(namespace string, name string, autoReload bool, secretAutoReload bool, configmapAutoReload bool, secretproviderclass bool, extraAnnotations map[string]string) metav1.ObjectMeta {
|
|
return metav1.ObjectMeta{
|
|
Name: name,
|
|
Namespace: namespace,
|
|
Labels: map[string]string{"firstLabel": "temp"},
|
|
Annotations: getAnnotations(name, autoReload, secretAutoReload, configmapAutoReload, secretproviderclass, extraAnnotations),
|
|
}
|
|
}
|
|
|
|
func getAnnotations(name string, autoReload bool, secretAutoReload bool, configmapAutoReload bool, secretproviderclass bool, extraAnnotations map[string]string) map[string]string {
|
|
annotations := make(map[string]string)
|
|
if autoReload {
|
|
annotations[options.ReloaderAutoAnnotation] = "true"
|
|
}
|
|
if secretAutoReload {
|
|
annotations[options.SecretReloaderAutoAnnotation] = "true"
|
|
}
|
|
if configmapAutoReload {
|
|
annotations[options.ConfigmapReloaderAutoAnnotation] = "true"
|
|
}
|
|
if secretproviderclass {
|
|
annotations[options.SecretProviderClassReloaderAutoAnnotation] = "true"
|
|
}
|
|
|
|
if len(annotations) == 0 {
|
|
annotations = map[string]string{
|
|
options.ConfigmapUpdateOnChangeAnnotation: name,
|
|
options.SecretUpdateOnChangeAnnotation: name,
|
|
options.SecretProviderClassUpdateOnChangeAnnotation: name,
|
|
}
|
|
}
|
|
for k, v := range extraAnnotations {
|
|
annotations[k] = v
|
|
}
|
|
return annotations
|
|
}
|
|
|
|
func getEnvVarSources(name string) []v1.EnvFromSource {
|
|
return []v1.EnvFromSource{
|
|
{
|
|
ConfigMapRef: &v1.ConfigMapEnvSource{
|
|
LocalObjectReference: v1.LocalObjectReference{
|
|
Name: name,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
SecretRef: &v1.SecretEnvSource{
|
|
LocalObjectReference: v1.LocalObjectReference{
|
|
Name: name,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func getVolumes(name string) []v1.Volume {
|
|
return []v1.Volume{
|
|
{
|
|
Name: "projectedconfigmap",
|
|
VolumeSource: v1.VolumeSource{
|
|
Projected: &v1.ProjectedVolumeSource{
|
|
Sources: []v1.VolumeProjection{
|
|
{
|
|
ConfigMap: &v1.ConfigMapProjection{
|
|
LocalObjectReference: v1.LocalObjectReference{
|
|
Name: name,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "projectedsecret",
|
|
VolumeSource: v1.VolumeSource{
|
|
Projected: &v1.ProjectedVolumeSource{
|
|
Sources: []v1.VolumeProjection{
|
|
{
|
|
Secret: &v1.SecretProjection{
|
|
LocalObjectReference: v1.LocalObjectReference{
|
|
Name: name,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "configmap",
|
|
VolumeSource: v1.VolumeSource{
|
|
ConfigMap: &v1.ConfigMapVolumeSource{
|
|
LocalObjectReference: v1.LocalObjectReference{
|
|
Name: name,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "secret",
|
|
VolumeSource: v1.VolumeSource{
|
|
Secret: &v1.SecretVolumeSource{
|
|
SecretName: name,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "secretproviderclass",
|
|
VolumeSource: v1.VolumeSource{
|
|
CSI: &v1.CSIVolumeSource{
|
|
Driver: "secrets-store.csi.k8s.io",
|
|
VolumeAttributes: map[string]string{"secretProviderClass": name},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func getVolumeMounts() []v1.VolumeMount {
|
|
return []v1.VolumeMount{
|
|
{
|
|
MountPath: "etc/config",
|
|
Name: "configmap",
|
|
},
|
|
{
|
|
MountPath: "etc/sec",
|
|
Name: "secret",
|
|
},
|
|
{
|
|
MountPath: "etc/spc",
|
|
Name: "secretproviderclass",
|
|
},
|
|
{
|
|
MountPath: "etc/projectedconfig",
|
|
Name: "projectedconfigmap",
|
|
},
|
|
{
|
|
MountPath: "etc/projectedsec",
|
|
Name: "projectedsecret",
|
|
},
|
|
}
|
|
}
|
|
|
|
func getPodTemplateSpecWithEnvVars(name string) v1.PodTemplateSpec {
|
|
return v1.PodTemplateSpec{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Labels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
Spec: v1.PodSpec{
|
|
Containers: []v1.Container{
|
|
{
|
|
Image: "tutum/hello-world",
|
|
Name: name,
|
|
Env: []v1.EnvVar{
|
|
{
|
|
Name: "BUCKET_NAME",
|
|
Value: "test",
|
|
},
|
|
{
|
|
Name: "CONFIGMAP_" + util.ConvertToEnvVarName(name),
|
|
ValueFrom: &v1.EnvVarSource{
|
|
ConfigMapKeyRef: &v1.ConfigMapKeySelector{
|
|
LocalObjectReference: v1.LocalObjectReference{
|
|
Name: name,
|
|
},
|
|
Key: "test.url",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "SECRET_" + util.ConvertToEnvVarName(name),
|
|
ValueFrom: &v1.EnvVarSource{
|
|
SecretKeyRef: &v1.SecretKeySelector{
|
|
LocalObjectReference: v1.LocalObjectReference{
|
|
Name: name,
|
|
},
|
|
Key: "test.url",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func getPodTemplateSpecWithEnvVarSources(name string) v1.PodTemplateSpec {
|
|
return v1.PodTemplateSpec{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Labels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
Spec: v1.PodSpec{
|
|
Containers: []v1.Container{
|
|
{
|
|
Image: "tutum/hello-world",
|
|
Name: name,
|
|
EnvFrom: getEnvVarSources(name),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func getPodTemplateSpecWithVolumes(name string) v1.PodTemplateSpec {
|
|
return v1.PodTemplateSpec{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Labels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
Spec: v1.PodSpec{
|
|
Containers: []v1.Container{
|
|
{
|
|
Image: "tutum/hello-world",
|
|
Name: name,
|
|
Env: []v1.EnvVar{
|
|
{
|
|
Name: "BUCKET_NAME",
|
|
Value: "test",
|
|
},
|
|
},
|
|
VolumeMounts: getVolumeMounts(),
|
|
},
|
|
},
|
|
Volumes: getVolumes(name),
|
|
},
|
|
}
|
|
}
|
|
|
|
func getPodTemplateSpecWithInitContainer(name string) v1.PodTemplateSpec {
|
|
return v1.PodTemplateSpec{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Labels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
Spec: v1.PodSpec{
|
|
InitContainers: []v1.Container{
|
|
{
|
|
Image: "busybox",
|
|
Name: "busyBox",
|
|
VolumeMounts: getVolumeMounts(),
|
|
},
|
|
},
|
|
Containers: []v1.Container{
|
|
{
|
|
Image: "tutum/hello-world",
|
|
Name: name,
|
|
Env: []v1.EnvVar{
|
|
{
|
|
Name: "BUCKET_NAME",
|
|
Value: "test",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Volumes: getVolumes(name),
|
|
},
|
|
}
|
|
}
|
|
|
|
func getPodTemplateSpecWithInitContainerAndEnv(name string) v1.PodTemplateSpec {
|
|
return v1.PodTemplateSpec{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Labels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
Spec: v1.PodSpec{
|
|
InitContainers: []v1.Container{
|
|
{
|
|
Image: "busybox",
|
|
Name: "busyBox",
|
|
EnvFrom: getEnvVarSources(name),
|
|
},
|
|
},
|
|
Containers: []v1.Container{
|
|
{
|
|
Image: "tutum/hello-world",
|
|
Name: name,
|
|
Env: []v1.EnvVar{
|
|
{
|
|
Name: "BUCKET_NAME",
|
|
Value: "test",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
// GetDeployment provides deployment for testing
|
|
func GetDeployment(namespace string, deploymentName string) *appsv1.Deployment {
|
|
replicaset := int32(1)
|
|
return &appsv1.Deployment{
|
|
ObjectMeta: getObjectMeta(namespace, deploymentName, false, false, false, false, map[string]string{}),
|
|
Spec: appsv1.DeploymentSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
Replicas: &replicaset,
|
|
Strategy: appsv1.DeploymentStrategy{
|
|
Type: appsv1.RollingUpdateDeploymentStrategyType,
|
|
},
|
|
Template: getPodTemplateSpecWithVolumes(deploymentName),
|
|
},
|
|
}
|
|
}
|
|
|
|
// GetDeploymentConfig provides deployment for testing
|
|
func GetDeploymentConfig(namespace string, deploymentConfigName string) *openshiftv1.DeploymentConfig {
|
|
replicaset := int32(1)
|
|
podTemplateSpecWithVolume := getPodTemplateSpecWithVolumes(deploymentConfigName)
|
|
return &openshiftv1.DeploymentConfig{
|
|
ObjectMeta: getObjectMeta(namespace, deploymentConfigName, false, false, false, false, map[string]string{}),
|
|
Spec: openshiftv1.DeploymentConfigSpec{
|
|
Replicas: replicaset,
|
|
Strategy: openshiftv1.DeploymentStrategy{
|
|
Type: openshiftv1.DeploymentStrategyTypeRolling,
|
|
},
|
|
Template: &podTemplateSpecWithVolume,
|
|
},
|
|
}
|
|
}
|
|
|
|
// GetDeploymentWithInitContainer provides deployment with init container and volumeMounts
|
|
func GetDeploymentWithInitContainer(namespace string, deploymentName string) *appsv1.Deployment {
|
|
replicaset := int32(1)
|
|
return &appsv1.Deployment{
|
|
ObjectMeta: getObjectMeta(namespace, deploymentName, false, false, false, false, map[string]string{}),
|
|
Spec: appsv1.DeploymentSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
Replicas: &replicaset,
|
|
Strategy: appsv1.DeploymentStrategy{
|
|
Type: appsv1.RollingUpdateDeploymentStrategyType,
|
|
},
|
|
Template: getPodTemplateSpecWithInitContainer(deploymentName),
|
|
},
|
|
}
|
|
}
|
|
|
|
// GetDeploymentWithInitContainerAndEnv provides deployment with init container and EnvSource
|
|
func GetDeploymentWithInitContainerAndEnv(namespace string, deploymentName string) *appsv1.Deployment {
|
|
replicaset := int32(1)
|
|
return &appsv1.Deployment{
|
|
ObjectMeta: getObjectMeta(namespace, deploymentName, true, false, false, false, map[string]string{}),
|
|
Spec: appsv1.DeploymentSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
Replicas: &replicaset,
|
|
Strategy: appsv1.DeploymentStrategy{
|
|
Type: appsv1.RollingUpdateDeploymentStrategyType,
|
|
},
|
|
Template: getPodTemplateSpecWithInitContainerAndEnv(deploymentName),
|
|
},
|
|
}
|
|
}
|
|
|
|
func GetDeploymentWithEnvVars(namespace string, deploymentName string) *appsv1.Deployment {
|
|
replicaset := int32(1)
|
|
return &appsv1.Deployment{
|
|
ObjectMeta: getObjectMeta(namespace, deploymentName, true, false, false, false, map[string]string{}),
|
|
Spec: appsv1.DeploymentSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
Replicas: &replicaset,
|
|
Strategy: appsv1.DeploymentStrategy{
|
|
Type: appsv1.RollingUpdateDeploymentStrategyType,
|
|
},
|
|
Template: getPodTemplateSpecWithEnvVars(deploymentName),
|
|
},
|
|
}
|
|
}
|
|
|
|
func GetDeploymentConfigWithEnvVars(namespace string, deploymentConfigName string) *openshiftv1.DeploymentConfig {
|
|
replicaset := int32(1)
|
|
podTemplateSpecWithEnvVars := getPodTemplateSpecWithEnvVars(deploymentConfigName)
|
|
return &openshiftv1.DeploymentConfig{
|
|
ObjectMeta: getObjectMeta(namespace, deploymentConfigName, false, false, false, false, map[string]string{}),
|
|
Spec: openshiftv1.DeploymentConfigSpec{
|
|
Replicas: replicaset,
|
|
Strategy: openshiftv1.DeploymentStrategy{
|
|
Type: openshiftv1.DeploymentStrategyTypeRolling,
|
|
},
|
|
Template: &podTemplateSpecWithEnvVars,
|
|
},
|
|
}
|
|
}
|
|
|
|
func GetDeploymentWithEnvVarSources(namespace string, deploymentName string) *appsv1.Deployment {
|
|
replicaset := int32(1)
|
|
return &appsv1.Deployment{
|
|
ObjectMeta: getObjectMeta(namespace, deploymentName, true, false, false, false, map[string]string{}),
|
|
Spec: appsv1.DeploymentSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
Replicas: &replicaset,
|
|
Strategy: appsv1.DeploymentStrategy{
|
|
Type: appsv1.RollingUpdateDeploymentStrategyType,
|
|
},
|
|
Template: getPodTemplateSpecWithEnvVarSources(deploymentName),
|
|
},
|
|
}
|
|
}
|
|
|
|
func GetDeploymentWithPodAnnotations(namespace string, deploymentName string, both bool) *appsv1.Deployment {
|
|
replicaset := int32(1)
|
|
deployment := &appsv1.Deployment{
|
|
ObjectMeta: getObjectMeta(namespace, deploymentName, false, false, false, false, map[string]string{}),
|
|
Spec: appsv1.DeploymentSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
Replicas: &replicaset,
|
|
Strategy: appsv1.DeploymentStrategy{
|
|
Type: appsv1.RollingUpdateDeploymentStrategyType,
|
|
},
|
|
Template: getPodTemplateSpecWithEnvVarSources(deploymentName),
|
|
},
|
|
}
|
|
if !both {
|
|
deployment.Annotations = nil
|
|
}
|
|
deployment.Spec.Template.Annotations = getAnnotations(deploymentName, true, false, false, false, map[string]string{})
|
|
return deployment
|
|
}
|
|
|
|
func GetDeploymentWithTypedAutoAnnotation(namespace string, deploymentName string, resourceType string) *appsv1.Deployment {
|
|
replicaset := int32(1)
|
|
var objectMeta metav1.ObjectMeta
|
|
switch resourceType {
|
|
case SecretResourceType:
|
|
objectMeta = getObjectMeta(namespace, deploymentName, false, true, false, false, map[string]string{})
|
|
case ConfigmapResourceType:
|
|
objectMeta = getObjectMeta(namespace, deploymentName, false, false, true, false, map[string]string{})
|
|
case SecretProviderClassPodStatusResourceType:
|
|
objectMeta = getObjectMeta(namespace, deploymentName, false, false, false, true, map[string]string{})
|
|
}
|
|
|
|
return &appsv1.Deployment{
|
|
ObjectMeta: objectMeta,
|
|
Spec: appsv1.DeploymentSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
Replicas: &replicaset,
|
|
Strategy: appsv1.DeploymentStrategy{
|
|
Type: appsv1.RollingUpdateDeploymentStrategyType,
|
|
},
|
|
Template: getPodTemplateSpecWithVolumes(deploymentName),
|
|
},
|
|
}
|
|
}
|
|
|
|
func GetDeploymentWithExcludeAnnotation(namespace string, deploymentName string, resourceType string) *appsv1.Deployment {
|
|
replicaset := int32(1)
|
|
|
|
annotation := map[string]string{}
|
|
|
|
switch resourceType {
|
|
case SecretResourceType:
|
|
annotation[options.SecretExcludeReloaderAnnotation] = deploymentName
|
|
case ConfigmapResourceType:
|
|
annotation[options.ConfigmapExcludeReloaderAnnotation] = deploymentName
|
|
case SecretProviderClassPodStatusResourceType:
|
|
annotation[options.SecretProviderClassExcludeReloaderAnnotation] = deploymentName
|
|
}
|
|
|
|
return &appsv1.Deployment{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: deploymentName,
|
|
Namespace: namespace,
|
|
Labels: map[string]string{"firstLabel": "temp"},
|
|
Annotations: annotation,
|
|
},
|
|
Spec: appsv1.DeploymentSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
Replicas: &replicaset,
|
|
Strategy: appsv1.DeploymentStrategy{
|
|
Type: appsv1.RollingUpdateDeploymentStrategyType,
|
|
},
|
|
Template: getPodTemplateSpecWithVolumes(deploymentName),
|
|
},
|
|
}
|
|
}
|
|
|
|
// GetDaemonSet provides daemonset for testing
|
|
func GetDaemonSet(namespace string, daemonsetName string) *appsv1.DaemonSet {
|
|
return &appsv1.DaemonSet{
|
|
ObjectMeta: getObjectMeta(namespace, daemonsetName, false, false, false, false, map[string]string{}),
|
|
Spec: appsv1.DaemonSetSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
UpdateStrategy: appsv1.DaemonSetUpdateStrategy{
|
|
Type: appsv1.RollingUpdateDaemonSetStrategyType,
|
|
},
|
|
Template: getPodTemplateSpecWithVolumes(daemonsetName),
|
|
},
|
|
}
|
|
}
|
|
|
|
func GetDaemonSetWithEnvVars(namespace string, daemonSetName string) *appsv1.DaemonSet {
|
|
return &appsv1.DaemonSet{
|
|
ObjectMeta: getObjectMeta(namespace, daemonSetName, true, false, false, false, map[string]string{}),
|
|
Spec: appsv1.DaemonSetSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
UpdateStrategy: appsv1.DaemonSetUpdateStrategy{
|
|
Type: appsv1.RollingUpdateDaemonSetStrategyType,
|
|
},
|
|
Template: getPodTemplateSpecWithEnvVars(daemonSetName),
|
|
},
|
|
}
|
|
}
|
|
|
|
// GetStatefulSet provides statefulset for testing
|
|
func GetStatefulSet(namespace string, statefulsetName string) *appsv1.StatefulSet {
|
|
return &appsv1.StatefulSet{
|
|
ObjectMeta: getObjectMeta(namespace, statefulsetName, false, false, false, false, map[string]string{}),
|
|
Spec: appsv1.StatefulSetSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
UpdateStrategy: appsv1.StatefulSetUpdateStrategy{
|
|
Type: appsv1.RollingUpdateStatefulSetStrategyType,
|
|
},
|
|
Template: getPodTemplateSpecWithVolumes(statefulsetName),
|
|
},
|
|
}
|
|
}
|
|
|
|
// GetStatefulSet provides statefulset for testing
|
|
func GetStatefulSetWithEnvVar(namespace string, statefulsetName string) *appsv1.StatefulSet {
|
|
return &appsv1.StatefulSet{
|
|
ObjectMeta: getObjectMeta(namespace, statefulsetName, true, false, false, false, map[string]string{}),
|
|
Spec: appsv1.StatefulSetSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
UpdateStrategy: appsv1.StatefulSetUpdateStrategy{
|
|
Type: appsv1.RollingUpdateStatefulSetStrategyType,
|
|
},
|
|
Template: getPodTemplateSpecWithEnvVars(statefulsetName),
|
|
},
|
|
}
|
|
}
|
|
|
|
// GetConfigmap provides configmap for testing
|
|
func GetConfigmap(namespace string, configmapName string, testData string) *v1.ConfigMap {
|
|
return &v1.ConfigMap{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: configmapName,
|
|
Namespace: namespace,
|
|
Labels: map[string]string{"firstLabel": "temp"},
|
|
},
|
|
Data: map[string]string{"test.url": testData},
|
|
}
|
|
}
|
|
|
|
func GetSecretProviderClass(namespace string, secretProviderClassName string, data string) *csiv1.SecretProviderClass {
|
|
return &csiv1.SecretProviderClass{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: secretProviderClassName,
|
|
Namespace: namespace,
|
|
},
|
|
Spec: csiv1.SecretProviderClassSpec{
|
|
Provider: "Test",
|
|
Parameters: map[string]string{
|
|
"parameter1": data,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func GetSecretProviderClassPodStatus(namespace string, secretProviderClassPodStatusName string, data string) *csiv1.SecretProviderClassPodStatus {
|
|
return &csiv1.SecretProviderClassPodStatus{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: secretProviderClassPodStatusName,
|
|
Namespace: namespace,
|
|
},
|
|
Status: csiv1.SecretProviderClassPodStatusStatus{
|
|
PodName: "test123",
|
|
SecretProviderClassName: secretProviderClassPodStatusName,
|
|
TargetPath: "/var/lib/kubelet/d8771ddf-935a-4199-a20b-f35f71c1d9e7/volumes/kubernetes.io~csi/secrets-store-inline/mount",
|
|
Mounted: true,
|
|
Objects: []csiv1.SecretProviderClassObject{
|
|
{
|
|
ID: "parameter1",
|
|
Version: data,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
// GetConfigmapWithUpdatedLabel provides configmap for testing
|
|
func GetConfigmapWithUpdatedLabel(namespace string, configmapName string, testLabel string, testData string) *v1.ConfigMap {
|
|
return &v1.ConfigMap{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: configmapName,
|
|
Namespace: namespace,
|
|
Labels: map[string]string{"firstLabel": testLabel},
|
|
},
|
|
Data: map[string]string{"test.url": testData},
|
|
}
|
|
}
|
|
|
|
// GetSecret provides secret for testing
|
|
func GetSecret(namespace string, secretName string, data string) *v1.Secret {
|
|
return &v1.Secret{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: secretName,
|
|
Namespace: namespace,
|
|
Labels: map[string]string{"firstLabel": "temp"},
|
|
},
|
|
Data: map[string][]byte{"test.url": []byte(data)},
|
|
}
|
|
}
|
|
|
|
func GetCronJob(namespace string, cronJobName string) *batchv1.CronJob {
|
|
return &batchv1.CronJob{
|
|
ObjectMeta: getObjectMeta(namespace, cronJobName, false, false, false, false, map[string]string{}),
|
|
Spec: batchv1.CronJobSpec{
|
|
Schedule: "*/5 * * * *", // Run every 5 minutes
|
|
JobTemplate: batchv1.JobTemplateSpec{
|
|
Spec: batchv1.JobSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
Template: getPodTemplateSpecWithVolumes(cronJobName),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func GetJob(namespace string, jobName string) *batchv1.Job {
|
|
return &batchv1.Job{
|
|
ObjectMeta: getObjectMeta(namespace, jobName, false, false, false, false, map[string]string{}),
|
|
Spec: batchv1.JobSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
Template: getPodTemplateSpecWithVolumes(jobName),
|
|
},
|
|
}
|
|
}
|
|
|
|
func GetCronJobWithEnvVar(namespace string, cronJobName string) *batchv1.CronJob {
|
|
return &batchv1.CronJob{
|
|
ObjectMeta: getObjectMeta(namespace, cronJobName, true, false, false, false, map[string]string{}),
|
|
Spec: batchv1.CronJobSpec{
|
|
Schedule: "*/5 * * * *", // Run every 5 minutes
|
|
JobTemplate: batchv1.JobTemplateSpec{
|
|
Spec: batchv1.JobSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
Template: getPodTemplateSpecWithEnvVars(cronJobName),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func GetJobWithEnvVar(namespace string, jobName string) *batchv1.Job {
|
|
return &batchv1.Job{
|
|
ObjectMeta: getObjectMeta(namespace, jobName, true, false, false, false, map[string]string{}),
|
|
Spec: batchv1.JobSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
Template: getPodTemplateSpecWithEnvVars(jobName),
|
|
},
|
|
}
|
|
}
|
|
|
|
// GetSecretWithUpdatedLabel provides secret for testing
|
|
func GetSecretWithUpdatedLabel(namespace string, secretName string, label string, data string) *v1.Secret {
|
|
return &v1.Secret{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: secretName,
|
|
Namespace: namespace,
|
|
Labels: map[string]string{"firstLabel": label},
|
|
},
|
|
Data: map[string][]byte{"test.url": []byte(data)},
|
|
}
|
|
}
|
|
|
|
// GetResourceSHAFromEnvVar returns the SHA value of given environment variable
|
|
func GetResourceSHAFromEnvVar(containers []v1.Container, envVar string) string {
|
|
for i := range containers {
|
|
envs := containers[i].Env
|
|
for j := range envs {
|
|
if envs[j].Name == envVar {
|
|
return envs[j].Value
|
|
}
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetResourceSHAFromAnnotation returns the SHA value of given environment variable
|
|
func GetResourceSHAFromAnnotation(podAnnotations map[string]string) string {
|
|
lastReloadedResourceName := fmt.Sprintf("%s/%s",
|
|
constants.ReloaderAnnotationPrefix,
|
|
constants.LastReloadedFromAnnotation,
|
|
)
|
|
|
|
annotationJson, ok := podAnnotations[lastReloadedResourceName]
|
|
if !ok {
|
|
return ""
|
|
}
|
|
|
|
var last common.ReloadSource
|
|
bytes := []byte(annotationJson)
|
|
err := json.Unmarshal(bytes, &last)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
return last.Hash
|
|
}
|
|
|
|
// ConvertResourceToSHA generates SHA from secret, configmap or secretproviderclasspodstatus data
|
|
func ConvertResourceToSHA(resourceType string, namespace string, resourceName string, data string) string {
|
|
values := []string{}
|
|
switch resourceType {
|
|
case SecretResourceType:
|
|
secret := GetSecret(namespace, resourceName, data)
|
|
for k, v := range secret.Data {
|
|
values = append(values, k+"="+string(v[:]))
|
|
}
|
|
case ConfigmapResourceType:
|
|
configmap := GetConfigmap(namespace, resourceName, data)
|
|
for k, v := range configmap.Data {
|
|
values = append(values, k+"="+v)
|
|
}
|
|
case SecretProviderClassPodStatusResourceType:
|
|
secretproviderclasspodstatus := GetSecretProviderClassPodStatus(namespace, resourceName, data)
|
|
for _, v := range secretproviderclasspodstatus.Status.Objects {
|
|
values = append(values, v.ID+"="+v.Version)
|
|
}
|
|
values = append(values, "SecretProviderClassName="+secretproviderclasspodstatus.Status.SecretProviderClassName)
|
|
}
|
|
sort.Strings(values)
|
|
return crypto.GenerateSHA(strings.Join(values, ";"))
|
|
}
|
|
|
|
// CreateConfigMap creates a configmap in given namespace and returns the ConfigMapInterface
|
|
func CreateConfigMap(client kubernetes.Interface, namespace string, configmapName string, data string) (core_v1.ConfigMapInterface, error) {
|
|
logrus.Infof("Creating configmap")
|
|
configmapClient := client.CoreV1().ConfigMaps(namespace)
|
|
_, err := configmapClient.Create(context.TODO(), GetConfigmap(namespace, configmapName, data), metav1.CreateOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return configmapClient, err
|
|
}
|
|
|
|
// CreateSecretProviderClass creates a SecretProviderClass in given namespace and returns the SecretProviderClassInterface
|
|
func CreateSecretProviderClass(client csiclient.Interface, namespace string, secretProviderClassName string, data string) (csiclient_v1.SecretProviderClassInterface, error) {
|
|
logrus.Infof("Creating SecretProviderClass")
|
|
secretProviderClassClient := client.SecretsstoreV1().SecretProviderClasses(namespace)
|
|
_, err := secretProviderClassClient.Create(context.TODO(), GetSecretProviderClass(namespace, secretProviderClassName, data), metav1.CreateOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return secretProviderClassClient, err
|
|
}
|
|
|
|
// CreateSecretProviderClassPodStatus creates a SecretProviderClassPodStatus in given namespace and returns the SecretProviderClassPodStatusInterface
|
|
func CreateSecretProviderClassPodStatus(client csiclient.Interface, namespace string, secretProviderClassPodStatusName string, data string) (csiclient_v1.SecretProviderClassPodStatusInterface, error) {
|
|
logrus.Infof("Creating SecretProviderClassPodStatus")
|
|
secretProviderClassPodStatusClient := client.SecretsstoreV1().SecretProviderClassPodStatuses(namespace)
|
|
secretProviderClassPodStatus := GetSecretProviderClassPodStatus(namespace, secretProviderClassPodStatusName, data)
|
|
_, err := secretProviderClassPodStatusClient.Create(context.TODO(), secretProviderClassPodStatus, metav1.CreateOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return secretProviderClassPodStatusClient, err
|
|
}
|
|
|
|
// CreateSecret creates a secret in given namespace and returns the SecretInterface
|
|
func CreateSecret(client kubernetes.Interface, namespace string, secretName string, data string) (core_v1.SecretInterface, error) {
|
|
logrus.Infof("Creating secret")
|
|
secretClient := client.CoreV1().Secrets(namespace)
|
|
_, err := secretClient.Create(context.TODO(), GetSecret(namespace, secretName, data), metav1.CreateOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return secretClient, err
|
|
}
|
|
|
|
// CreateDeployment creates a deployment in given namespace and returns the Deployment
|
|
func CreateDeployment(client kubernetes.Interface, deploymentName string, namespace string, volumeMount bool) (*appsv1.Deployment, error) {
|
|
logrus.Infof("Creating Deployment")
|
|
deploymentClient := client.AppsV1().Deployments(namespace)
|
|
var deploymentObj *appsv1.Deployment
|
|
if volumeMount {
|
|
deploymentObj = GetDeployment(namespace, deploymentName)
|
|
} else {
|
|
deploymentObj = GetDeploymentWithEnvVars(namespace, deploymentName)
|
|
}
|
|
deployment, err := deploymentClient.Create(context.TODO(), deploymentObj, metav1.CreateOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return deployment, err
|
|
}
|
|
|
|
// CreateDeployment creates a deployment in given namespace and returns the Deployment
|
|
func CreateDeploymentWithAnnotations(client kubernetes.Interface, deploymentName string, namespace string, additionalAnnotations map[string]string, volumeMount bool) (*appsv1.Deployment, error) {
|
|
logrus.Infof("Creating Deployment")
|
|
deploymentClient := client.AppsV1().Deployments(namespace)
|
|
var deploymentObj *appsv1.Deployment
|
|
if volumeMount {
|
|
deploymentObj = GetDeployment(namespace, deploymentName)
|
|
} else {
|
|
deploymentObj = GetDeploymentWithEnvVars(namespace, deploymentName)
|
|
}
|
|
|
|
for annotationKey, annotationValue := range additionalAnnotations {
|
|
deploymentObj.Annotations[annotationKey] = annotationValue
|
|
}
|
|
|
|
deployment, err := deploymentClient.Create(context.TODO(), deploymentObj, metav1.CreateOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return deployment, err
|
|
}
|
|
|
|
// CreateDeploymentConfig creates a deploymentConfig in given namespace and returns the DeploymentConfig
|
|
func CreateDeploymentConfig(client appsclient.Interface, deploymentName string, namespace string, volumeMount bool) (*openshiftv1.DeploymentConfig, error) {
|
|
logrus.Infof("Creating DeploymentConfig")
|
|
deploymentConfigsClient := client.AppsV1().DeploymentConfigs(namespace)
|
|
var deploymentConfigObj *openshiftv1.DeploymentConfig
|
|
if volumeMount {
|
|
deploymentConfigObj = GetDeploymentConfig(namespace, deploymentName)
|
|
} else {
|
|
deploymentConfigObj = GetDeploymentConfigWithEnvVars(namespace, deploymentName)
|
|
}
|
|
deploymentConfig, err := deploymentConfigsClient.Create(context.TODO(), deploymentConfigObj, metav1.CreateOptions{})
|
|
time.Sleep(5 * time.Second)
|
|
return deploymentConfig, err
|
|
}
|
|
|
|
// CreateDeploymentWithInitContainer creates a deployment in given namespace with init container and returns the Deployment
|
|
func CreateDeploymentWithInitContainer(client kubernetes.Interface, deploymentName string, namespace string, volumeMount bool) (*appsv1.Deployment, error) {
|
|
logrus.Infof("Creating Deployment")
|
|
deploymentClient := client.AppsV1().Deployments(namespace)
|
|
var deploymentObj *appsv1.Deployment
|
|
if volumeMount {
|
|
deploymentObj = GetDeploymentWithInitContainer(namespace, deploymentName)
|
|
} else {
|
|
deploymentObj = GetDeploymentWithInitContainerAndEnv(namespace, deploymentName)
|
|
}
|
|
deployment, err := deploymentClient.Create(context.TODO(), deploymentObj, metav1.CreateOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return deployment, err
|
|
}
|
|
|
|
// CreateDeploymentWithEnvVarSource creates a deployment in given namespace and returns the Deployment
|
|
func CreateDeploymentWithEnvVarSource(client kubernetes.Interface, deploymentName string, namespace string) (*appsv1.Deployment, error) {
|
|
logrus.Infof("Creating Deployment")
|
|
deploymentClient := client.AppsV1().Deployments(namespace)
|
|
deploymentObj := GetDeploymentWithEnvVarSources(namespace, deploymentName)
|
|
deployment, err := deploymentClient.Create(context.TODO(), deploymentObj, metav1.CreateOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return deployment, err
|
|
|
|
}
|
|
|
|
// CreateDeploymentWithPodAnnotations creates a deployment in given namespace and returns the Deployment
|
|
func CreateDeploymentWithPodAnnotations(client kubernetes.Interface, deploymentName string, namespace string, both bool) (*appsv1.Deployment, error) {
|
|
logrus.Infof("Creating Deployment")
|
|
deploymentClient := client.AppsV1().Deployments(namespace)
|
|
deploymentObj := GetDeploymentWithPodAnnotations(namespace, deploymentName, both)
|
|
deployment, err := deploymentClient.Create(context.TODO(), deploymentObj, metav1.CreateOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return deployment, err
|
|
}
|
|
|
|
// CreateDeploymentWithEnvVarSourceAndAnnotations returns a deployment in given
|
|
// namespace with given annotations.
|
|
func CreateDeploymentWithEnvVarSourceAndAnnotations(client kubernetes.Interface, deploymentName string, namespace string, annotations map[string]string) (*appsv1.Deployment, error) {
|
|
logrus.Infof("Creating Deployment")
|
|
deploymentClient := client.AppsV1().Deployments(namespace)
|
|
deploymentObj := GetDeploymentWithEnvVarSources(namespace, deploymentName)
|
|
deploymentObj.Annotations = annotations
|
|
deployment, err := deploymentClient.Create(context.TODO(), deploymentObj, metav1.CreateOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return deployment, err
|
|
}
|
|
|
|
// CreateDeploymentWithTypedAutoAnnotation creates a deployment in given namespace and returns the Deployment with typed auto annotation
|
|
func CreateDeploymentWithTypedAutoAnnotation(client kubernetes.Interface, deploymentName string, namespace string, resourceType string) (*appsv1.Deployment, error) {
|
|
logrus.Infof("Creating Deployment")
|
|
deploymentClient := client.AppsV1().Deployments(namespace)
|
|
deploymentObj := GetDeploymentWithTypedAutoAnnotation(namespace, deploymentName, resourceType)
|
|
deployment, err := deploymentClient.Create(context.TODO(), deploymentObj, metav1.CreateOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return deployment, err
|
|
}
|
|
|
|
// CreateDeploymentWithExcludeAnnotation creates a deployment in given namespace and returns the Deployment with typed auto annotation
|
|
func CreateDeploymentWithExcludeAnnotation(client kubernetes.Interface, deploymentName string, namespace string, resourceType string) (*appsv1.Deployment, error) {
|
|
logrus.Infof("Creating Deployment")
|
|
deploymentClient := client.AppsV1().Deployments(namespace)
|
|
deploymentObj := GetDeploymentWithExcludeAnnotation(namespace, deploymentName, resourceType)
|
|
deployment, err := deploymentClient.Create(context.TODO(), deploymentObj, metav1.CreateOptions{})
|
|
return deployment, err
|
|
}
|
|
|
|
// CreateDaemonSet creates a deployment in given namespace and returns the DaemonSet
|
|
func CreateDaemonSet(client kubernetes.Interface, daemonsetName string, namespace string, volumeMount bool) (*appsv1.DaemonSet, error) {
|
|
logrus.Infof("Creating DaemonSet")
|
|
daemonsetClient := client.AppsV1().DaemonSets(namespace)
|
|
var daemonsetObj *appsv1.DaemonSet
|
|
if volumeMount {
|
|
daemonsetObj = GetDaemonSet(namespace, daemonsetName)
|
|
} else {
|
|
daemonsetObj = GetDaemonSetWithEnvVars(namespace, daemonsetName)
|
|
}
|
|
daemonset, err := daemonsetClient.Create(context.TODO(), daemonsetObj, metav1.CreateOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return daemonset, err
|
|
}
|
|
|
|
// CreateStatefulSet creates a deployment in given namespace and returns the StatefulSet
|
|
func CreateStatefulSet(client kubernetes.Interface, statefulsetName string, namespace string, volumeMount bool) (*appsv1.StatefulSet, error) {
|
|
logrus.Infof("Creating StatefulSet")
|
|
statefulsetClient := client.AppsV1().StatefulSets(namespace)
|
|
var statefulsetObj *appsv1.StatefulSet
|
|
if volumeMount {
|
|
statefulsetObj = GetStatefulSet(namespace, statefulsetName)
|
|
} else {
|
|
statefulsetObj = GetStatefulSetWithEnvVar(namespace, statefulsetName)
|
|
}
|
|
statefulset, err := statefulsetClient.Create(context.TODO(), statefulsetObj, metav1.CreateOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return statefulset, err
|
|
}
|
|
|
|
// CreateCronJob creates a cronjob in given namespace and returns the CronJob
|
|
func CreateCronJob(client kubernetes.Interface, cronJobName string, namespace string, volumeMount bool) (*batchv1.CronJob, error) {
|
|
logrus.Infof("Creating CronJob")
|
|
cronJobClient := client.BatchV1().CronJobs(namespace)
|
|
var cronJobObj *batchv1.CronJob
|
|
if volumeMount {
|
|
cronJobObj = GetCronJob(namespace, cronJobName)
|
|
} else {
|
|
cronJobObj = GetCronJobWithEnvVar(namespace, cronJobName)
|
|
}
|
|
cronJob, err := cronJobClient.Create(context.TODO(), cronJobObj, metav1.CreateOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return cronJob, err
|
|
}
|
|
|
|
// CreateJob creates a job in given namespace and returns the Job
|
|
func CreateJob(client kubernetes.Interface, jobName string, namespace string, volumeMount bool) (*batchv1.Job, error) {
|
|
logrus.Infof("Creating Job")
|
|
jobClient := client.BatchV1().Jobs(namespace)
|
|
var jobObj *batchv1.Job
|
|
if volumeMount {
|
|
jobObj = GetJob(namespace, jobName)
|
|
} else {
|
|
jobObj = GetJobWithEnvVar(namespace, jobName)
|
|
}
|
|
job, err := jobClient.Create(context.TODO(), jobObj, metav1.CreateOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return job, err
|
|
}
|
|
|
|
// DeleteDeployment creates a deployment in given namespace and returns the error if any
|
|
func DeleteDeployment(client kubernetes.Interface, namespace string, deploymentName string) error {
|
|
logrus.Infof("Deleting Deployment")
|
|
deploymentError := client.AppsV1().Deployments(namespace).Delete(context.TODO(), deploymentName, metav1.DeleteOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return deploymentError
|
|
}
|
|
|
|
// DeleteDeploymentConfig deletes a deploymentConfig in given namespace and returns the error if any
|
|
func DeleteDeploymentConfig(client appsclient.Interface, namespace string, deploymentConfigName string) error {
|
|
logrus.Infof("Deleting DeploymentConfig")
|
|
deploymentConfigError := client.AppsV1().DeploymentConfigs(namespace).Delete(context.TODO(), deploymentConfigName, metav1.DeleteOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return deploymentConfigError
|
|
}
|
|
|
|
// DeleteDaemonSet creates a daemonset in given namespace and returns the error if any
|
|
func DeleteDaemonSet(client kubernetes.Interface, namespace string, daemonsetName string) error {
|
|
logrus.Infof("Deleting DaemonSet %s", daemonsetName)
|
|
daemonsetError := client.AppsV1().DaemonSets(namespace).Delete(context.TODO(), daemonsetName, metav1.DeleteOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return daemonsetError
|
|
}
|
|
|
|
// DeleteStatefulSet creates a statefulset in given namespace and returns the error if any
|
|
func DeleteStatefulSet(client kubernetes.Interface, namespace string, statefulsetName string) error {
|
|
logrus.Infof("Deleting StatefulSet %s", statefulsetName)
|
|
statefulsetError := client.AppsV1().StatefulSets(namespace).Delete(context.TODO(), statefulsetName, metav1.DeleteOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return statefulsetError
|
|
}
|
|
|
|
// DeleteCronJob deletes a cronJob in given namespace and returns the error if any
|
|
func DeleteCronJob(client kubernetes.Interface, namespace string, cronJobName string) error {
|
|
logrus.Infof("Deleting CronJob %s", cronJobName)
|
|
cronJobError := client.BatchV1().CronJobs(namespace).Delete(context.TODO(), cronJobName, metav1.DeleteOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return cronJobError
|
|
}
|
|
|
|
// Deleteob deletes a job in given namespace and returns the error if any
|
|
func DeleteJob(client kubernetes.Interface, namespace string, jobName string) error {
|
|
logrus.Infof("Deleting Job %s", jobName)
|
|
jobError := client.BatchV1().Jobs(namespace).Delete(context.TODO(), jobName, metav1.DeleteOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return jobError
|
|
}
|
|
|
|
// UpdateConfigMap updates a configmap in given namespace and returns the error if any
|
|
func UpdateConfigMap(configmapClient core_v1.ConfigMapInterface, namespace string, configmapName string, label string, data string) error {
|
|
logrus.Infof("Updating configmap %q.\n", configmapName)
|
|
var configmap *v1.ConfigMap
|
|
if label != "" {
|
|
configmap = GetConfigmapWithUpdatedLabel(namespace, configmapName, label, data)
|
|
} else {
|
|
configmap = GetConfigmap(namespace, configmapName, data)
|
|
}
|
|
_, updateErr := configmapClient.Update(context.TODO(), configmap, metav1.UpdateOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return updateErr
|
|
}
|
|
|
|
// UpdateSecret updates a secret in given namespace and returns the error if any
|
|
func UpdateSecret(secretClient core_v1.SecretInterface, namespace string, secretName string, label string, data string) error {
|
|
logrus.Infof("Updating secret %q.\n", secretName)
|
|
var secret *v1.Secret
|
|
if label != "" {
|
|
secret = GetSecretWithUpdatedLabel(namespace, secretName, label, data)
|
|
} else {
|
|
secret = GetSecret(namespace, secretName, data)
|
|
}
|
|
_, updateErr := secretClient.Update(context.TODO(), secret, metav1.UpdateOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return updateErr
|
|
}
|
|
|
|
// UpdateSecretProviderClassPodStatus updates a secretproviderclasspodstatus in given namespace and returns the error if any
|
|
func UpdateSecretProviderClassPodStatus(spcpsClient csiclient_v1.SecretProviderClassPodStatusInterface, namespace string, spcpsName string, label string, data string) error {
|
|
logrus.Infof("Updating secretproviderclasspodstatus %q.\n", spcpsName)
|
|
updatedStatus := GetSecretProviderClassPodStatus(namespace, spcpsName, data).Status
|
|
secretproviderclasspodstatus, err := spcpsClient.Get(context.TODO(), spcpsName, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
secretproviderclasspodstatus.Status = updatedStatus
|
|
if label != "" {
|
|
labels := secretproviderclasspodstatus.Labels
|
|
if labels == nil {
|
|
labels = make(map[string]string)
|
|
}
|
|
labels["firstLabel"] = label
|
|
}
|
|
_, updateErr := spcpsClient.Update(context.TODO(), secretproviderclasspodstatus, metav1.UpdateOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return updateErr
|
|
}
|
|
|
|
// DeleteConfigMap deletes a configmap in given namespace and returns the error if any
|
|
func DeleteConfigMap(client kubernetes.Interface, namespace string, configmapName string) error {
|
|
logrus.Infof("Deleting configmap %q.\n", configmapName)
|
|
err := client.CoreV1().ConfigMaps(namespace).Delete(context.TODO(), configmapName, metav1.DeleteOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return err
|
|
}
|
|
|
|
// DeleteSecret deletes a secret in given namespace and returns the error if any
|
|
func DeleteSecret(client kubernetes.Interface, namespace string, secretName string) error {
|
|
logrus.Infof("Deleting secret %q.\n", secretName)
|
|
err := client.CoreV1().Secrets(namespace).Delete(context.TODO(), secretName, metav1.DeleteOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return err
|
|
}
|
|
|
|
// DeleteSecretProviderClass deletes a secretproviderclass in given namespace and returns the error if any
|
|
func DeleteSecretProviderClass(client csiclient.Interface, namespace string, secretProviderClassName string) error {
|
|
logrus.Infof("Deleting secretproviderclass %q.\n", secretProviderClassName)
|
|
err := client.SecretsstoreV1().SecretProviderClasses(namespace).Delete(context.TODO(), secretProviderClassName, metav1.DeleteOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return err
|
|
}
|
|
|
|
// DeleteSecretProviderClassPodStatus deletes a secretproviderclasspodstatus in given namespace and returns the error if any
|
|
func DeleteSecretProviderClassPodStatus(client csiclient.Interface, namespace string, secretProviderClassPodStatusName string) error {
|
|
logrus.Infof("Deleting secretproviderclasspodstatus %q.\n", secretProviderClassPodStatusName)
|
|
err := client.SecretsstoreV1().SecretProviderClassPodStatuses(namespace).Delete(context.TODO(), secretProviderClassPodStatusName, metav1.DeleteOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return err
|
|
}
|
|
|
|
// RandSeq generates a random sequence
|
|
func RandSeq(n int) string {
|
|
b := make([]rune, n)
|
|
for i := range b {
|
|
b[i] = letters[rand.Intn(len(letters))]
|
|
}
|
|
return string(b)
|
|
}
|
|
|
|
// VerifyResourceEnvVarUpdate verifies whether the rolling upgrade happened or not
|
|
func VerifyResourceEnvVarUpdate(clients kube.Clients, config common.Config, envVarPostfix string, upgradeFuncs callbacks.RollingUpgradeFuncs) bool {
|
|
items := upgradeFuncs.ItemsFunc(clients, config.Namespace)
|
|
for _, i := range items {
|
|
containers := upgradeFuncs.ContainersFunc(i)
|
|
accessor, err := meta.Accessor(i)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
annotations := accessor.GetAnnotations()
|
|
// match statefulsets with the correct annotation
|
|
annotationValue := annotations[config.Annotation]
|
|
searchAnnotationValue := annotations[options.AutoSearchAnnotation]
|
|
reloaderEnabledValue := annotations[options.ReloaderAutoAnnotation]
|
|
typedAutoAnnotationEnabledValue := annotations[config.TypedAutoAnnotation]
|
|
reloaderEnabled, err := strconv.ParseBool(reloaderEnabledValue)
|
|
typedAutoAnnotationEnabled, errTyped := strconv.ParseBool(typedAutoAnnotationEnabledValue)
|
|
matches := false
|
|
if err == nil && reloaderEnabled || errTyped == nil && typedAutoAnnotationEnabled {
|
|
matches = true
|
|
} else if annotationValue != "" {
|
|
values := strings.Split(annotationValue, ",")
|
|
for _, value := range values {
|
|
value = strings.Trim(value, " ")
|
|
if value == config.ResourceName {
|
|
matches = true
|
|
break
|
|
}
|
|
}
|
|
} else if searchAnnotationValue == "true" {
|
|
if config.ResourceAnnotations[options.SearchMatchAnnotation] == "true" {
|
|
matches = true
|
|
}
|
|
}
|
|
|
|
if matches {
|
|
envName := constants.EnvVarPrefix + util.ConvertToEnvVarName(config.ResourceName) + "_" + envVarPostfix
|
|
updated := GetResourceSHAFromEnvVar(containers, envName)
|
|
if updated == config.SHAValue {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// VerifyResourceEnvVarRemoved verifies whether the rolling upgrade happened or not and all Envvars SKAKATER_name_CONFIGMAP/SECRET are removed
|
|
func VerifyResourceEnvVarRemoved(clients kube.Clients, config common.Config, envVarPostfix string, upgradeFuncs callbacks.RollingUpgradeFuncs) bool {
|
|
items := upgradeFuncs.ItemsFunc(clients, config.Namespace)
|
|
for _, i := range items {
|
|
containers := upgradeFuncs.ContainersFunc(i)
|
|
accessor, err := meta.Accessor(i)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
annotations := accessor.GetAnnotations()
|
|
// match statefulsets with the correct annotation
|
|
|
|
annotationValue := annotations[config.Annotation]
|
|
searchAnnotationValue := annotations[options.AutoSearchAnnotation]
|
|
reloaderEnabledValue := annotations[options.ReloaderAutoAnnotation]
|
|
typedAutoAnnotationEnabledValue := annotations[config.TypedAutoAnnotation]
|
|
reloaderEnabled, err := strconv.ParseBool(reloaderEnabledValue)
|
|
typedAutoAnnotationEnabled, errTyped := strconv.ParseBool(typedAutoAnnotationEnabledValue)
|
|
|
|
matches := false
|
|
if err == nil && reloaderEnabled || errTyped == nil && typedAutoAnnotationEnabled {
|
|
matches = true
|
|
} else if annotationValue != "" {
|
|
values := strings.Split(annotationValue, ",")
|
|
for _, value := range values {
|
|
value = strings.Trim(value, " ")
|
|
if value == config.ResourceName {
|
|
matches = true
|
|
break
|
|
}
|
|
}
|
|
} else if searchAnnotationValue == "true" {
|
|
if config.ResourceAnnotations[options.SearchMatchAnnotation] == "true" {
|
|
matches = true
|
|
}
|
|
}
|
|
|
|
if matches {
|
|
envName := constants.EnvVarPrefix + util.ConvertToEnvVarName(config.ResourceName) + "_" + envVarPostfix
|
|
value := GetResourceSHAFromEnvVar(containers, envName)
|
|
if value == "" {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// VerifyResourceAnnotationUpdate verifies whether the rolling upgrade happened or not
|
|
func VerifyResourceAnnotationUpdate(clients kube.Clients, config common.Config, upgradeFuncs callbacks.RollingUpgradeFuncs) bool {
|
|
items := upgradeFuncs.ItemsFunc(clients, config.Namespace)
|
|
for _, i := range items {
|
|
podAnnotations := upgradeFuncs.PodAnnotationsFunc(i)
|
|
accessor, err := meta.Accessor(i)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
annotations := accessor.GetAnnotations()
|
|
// match statefulsets with the correct annotation
|
|
annotationValue := annotations[config.Annotation]
|
|
searchAnnotationValue := annotations[options.AutoSearchAnnotation]
|
|
reloaderEnabledValue := annotations[options.ReloaderAutoAnnotation]
|
|
typedAutoAnnotationEnabledValue := annotations[config.TypedAutoAnnotation]
|
|
reloaderEnabled, _ := strconv.ParseBool(reloaderEnabledValue)
|
|
typedAutoAnnotationEnabled, _ := strconv.ParseBool(typedAutoAnnotationEnabledValue)
|
|
matches := false
|
|
if reloaderEnabled || typedAutoAnnotationEnabled || reloaderEnabledValue == "" && typedAutoAnnotationEnabledValue == "" && options.AutoReloadAll {
|
|
matches = true
|
|
} else if annotationValue != "" {
|
|
values := strings.Split(annotationValue, ",")
|
|
for _, value := range values {
|
|
value = strings.Trim(value, " ")
|
|
if value == config.ResourceName {
|
|
matches = true
|
|
break
|
|
}
|
|
}
|
|
} else if searchAnnotationValue == "true" {
|
|
if config.ResourceAnnotations[options.SearchMatchAnnotation] == "true" {
|
|
matches = true
|
|
}
|
|
}
|
|
|
|
if matches {
|
|
updated := GetResourceSHAFromAnnotation(podAnnotations)
|
|
if updated == config.SHAValue {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func GetSHAfromEmptyData() string {
|
|
// Use a special marker that represents "deleted" or "empty" state
|
|
// This ensures we have a distinct, deterministic hash for the delete strategy
|
|
// Note: We could use GenerateSHA("") which now returns a hash, but using a marker
|
|
// makes the intent clearer and avoids potential confusion with actual empty data
|
|
return crypto.GenerateSHA("__RELOADER_EMPTY_DELETE_MARKER__")
|
|
}
|
|
|
|
// GetRollout provides rollout for testing
|
|
func GetRollout(namespace string, rolloutName string, annotations map[string]string) *argorolloutv1alpha1.Rollout {
|
|
replicaset := int32(1)
|
|
return &argorolloutv1alpha1.Rollout{
|
|
ObjectMeta: getObjectMeta(namespace, rolloutName, false, false, false, false, annotations),
|
|
Spec: argorolloutv1alpha1.RolloutSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"secondLabel": "temp"},
|
|
},
|
|
Replicas: &replicaset,
|
|
Template: getPodTemplateSpecWithVolumes(rolloutName),
|
|
},
|
|
}
|
|
}
|
|
|
|
// CreateRollout creates a rolout in given namespace and returns the Rollout
|
|
func CreateRollout(client argorollout.Interface, rolloutName string, namespace string, annotations map[string]string) (*argorolloutv1alpha1.Rollout, error) {
|
|
logrus.Infof("Creating Rollout")
|
|
rolloutClient := client.ArgoprojV1alpha1().Rollouts(namespace)
|
|
rolloutObj := GetRollout(namespace, rolloutName, annotations)
|
|
rollout, err := rolloutClient.Create(context.TODO(), rolloutObj, metav1.CreateOptions{})
|
|
time.Sleep(3 * time.Second)
|
|
return rollout, err
|
|
}
|