mirror of
https://github.com/stakater/Reloader.git
synced 2026-08-20 12:36:26 +00:00
190 lines
5.1 KiB
Go
190 lines
5.1 KiB
Go
package workload
|
|
|
|
import (
|
|
"context"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
)
|
|
|
|
// PodTemplateAccessor provides access to a workload's pod template.
|
|
// Each workload type implements this to provide access to its specific template location.
|
|
type PodTemplateAccessor interface {
|
|
// GetPodTemplateSpec returns a pointer to the pod template spec.
|
|
// Returns nil if the workload doesn't have a pod template
|
|
GetPodTemplateSpec() *corev1.PodTemplateSpec
|
|
|
|
// GetObjectMeta returns the workload's object metadata.
|
|
GetObjectMeta() *metav1.ObjectMeta
|
|
}
|
|
|
|
// BaseWorkload provides common functionality for all workload types.
|
|
// It uses composition with a PodTemplateAccessor to access type-specific fields.
|
|
type BaseWorkload[T client.Object] struct {
|
|
object T
|
|
original T
|
|
accessor PodTemplateAccessor
|
|
kind Kind
|
|
}
|
|
|
|
// NewBaseWorkload creates a new BaseWorkload with the given object and accessor.
|
|
func NewBaseWorkload[T client.Object](obj T, original T, accessor PodTemplateAccessor, kind Kind) *BaseWorkload[T] {
|
|
return &BaseWorkload[T]{
|
|
object: obj,
|
|
original: original,
|
|
accessor: accessor,
|
|
kind: kind,
|
|
}
|
|
}
|
|
|
|
func (b *BaseWorkload[T]) Kind() Kind {
|
|
return b.kind
|
|
}
|
|
|
|
func (b *BaseWorkload[T]) GetObject() client.Object {
|
|
return b.object
|
|
}
|
|
|
|
func (b *BaseWorkload[T]) GetName() string {
|
|
return b.accessor.GetObjectMeta().Name
|
|
}
|
|
|
|
func (b *BaseWorkload[T]) GetNamespace() string {
|
|
return b.accessor.GetObjectMeta().Namespace
|
|
}
|
|
|
|
func (b *BaseWorkload[T]) GetAnnotations() map[string]string {
|
|
return b.accessor.GetObjectMeta().Annotations
|
|
}
|
|
|
|
func (b *BaseWorkload[T]) GetPodTemplateAnnotations() map[string]string {
|
|
template := b.accessor.GetPodTemplateSpec()
|
|
if template == nil {
|
|
return nil
|
|
}
|
|
if template.Annotations == nil {
|
|
template.Annotations = make(map[string]string)
|
|
}
|
|
return template.Annotations
|
|
}
|
|
|
|
func (b *BaseWorkload[T]) SetPodTemplateAnnotation(key, value string) {
|
|
template := b.accessor.GetPodTemplateSpec()
|
|
if template == nil {
|
|
return
|
|
}
|
|
if template.Annotations == nil {
|
|
template.Annotations = make(map[string]string)
|
|
}
|
|
template.Annotations[key] = value
|
|
}
|
|
|
|
func (b *BaseWorkload[T]) GetContainers() []corev1.Container {
|
|
template := b.accessor.GetPodTemplateSpec()
|
|
if template == nil {
|
|
return nil
|
|
}
|
|
return template.Spec.Containers
|
|
}
|
|
|
|
func (b *BaseWorkload[T]) SetContainers(containers []corev1.Container) {
|
|
template := b.accessor.GetPodTemplateSpec()
|
|
if template == nil {
|
|
return
|
|
}
|
|
template.Spec.Containers = containers
|
|
}
|
|
|
|
func (b *BaseWorkload[T]) GetInitContainers() []corev1.Container {
|
|
template := b.accessor.GetPodTemplateSpec()
|
|
if template == nil {
|
|
return nil
|
|
}
|
|
return template.Spec.InitContainers
|
|
}
|
|
|
|
func (b *BaseWorkload[T]) SetInitContainers(containers []corev1.Container) {
|
|
template := b.accessor.GetPodTemplateSpec()
|
|
if template == nil {
|
|
return
|
|
}
|
|
template.Spec.InitContainers = containers
|
|
}
|
|
|
|
func (b *BaseWorkload[T]) GetVolumes() []corev1.Volume {
|
|
template := b.accessor.GetPodTemplateSpec()
|
|
if template == nil {
|
|
return nil
|
|
}
|
|
return template.Spec.Volumes
|
|
}
|
|
|
|
func (b *BaseWorkload[T]) GetEnvFromSources() []corev1.EnvFromSource {
|
|
template := b.accessor.GetPodTemplateSpec()
|
|
if template == nil {
|
|
return nil
|
|
}
|
|
var sources []corev1.EnvFromSource
|
|
for _, container := range template.Spec.Containers {
|
|
sources = append(sources, container.EnvFrom...)
|
|
}
|
|
for _, container := range template.Spec.InitContainers {
|
|
sources = append(sources, container.EnvFrom...)
|
|
}
|
|
return sources
|
|
}
|
|
|
|
func (b *BaseWorkload[T]) UsesConfigMap(name string) bool {
|
|
template := b.accessor.GetPodTemplateSpec()
|
|
if template == nil {
|
|
return false
|
|
}
|
|
return SpecUsesConfigMap(&template.Spec, name)
|
|
}
|
|
|
|
func (b *BaseWorkload[T]) UsesSecret(name string) bool {
|
|
template := b.accessor.GetPodTemplateSpec()
|
|
if template == nil {
|
|
return false
|
|
}
|
|
return SpecUsesSecret(&template.Spec, name)
|
|
}
|
|
|
|
func (b *BaseWorkload[T]) GetOwnerReferences() []metav1.OwnerReference {
|
|
return b.accessor.GetObjectMeta().OwnerReferences
|
|
}
|
|
|
|
// Update performs a strategic merge patch update.
|
|
func (b *BaseWorkload[T]) Update(ctx context.Context, c client.Client) error {
|
|
return c.Patch(ctx, b.object, client.StrategicMergeFrom(b.original), client.FieldOwner(FieldManager))
|
|
}
|
|
|
|
// ResetOriginal resets the original state to the current object state.
|
|
func (b *BaseWorkload[T]) ResetOriginal() {
|
|
//nolint:errcheck // Type assertion is safe: DeepCopyObject returns same type T
|
|
b.original = b.object.DeepCopyObject().(T)
|
|
}
|
|
|
|
// UpdateStrategy returns the default patch strategy.
|
|
// Workloads with special update logic should override this.
|
|
func (b *BaseWorkload[T]) UpdateStrategy() UpdateStrategy {
|
|
return UpdateStrategyPatch
|
|
}
|
|
|
|
// PerformSpecialUpdate returns false for standard workloads.
|
|
// Workloads with special update logic should override this.
|
|
func (b *BaseWorkload[T]) PerformSpecialUpdate(ctx context.Context, c client.Client) (bool, error) {
|
|
return false, nil
|
|
}
|
|
|
|
// Object returns the underlying Kubernetes object.
|
|
func (b *BaseWorkload[T]) Object() T {
|
|
return b.object
|
|
}
|
|
|
|
// Original returns the original state of the object.
|
|
func (b *BaseWorkload[T]) Original() T {
|
|
return b.original
|
|
}
|