Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use StrategicMergePatch to apply overrides #175

Merged
merged 2 commits into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ help: ## Display this help.
##@ Development

.PHONY: manifests
manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
manifests: controller-gen yq ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
$(YQ) -i '.spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.podTemplate.properties.spec.properties |= {}' config/crd/bases/etcd.aenix.io_etcdclusters.yaml

.PHONY: generate
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
Expand Down
60 changes: 5 additions & 55 deletions api/v1alpha1/etcdcluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
"k8s.io/apimachinery/pkg/util/intstr"
)

const defaultEtcdImage = "quay.io/coreos/etcd:v3.5.12"
const DefaultEtcdImage = "quay.io/coreos/etcd:v3.5.12"

// EtcdClusterSpec defines the desired state of EtcdCluster
type EtcdClusterSpec struct {
Expand Down Expand Up @@ -128,66 +128,16 @@ type EmbeddedObjectMetadata struct {
Annotations map[string]string `json:"annotations,omitempty" protobuf:"bytes,12,rep,name=annotations"`
}

// PodTemplate allows overrides, such as sidecars, init containers, changes to the security context, etc to the pod template generated by the operator.
type PodTemplate struct {
// EmbeddedObjectMetadata contains metadata relevant to an EmbeddedResource
// +optional
EmbeddedObjectMetadata `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`

// Spec defines the desired state of spec for etcd members. If not specified, default values will be used.
// Spec follows the structure of a regular Pod spec. Overrides defined here will be strategically merged with the default pod spec, generated by the operator.
// +optional
Spec PodSpec `json:"spec,omitempty"`
}

// PodSpec defines the desired state of PodSpec for etcd members.
// +k8s:openapi-gen=true
type PodSpec struct {
// Containers allows the user to add containers to the pod and change "etcd" container if such options are not
// available in the EtcdCluster custom resource.
// +optional
Containers []corev1.Container `json:"containers" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,2,rep,name=containers"`

// ImagePullSecrets An optional list of references to secrets in the same namespace
// to use for pulling images from registries
// see https://kubernetes.io/docs/concepts/containers/images/#referring-to-an-imagepullsecrets-on-a-pod
// +optional
ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"`
// ServiceAccountName is the name of the ServiceAccount to use to run the etcd pods.
// +optional
ServiceAccountName string `json:"serviceAccountName,omitempty"`
// ReadinessGates is an optional list of conditions that must be true for the pod to be considered ready for
// traffic. A pod is considered ready when all of its containers are ready.
// +optional
ReadinessGates []corev1.PodReadinessGate `json:"readinessGates,omitempty"`
// Affinity sets the scheduling constraints for the pod.
// +optional
Affinity *corev1.Affinity `json:"affinity,omitempty"`
// NodeSelector is a selector which must be true for the pod to fit on a node.
// +optional
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
// TopologySpreadConstraints describes how a group of pods ought to spread across topology domains.
// +optional
TopologySpreadConstraints []corev1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty"`
// Tolerations is a list of tolerations.
// +optional
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
// SecurityContext holds pod-level security attributes and common container settings.
// +optional
SecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty"`
// PriorityClassName is the name of the PriorityClass for this pod.
// +optional
PriorityClassName string `json:"priorityClassName,omitempty"`
// TerminationGracePeriodSeconds is the time to wait before forceful pod shutdown.
// +optional
TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty"`
// SchedulerName is the name of the scheduler to be used for scheduling the pod.
// +optional
SchedulerName string `json:"schedulerName,omitempty"`
// RuntimeClassName refers to a RuntimeClass object in the node.k8s.io group, which should be used to run this pod.
// +optional
RuntimeClassName *string `json:"runtimeClassName,omitempty"`
// Volumes are volumes for being used by the pods. Cannot collide with "data" volume used by etcd.
// +optional
Volumes []corev1.Volume `json:"volumes,omitempty" patchStrategy:"merge,retainKeys" patchMergeKey:"name" protobuf:"bytes,1,rep,name=volumes"`
// +kubebuilder:pruning:PreserveUnknownFields
Spec corev1.PodSpec `json:"spec,omitempty"`
}

// StorageSpec defines the configured storage for a etcd members.
Expand Down
15 changes: 0 additions & 15 deletions api/v1alpha1/etcdcluster_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package v1alpha1
import (
"fmt"
"math"
"slices"
"strings"

corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -64,20 +63,6 @@ func (r *EtcdCluster) Default() {
}
}
}
etcdContainerIdx := slices.IndexFunc(r.Spec.PodTemplate.Spec.Containers, func(c corev1.Container) bool {
return c.Name == "etcd"
})
if etcdContainerIdx == -1 {
r.Spec.PodTemplate.Spec.Containers = append(r.Spec.PodTemplate.Spec.Containers, corev1.Container{
Name: "etcd",
Image: defaultEtcdImage,
})
} else {
c := &r.Spec.PodTemplate.Spec.Containers[etcdContainerIdx]
if c.Image == "" {
c.Image = defaultEtcdImage
}
}
}

// +kubebuilder:webhook:path=/validate-etcd-aenix-io-v1alpha1-etcdcluster,mutating=false,failurePolicy=fail,sideEffects=None,groups=etcd.aenix.io,resources=etcdclusters,verbs=create;update,versions=v1alpha1,name=vetcdcluster.kb.io,admissionReviewVersions=v1
Expand Down
1 change: 0 additions & 1 deletion api/v1alpha1/etcdcluster_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ var _ = Describe("EtcdCluster Webhook", func() {
It("Should fill in the default value if a required field is empty", func() {
etcdCluster := &EtcdCluster{}
etcdCluster.Default()
Expect(etcdCluster.Spec.PodTemplate.Spec.Containers[0].Image).To(Equal(defaultEtcdImage))
Expect(etcdCluster.Spec.Replicas).To(BeNil(), "User should have an opportunity to create cluster with 0 replicas")
Expect(etcdCluster.Spec.Storage.EmptyDir).To(BeNil())
storage := etcdCluster.Spec.Storage.VolumeClaimTemplate.Spec.Resources.Requests.Storage()
Expand Down
80 changes: 0 additions & 80 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading