Skip to content

Commit

Permalink
feat: add new CoreDNSUpdateStrategy API
Browse files Browse the repository at this point in the history
  • Loading branch information
dkoshkin committed Oct 31, 2024
1 parent 07c7ebe commit 5dc9fb6
Show file tree
Hide file tree
Showing 10 changed files with 180 additions and 26 deletions.
17 changes: 15 additions & 2 deletions api/v1alpha1/clusterconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ import (
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/variables"
)

const (
CoreDNSUpdateStrategyAutomatic CoreDNSUpdateStrategy = "Automatic"
CoreDNSUpdateStrategyManual CoreDNSUpdateStrategy = "Manual"
)

var (
DefaultDockerCertSANs = []string{
"localhost",
Expand Down Expand Up @@ -320,12 +325,20 @@ type DNS struct {
CoreDNS *CoreDNS `json:"coreDNS,omitempty"`
}

// +kubebuilder:validation:Optional
// +kubebuilder:validation:Enum=Manual;Automatic
type CoreDNSUpdateStrategy string

type CoreDNS struct {
// Image required for overriding Kubernetes DNS image details.
// If the image version is not specified,
// the default version based on the cluster's Kubernetes version will be used.
// +kubebuilder:validation:Optional
Image *Image `json:"image,omitempty"`

// UpdateStrategy defines the strategy for how the CoreDNS version will be updated.
// If not specified, the default value is Automatic,
// which sets the CoreDNS version based on the cluster's Kubernetes version.
// +kubebuilder:default=Automatic
UpdateStrategy *CoreDNSUpdateStrategy `json:"updateStrategy,omitempty"`
}

//nolint:gochecknoinits // Idiomatic to use init functions to register APIs with scheme.
Expand Down
15 changes: 11 additions & 4 deletions api/v1alpha1/crds/caren.nutanix.com_awsclusterconfigs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -379,10 +379,7 @@ spec:
description: CoreDNS defines the CoreDNS configuration for the cluster.
properties:
image:
description: |-
Image required for overriding Kubernetes DNS image details.
If the image version is not specified,
the default version based on the cluster's Kubernetes version will be used.
description: Image required for overriding Kubernetes DNS image details.
properties:
repository:
description: Repository is used to override the image repository to pull from.
Expand All @@ -393,6 +390,16 @@ spec:
pattern: ^[\w][\w.-]{0,127}$
type: string
type: object
updateStrategy:
default: Automatic
description: |-
UpdateStrategy defines the strategy for how the CoreDNS version will be updated.
If not specified, the default value is Automatic,
which sets the CoreDNS version based on the cluster's Kubernetes version.
enum:
- Manual
- Automatic
type: string
type: object
type: object
encryptionAtRest:
Expand Down
15 changes: 11 additions & 4 deletions api/v1alpha1/crds/caren.nutanix.com_dockerclusterconfigs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -296,10 +296,7 @@ spec:
description: CoreDNS defines the CoreDNS configuration for the cluster.
properties:
image:
description: |-
Image required for overriding Kubernetes DNS image details.
If the image version is not specified,
the default version based on the cluster's Kubernetes version will be used.
description: Image required for overriding Kubernetes DNS image details.
properties:
repository:
description: Repository is used to override the image repository to pull from.
Expand All @@ -310,6 +307,16 @@ spec:
pattern: ^[\w][\w.-]{0,127}$
type: string
type: object
updateStrategy:
default: Automatic
description: |-
UpdateStrategy defines the strategy for how the CoreDNS version will be updated.
If not specified, the default value is Automatic,
which sets the CoreDNS version based on the cluster's Kubernetes version.
enum:
- Manual
- Automatic
type: string
type: object
type: object
docker:
Expand Down
16 changes: 12 additions & 4 deletions api/v1alpha1/crds/caren.nutanix.com_genericclusterconfigs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,8 @@ spec:
cluster.
properties:
image:
description: |-
Image required for overriding Kubernetes DNS image details.
If the image version is not specified,
the default version based on the cluster's Kubernetes version will be used.
description: Image required for overriding Kubernetes DNS
image details.
properties:
repository:
description: Repository is used to override the image
Expand All @@ -74,6 +72,16 @@ spec:
pattern: ^[\w][\w.-]{0,127}$
type: string
type: object
updateStrategy:
default: Automatic
description: |-
UpdateStrategy defines the strategy for how the CoreDNS version will be updated.
If not specified, the default value is Automatic,
which sets the CoreDNS version based on the cluster's Kubernetes version.
enum:
- Manual
- Automatic
type: string
type: object
type: object
encryptionAtRest:
Expand Down
15 changes: 11 additions & 4 deletions api/v1alpha1/crds/caren.nutanix.com_nutanixclusterconfigs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -449,10 +449,7 @@ spec:
description: CoreDNS defines the CoreDNS configuration for the cluster.
properties:
image:
description: |-
Image required for overriding Kubernetes DNS image details.
If the image version is not specified,
the default version based on the cluster's Kubernetes version will be used.
description: Image required for overriding Kubernetes DNS image details.
properties:
repository:
description: Repository is used to override the image repository to pull from.
Expand All @@ -463,6 +460,16 @@ spec:
pattern: ^[\w][\w.-]{0,127}$
type: string
type: object
updateStrategy:
default: Automatic
description: |-
UpdateStrategy defines the strategy for how the CoreDNS version will be updated.
If not specified, the default value is Automatic,
which sets the CoreDNS version based on the cluster's Kubernetes version.
enum:
- Manual
- Automatic
type: string
type: object
type: object
encryptionAtRest:
Expand Down
5 changes: 5 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

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

47 changes: 47 additions & 0 deletions docs/content/customization/generic/dns.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ spec:
image:
repository: my-registry.io/my-org/my-repo
tag: "v1.11.3_custom.0"
updateStrategy: Manual
```
Applying this configuration will result in the following value being set:
Expand All @@ -48,3 +49,49 @@ Applying this configuration will result in the following value being set:
imageRepository: "my-registry.io/my-org/my-repo"
imageTag: "v1.11.3_custom.0"
```

The CoreDNS version can also be updated automatically. To do this, set the `updateStrategy` to `Automatic`:

```yaml
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
name: <NAME>
spec:
topology:
variables:
- name: clusterConfig
value:
dns:
coreDNS:
updateStrategy: Automatic
```

Alternatively since the default value is `Automatic`, the following configuration is equivalent:

```yaml
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
name: <NAME>
spec:
topology:
variables:
- name: clusterConfig
value:
dns:
coreDNS: {}
```

Applying this configuration will result in the following value being set,
with the version of the CoreDNS image being set based on the cluster's Kubernetes version:

- `KubeadmControlPlaneTemplate`:

- ```yaml
spec:
kubeadmConfigSpec:
clusterConfiguration:
dns:
imageTag: "v1.11.3"
```
19 changes: 13 additions & 6 deletions pkg/handlers/generic/mutation/coredns/inject.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/utils/ptr"
bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1"
controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta1"
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
Expand Down Expand Up @@ -71,10 +72,11 @@ func (h *coreDNSPatchHandler) Mutate(
h.variableFieldPath...,
)
if err != nil {
if !variables.IsNotFoundError(err) {
return err
if variables.IsNotFoundError(err) {
log.V(5).Info("coreDNS variable not defined")
return nil
}
log.V(5).Info("coreDNS variable not defined")
return err
}

log = log.WithValues(
Expand All @@ -101,7 +103,7 @@ func (h *coreDNSPatchHandler) Mutate(
log.WithValues(
"patchedObjectKind", obj.GetObjectKind().GroupVersionKind().String(),
"patchedObjectName", ctrlclient.ObjectKeyFromObject(obj),
).Info("setting CoreDNS version")
).Info("setting CoreDNS version if needed")

if obj.Spec.Template.Spec.KubeadmConfigSpec.ClusterConfiguration == nil {
obj.Spec.Template.Spec.KubeadmConfigSpec.ClusterConfiguration = &bootstrapv1.ClusterConfiguration{}
Expand All @@ -119,9 +121,14 @@ func (h *coreDNSPatchHandler) Mutate(
}
}

// If the CoreDNS image tag is still not set, set the image tag to the default CoreDNS version based on the
// If the updateStrategy is set Automatic, set the image tag to the default CoreDNS version based on the
// Kubernetes version.
if dns.ImageTag == "" {
// Default the strategy to Automatic if var is not nil.
strategy := ptr.Deref(
coreDNSVar.UpdateStrategy,
v1alpha1.CoreDNSUpdateStrategyAutomatic,
)
if strategy == v1alpha1.CoreDNSUpdateStrategyAutomatic {
defaultCoreDNSVersion, found := corednsversions.GetCoreDNSVersion(
cluster.Spec.Topology.Version,
)
Expand Down
43 changes: 41 additions & 2 deletions pkg/handlers/generic/mutation/coredns/inject_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/utils/ptr"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"

Expand Down Expand Up @@ -46,7 +47,34 @@ var _ = Describe("Generate CoreDNS patches", func() {
testDefs := []testObj{
{
patchTest: capitest.PatchTestDef{
Name: "unset variable",
Name: "unset variable",
},
cluster: clusterv1.Cluster{
ObjectMeta: metav1.ObjectMeta{
Name: "test-cluster",
Namespace: request.Namespace,
Labels: map[string]string{
clusterv1.ProviderNameLabel: "nutanix",
},
},
Spec: clusterv1.ClusterSpec{
Topology: &clusterv1.Topology{
Version: "1.30.100",
},
},
},
},
{
patchTest: capitest.PatchTestDef{
Name: "variable with defaults",
Vars: []runtimehooksv1.Variable{
capitest.VariableWithValue(
v1alpha1.ClusterConfigVariableName,
v1alpha1.CoreDNS{},
v1alpha1.DNSVariableName,
VariableName,
),
},
RequestItem: request.NewKubeadmControlPlaneTemplateRequestItem(""),
ExpectedPatchMatchers: []capitest.JSONPatchMatcher{{
Operation: "add",
Expand Down Expand Up @@ -85,6 +113,7 @@ var _ = Describe("Generate CoreDNS patches", func() {
Repository: "my-registry.io/my-org/my-repo",
Tag: "v1.11.3_custom.0",
},
UpdateStrategy: ptr.To(v1alpha1.CoreDNSUpdateStrategyManual),
},
v1alpha1.DNSVariableName,
VariableName,
Expand Down Expand Up @@ -171,6 +200,7 @@ var _ = Describe("Generate CoreDNS patches", func() {
Image: &v1alpha1.Image{
Tag: "v1.11.3_custom.0",
},
UpdateStrategy: ptr.To(v1alpha1.CoreDNSUpdateStrategyManual),
},
v1alpha1.DNSVariableName,
VariableName,
Expand Down Expand Up @@ -205,7 +235,15 @@ var _ = Describe("Generate CoreDNS patches", func() {
},
{
patchTest: capitest.PatchTestDef{
Name: "error if cannot find default CoreDNS version",
Name: "error if cannot find default CoreDNS version",
Vars: []runtimehooksv1.Variable{
capitest.VariableWithValue(
v1alpha1.ClusterConfigVariableName,
v1alpha1.CoreDNS{},
v1alpha1.DNSVariableName,
VariableName,
),
},
RequestItem: request.NewKubeadmControlPlaneTemplateRequestItem(""),
ExpectedFailure: true,
},
Expand Down Expand Up @@ -235,6 +273,7 @@ var _ = Describe("Generate CoreDNS patches", func() {
Repository: "my-registry.io/my-org/my-repo",
Tag: "v1.11.3_custom.0",
},
UpdateStrategy: ptr.To(v1alpha1.CoreDNSUpdateStrategyManual),
},
v1alpha1.DNSVariableName,
VariableName,
Expand Down
14 changes: 14 additions & 0 deletions pkg/handlers/generic/mutation/coredns/variables_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import (
nutanixclusterconfig "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/nutanix/clusterconfig"
)

const (
invalidUpdateStrategy = v1alpha1.CoreDNSUpdateStrategy("this:is:not:a:valid:update:strategy")
)

var testDefs = []capitest.VariableTestDef{{
Name: "unset",
Vals: v1alpha1.GenericClusterConfigSpec{
Expand Down Expand Up @@ -78,6 +82,16 @@ var testDefs = []capitest.VariableTestDef{{
},
},
ExpectError: true,
}, {
Name: "set an invalid updateStrategy",
Vals: v1alpha1.GenericClusterConfigSpec{
DNS: &v1alpha1.DNS{
CoreDNS: &v1alpha1.CoreDNS{
UpdateStrategy: ptr.To(invalidUpdateStrategy),
},
},
},
ExpectError: true,
}}

func TestVariableValidation_AWS(t *testing.T) {
Expand Down

0 comments on commit 5dc9fb6

Please sign in to comment.