Files
Reloader/test/e2e/utils/workload_deployment.go
faizanahmad055 b5c8705395 Refactor code
Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>
2026-05-11 16:18:53 +02:00

129 lines
5.4 KiB
Go

package utils
import (
"context"
"time"
appsv1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/kubernetes"
)
// DeploymentAdapter implements WorkloadAdapter for Kubernetes Deployments.
type DeploymentAdapter struct {
client kubernetes.Interface
}
// NewDeploymentAdapter creates a new DeploymentAdapter.
func NewDeploymentAdapter(client kubernetes.Interface) *DeploymentAdapter {
return &DeploymentAdapter{client: client}
}
// Type returns the workload type.
func (a *DeploymentAdapter) Type() WorkloadType {
return WorkloadDeployment
}
// Create creates a Deployment with the given config.
func (a *DeploymentAdapter) Create(ctx context.Context, namespace, name string, cfg WorkloadConfig) error {
opts := buildDeploymentOptions(cfg)
_, err := CreateDeployment(ctx, a.client, namespace, name, opts...)
return err
}
// Delete removes the Deployment.
func (a *DeploymentAdapter) Delete(ctx context.Context, namespace, name string) error {
return DeleteDeployment(ctx, a.client, namespace, name)
}
// WaitReady waits for the Deployment to be ready using watches.
func (a *DeploymentAdapter) WaitReady(ctx context.Context, namespace, name string, timeout time.Duration) error {
watchFunc := func(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
return a.client.AppsV1().Deployments(namespace).Watch(ctx, opts)
}
_, err := WatchUntil(ctx, watchFunc, name, IsReady(DeploymentIsReady), timeout)
return err
}
// WaitReloaded waits for the Deployment to have the reload annotation using watches.
// It captures the current annotation value before watching so that a prior reload's annotation
// does not cause a false positive — the condition triggers only when the value changes.
func (a *DeploymentAdapter) WaitReloaded(ctx context.Context, namespace, name, annotationKey string, timeout time.Duration) (bool, error) {
priorValue, _ := a.GetPodTemplateAnnotation(ctx, namespace, name, annotationKey)
watchFunc := func(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
return a.client.AppsV1().Deployments(namespace).Watch(ctx, opts)
}
_, err := WatchUntil(ctx, watchFunc, name, HasPodTemplateAnnotationChanged(DeploymentPodTemplate, annotationKey, priorValue), timeout)
return HandleWatchResult(err)
}
// WaitEnvVar waits for the Deployment to have a STAKATER_ env var using watches.
// It captures the current env var value before watching so that a prior reload's value does not
// cause a false positive — the condition triggers only when the value appears or changes.
func (a *DeploymentAdapter) WaitEnvVar(ctx context.Context, namespace, name, prefix string, timeout time.Duration) (bool, error) {
priorValue := ""
if d, err := a.client.AppsV1().Deployments(namespace).Get(ctx, name, metav1.GetOptions{}); err == nil {
priorValue = GetEnvVarValueByPrefix(d.Spec.Template.Spec.Containers, prefix)
}
watchFunc := func(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
return a.client.AppsV1().Deployments(namespace).Watch(ctx, opts)
}
_, err := WatchUntil(ctx, watchFunc, name, HasEnvVarPrefixChanged(DeploymentContainers, prefix, priorValue), timeout)
return HandleWatchResult(err)
}
// WaitPaused waits for the Deployment to have the paused annotation using watches.
func (a *DeploymentAdapter) WaitPaused(ctx context.Context, namespace, name, annotationKey string, timeout time.Duration) (bool, error) {
watchFunc := func(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
return a.client.AppsV1().Deployments(namespace).Watch(ctx, opts)
}
_, err := WatchUntil(ctx, watchFunc, name, HasAnnotation(DeploymentAnnotations, annotationKey), timeout)
return HandleWatchResult(err)
}
// WaitUnpaused waits for the Deployment to NOT have the paused annotation using watches.
func (a *DeploymentAdapter) WaitUnpaused(ctx context.Context, namespace, name, annotationKey string, timeout time.Duration) (bool, error) {
watchFunc := func(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
return a.client.AppsV1().Deployments(namespace).Watch(ctx, opts)
}
_, err := WatchUntil(ctx, watchFunc, name, NoAnnotation(DeploymentAnnotations, annotationKey), timeout)
return HandleWatchResult(err)
}
// SupportsEnvVarStrategy returns true as Deployments support env var reload strategy.
func (a *DeploymentAdapter) SupportsEnvVarStrategy() bool {
return true
}
// RequiresSpecialHandling returns false as Deployments use standard rolling restart.
func (a *DeploymentAdapter) RequiresSpecialHandling() bool {
return false
}
// GetPodTemplateAnnotation returns the value of a pod template annotation.
func (a *DeploymentAdapter) GetPodTemplateAnnotation(ctx context.Context, namespace, name, annotationKey string) (string, error) {
deploy, err := a.client.AppsV1().Deployments(namespace).Get(ctx, name, metav1.GetOptions{})
if err != nil {
return "", err
}
return deploy.Spec.Template.Annotations[annotationKey], nil
}
// buildDeploymentOptions converts WorkloadConfig to DeploymentOption slice.
func buildDeploymentOptions(cfg WorkloadConfig) []DeploymentOption {
return []DeploymentOption{
func(d *appsv1.Deployment) {
if len(cfg.Annotations) > 0 {
if d.Annotations == nil {
d.Annotations = make(map[string]string)
}
for k, v := range cfg.Annotations {
d.Annotations[k] = v
}
}
ApplyWorkloadConfig(&d.Spec.Template, cfg)
},
}
}