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

Allow dns operator to be disabled with managementState field #260

Merged
merged 2 commits into from Jul 23, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions go.mod
Expand Up @@ -7,8 +7,8 @@ require (
github.com/google/go-cmp v0.5.5
github.com/google/gofuzz v1.2.0 // indirect
github.com/kevinburke/go-bindata v3.11.0+incompatible
github.com/openshift/api v0.0.0-20210601190906-e782d76c7bc4
github.com/openshift/build-machinery-go v0.0.0-20210423112049-9415d7ebd33e
github.com/openshift/api v0.0.0-20210719174558-55d730c80aa9
github.com/openshift/build-machinery-go v0.0.0-20210712174854-1bb7fd1518d3
github.com/sirupsen/logrus v1.7.0
golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
k8s.io/api v0.21.1
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Expand Up @@ -374,10 +374,10 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/openshift/api v0.0.0-20210601190906-e782d76c7bc4 h1:Co6wBspugQ1f59+bNq6IXhFq20jg71fcjPyU0KAUXm0=
github.com/openshift/api v0.0.0-20210601190906-e782d76c7bc4/go.mod h1:izBmoXbUu3z5kUa4FjZhvekTsyzIWiOoaIgJiZBBMQs=
github.com/openshift/build-machinery-go v0.0.0-20210423112049-9415d7ebd33e h1:F7rBobgSjtYL3/zsgDUjlTVx3Z06hdgpoldpDcn7jzc=
github.com/openshift/build-machinery-go v0.0.0-20210423112049-9415d7ebd33e/go.mod h1:b1BuldmJlbA/xYtdZvKi+7j5YGB44qJUJDZ9zwiNCfE=
github.com/openshift/api v0.0.0-20210719174558-55d730c80aa9 h1:5XE/Uj3vJX/HUijKIlUsOhUDd6Urm6dQliIGi0GyiZE=
github.com/openshift/api v0.0.0-20210719174558-55d730c80aa9/go.mod h1:6CGz601vxLz2y2Xa51k5bnbAz0yH2oKMDH28yC2MT3w=
github.com/openshift/build-machinery-go v0.0.0-20210712174854-1bb7fd1518d3 h1:hYMLjavR8LrcCva788SxDqYjRc1k2w0LNGi7eX9vY5Y=
github.com/openshift/build-machinery-go v0.0.0-20210712174854-1bb7fd1518d3/go.mod h1:b1BuldmJlbA/xYtdZvKi+7j5YGB44qJUJDZ9zwiNCfE=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
Expand Down
295 changes: 108 additions & 187 deletions manifests/0000_70_dns-operator_00-custom-resource-definition.yaml

Large diffs are not rendered by default.

80 changes: 53 additions & 27 deletions pkg/operator/controller/controller.go
Expand Up @@ -111,38 +111,64 @@ func (r *reconciler) Reconcile(ctx context.Context, request reconcile.Request) (
}

if dns != nil {
// Ensure we have all the necessary scaffolding on which to place dns instances.
if err := r.ensureDNSNamespace(); err != nil {
errs = append(errs, fmt.Errorf("failed to ensure dns namespace: %v", err))
}

if dns.DeletionTimestamp != nil {
// Handle deletion.
if err := r.ensureOpenshiftExternalNameServiceDeleted(); err != nil {
errs = append(errs, fmt.Errorf("failed to delete external name for openshift service: %v", err))
switch dns.Spec.ManagementState {
case operatorv1.Unmanaged:
// When the operator is set to unmanaged, it should not make
// changes to the DNS or node resolver pods, but it should still
// update status
//
// TODO: fetch clusterDomain from higher level openshift resource
// when it is exposed
clusterDomain := "cluster.local"
clusterIP, err := r.getClusterIPFromNetworkConfig()
if err != nil {
errs = append(errs, fmt.Errorf("failed to get cluster IP from network config: %v", err))
}
haveDNSDaemonset, dnsDaemonset, err := r.currentDNSDaemonSet(dns)
if err != nil {
errs = append(errs, err)
}
if err := r.ensureDNSDeleted(dns); err != nil {
errs = append(errs, fmt.Errorf("failed to ensure deletion for dns %s: %v", dns.Name, err))
haveNodeResolverDaemonset, nodeResolverDaemonset, err := r.currentNodeResolverDaemonSet()
if err != nil {
errs = append(errs, err)
}
if err := r.syncDNSStatus(dns, clusterIP, clusterDomain, haveDNSDaemonset, dnsDaemonset, haveNodeResolverDaemonset, nodeResolverDaemonset); err != nil {
errs = append(errs, fmt.Errorf("failed to sync status of dns %q: %w", dns.Name, err))
}
default:
// Ensure we have all the necessary scaffolding on which to place dns instances.
if err := r.ensureDNSNamespace(); err != nil {
errs = append(errs, fmt.Errorf("failed to ensure dns namespace: %v", err))
}

if len(errs) == 0 {
// Clean up the finalizer to allow the dns to be deleted.
if slice.ContainsString(dns.Finalizers, DNSControllerFinalizer) {
updated := dns.DeepCopy()
updated.Finalizers = slice.RemoveString(updated.Finalizers, DNSControllerFinalizer)
if err := r.client.Update(ctx, updated); err != nil {
errs = append(errs, fmt.Errorf("failed to remove finalizer from dns %s: %v", dns.Name, err))
if dns.DeletionTimestamp != nil {
// Handle deletion.
if err := r.ensureOpenshiftExternalNameServiceDeleted(); err != nil {
errs = append(errs, fmt.Errorf("failed to delete external name for openshift service: %v", err))
}
if err := r.ensureDNSDeleted(dns); err != nil {
errs = append(errs, fmt.Errorf("failed to ensure deletion for dns %s: %v", dns.Name, err))
}

if len(errs) == 0 {
// Clean up the finalizer to allow the dns to be deleted.
if slice.ContainsString(dns.Finalizers, DNSControllerFinalizer) {
updated := dns.DeepCopy()
updated.Finalizers = slice.RemoveString(updated.Finalizers, DNSControllerFinalizer)
if err := r.client.Update(ctx, updated); err != nil {
errs = append(errs, fmt.Errorf("failed to remove finalizer from dns %s: %v", dns.Name, err))
}
}
}
}
} else if err := r.enforceDNSFinalizer(dns); err != nil {
errs = append(errs, fmt.Errorf("failed to enforce finalizer for dns %s: %v", dns.Name, err))
} else {
// Handle everything else.
if err := r.ensureDNS(dns); err != nil {
errs = append(errs, fmt.Errorf("failed to ensure dns %s: %v", dns.Name, err))
} else if err := r.ensureExternalNameForOpenshiftService(); err != nil {
errs = append(errs, fmt.Errorf("failed to ensure external name for openshift service: %v", err))
} else if err := r.enforceDNSFinalizer(dns); err != nil {
errs = append(errs, fmt.Errorf("failed to enforce finalizer for dns %s: %v", dns.Name, err))
} else {
// Handle everything else.
if err := r.ensureDNS(dns); err != nil {
errs = append(errs, fmt.Errorf("failed to ensure dns %s: %v", dns.Name, err))
} else if err := r.ensureExternalNameForOpenshiftService(); err != nil {
errs = append(errs, fmt.Errorf("failed to ensure external name for openshift service: %v", err))
}
}
}
}
Expand Down
23 changes: 22 additions & 1 deletion pkg/operator/controller/dns_status.go
Expand Up @@ -37,8 +37,8 @@ func (r *reconciler) syncDNSStatus(dns *operatorv1.DNS, clusterIP, clusterDomain
// computeDNSStatusConditions computes dns status conditions based on
// the status of ds and clusterIP.
func computeDNSStatusConditions(dns *operatorv1.DNS, clusterIP string, haveDNSDaemonset bool, dnsDaemonset *appsv1.DaemonSet, haveNodeResolverDaemonset bool, nodeResolverDaemonset *appsv1.DaemonSet) []operatorv1.OperatorCondition {
var oldDegradedCondition, oldProgressingCondition, oldAvailableCondition *operatorv1.OperatorCondition
oldConditions := dns.Status.Conditions
var oldDegradedCondition, oldProgressingCondition, oldAvailableCondition, oldUpgradeableCondition *operatorv1.OperatorCondition
for i := range oldConditions {
switch oldConditions[i].Type {
case operatorv1.OperatorStatusTypeDegraded:
Expand All @@ -47,13 +47,16 @@ func computeDNSStatusConditions(dns *operatorv1.DNS, clusterIP string, haveDNSDa
oldProgressingCondition = &oldConditions[i]
case operatorv1.OperatorStatusTypeAvailable:
oldAvailableCondition = &oldConditions[i]
case operatorv1.OperatorStatusTypeUpgradeable:
oldUpgradeableCondition = &oldConditions[i]
}
}

conditions := []operatorv1.OperatorCondition{
computeDNSDegradedCondition(oldDegradedCondition, clusterIP, haveDNSDaemonset, dnsDaemonset),
computeDNSProgressingCondition(oldProgressingCondition, dns, clusterIP, haveDNSDaemonset, dnsDaemonset, haveNodeResolverDaemonset, nodeResolverDaemonset),
computeDNSAvailableCondition(oldAvailableCondition, clusterIP, haveDNSDaemonset, dnsDaemonset),
computeDNSUpgradeableCondition(oldUpgradeableCondition, dns),
}

return conditions
Expand Down Expand Up @@ -204,6 +207,24 @@ func computeDNSAvailableCondition(oldCondition *operatorv1.OperatorCondition, cl
return setDNSLastTransitionTime(availableCondition, oldCondition)
}

func computeDNSUpgradeableCondition(oldCondition *operatorv1.OperatorCondition, dns *operatorv1.DNS) operatorv1.OperatorCondition {
upgradeableCondition := &operatorv1.OperatorCondition{
Type: operatorv1.OperatorStatusTypeUpgradeable,
}

if dns.Spec.ManagementState == operatorv1.Unmanaged {
upgradeableCondition.Status = operatorv1.ConditionFalse
upgradeableCondition.Reason = "OperatorUnmanaged"
upgradeableCondition.Message = "Cannot upgrade while managementState is Unmanaged"
} else {
upgradeableCondition.Status = operatorv1.ConditionTrue
upgradeableCondition.Reason = "AsExpected"
upgradeableCondition.Message = "DNS Operator can be upgraded"
}

return setDNSLastTransitionTime(upgradeableCondition, oldCondition)
}

// setDNSLastTransitionTime sets LastTransitionTime for the given condition.
// If the condition has changed, it will assign a new timestamp otherwise keeps the old timestamp.
func setDNSLastTransitionTime(condition, oldCondition *operatorv1.OperatorCondition) operatorv1.OperatorCondition {
Expand Down
89 changes: 60 additions & 29 deletions pkg/operator/controller/dns_status_test.go
Expand Up @@ -19,46 +19,55 @@ func TestDNSStatusConditions(t *testing.T) {
availDNS, desireDNS int32
haveNR bool
availNR, desireNR int32
managementState operatorv1.ManagementState
}
type testOut struct {
degraded, progressing, available bool
degraded, progressing, available, upgradeable bool
}
testCases := []struct {
inputs testIn
outputs testOut
}{
{testIn{false, false, 0, 0, false, 0, 0}, testOut{true, true, false}},
{testIn{false, true, 0, 0, true, 0, 0}, testOut{true, true, false}},
{testIn{false, true, 0, 0, true, 0, 2}, testOut{true, true, false}},
{testIn{false, true, 0, 2, true, 0, 0}, testOut{true, true, false}},
{testIn{false, true, 0, 2, true, 0, 2}, testOut{true, true, false}},
{testIn{false, true, 1, 2, true, 0, 2}, testOut{true, true, false}},
{testIn{false, true, 0, 2, true, 1, 2}, testOut{true, true, false}},
{testIn{false, true, 1, 2, true, 1, 2}, testOut{true, true, false}},
{testIn{false, true, 1, 2, true, 2, 2}, testOut{true, true, false}},
{testIn{false, true, 2, 2, true, 1, 2}, testOut{true, true, false}},
{testIn{false, true, 2, 2, true, 2, 2}, testOut{true, true, false}},
{testIn{true, true, 0, 0, true, 0, 0}, testOut{true, false, false}},
{testIn{true, true, 0, 0, true, 0, 2}, testOut{true, true, false}},
{testIn{true, true, 0, 2, true, 0, 0}, testOut{true, true, false}},
{testIn{true, true, 0, 2, true, 0, 2}, testOut{true, true, false}},
{testIn{true, true, 0, 2, true, 1, 2}, testOut{true, true, false}},
{testIn{true, true, 1, 2, true, 0, 2}, testOut{false, true, true}},
{testIn{true, true, 1, 2, true, 1, 2}, testOut{false, true, true}},
{testIn{true, true, 1, 2, true, 2, 2}, testOut{false, true, true}},
{testIn{true, true, 2, 2, true, 0, 2}, testOut{false, true, true}},
{testIn{true, true, 2, 2, true, 2, 2}, testOut{false, false, true}},
{testIn{true, true, 1, 3, true, 3, 3}, testOut{true, true, true}},
{testIn{true, true, 3, 3, true, 0, 3}, testOut{false, true, true}},
{testIn{true, true, 2, 3, true, 3, 3}, testOut{false, true, true}},
{testIn{true, true, 0, 1, true, 0, 1}, testOut{true, true, false}},
{testIn{false, false, 0, 0, false, 0, 0, operatorv1.Managed}, testOut{true, true, false, true}},
{testIn{false, true, 0, 0, true, 0, 0, operatorv1.Managed}, testOut{true, true, false, true}},
{testIn{false, true, 0, 0, true, 0, 2, operatorv1.Managed}, testOut{true, true, false, true}},
{testIn{false, true, 0, 2, true, 0, 0, operatorv1.Managed}, testOut{true, true, false, true}},
{testIn{false, true, 0, 2, true, 0, 2, operatorv1.Managed}, testOut{true, true, false, true}},
{testIn{false, true, 1, 2, true, 0, 2, operatorv1.Managed}, testOut{true, true, false, true}},
{testIn{false, true, 0, 2, true, 1, 2, operatorv1.Managed}, testOut{true, true, false, true}},
{testIn{false, true, 1, 2, true, 1, 2, operatorv1.Managed}, testOut{true, true, false, true}},
{testIn{false, true, 1, 2, true, 2, 2, operatorv1.Managed}, testOut{true, true, false, true}},
{testIn{false, true, 2, 2, true, 1, 2, operatorv1.Managed}, testOut{true, true, false, true}},
{testIn{false, true, 2, 2, true, 2, 2, operatorv1.Managed}, testOut{true, true, false, true}},
{testIn{true, true, 0, 0, true, 0, 0, operatorv1.Managed}, testOut{true, false, false, true}},
{testIn{true, true, 0, 0, true, 0, 2, operatorv1.Managed}, testOut{true, true, false, true}},
{testIn{true, true, 0, 2, true, 0, 0, operatorv1.Managed}, testOut{true, true, false, true}},
{testIn{true, true, 0, 2, true, 0, 2, operatorv1.Managed}, testOut{true, true, false, true}},
{testIn{true, true, 0, 2, true, 1, 2, operatorv1.Managed}, testOut{true, true, false, true}},
{testIn{true, true, 1, 2, true, 0, 2, operatorv1.Managed}, testOut{false, true, true, true}},
{testIn{true, true, 1, 2, true, 1, 2, operatorv1.Managed}, testOut{false, true, true, true}},
{testIn{true, true, 1, 2, true, 2, 2, operatorv1.Managed}, testOut{false, true, true, true}},
{testIn{true, true, 2, 2, true, 0, 2, operatorv1.Managed}, testOut{false, true, true, true}},
{testIn{true, true, 2, 2, true, 2, 2, operatorv1.Managed}, testOut{false, false, true, true}},
{testIn{true, true, 1, 3, true, 3, 3, operatorv1.Managed}, testOut{true, true, true, true}},
{testIn{true, true, 3, 3, true, 0, 3, operatorv1.Managed}, testOut{false, true, true, true}},
{testIn{true, true, 2, 3, true, 3, 3, operatorv1.Managed}, testOut{false, true, true, true}},
{testIn{true, true, 0, 1, true, 0, 1, operatorv1.Managed}, testOut{true, true, false, true}},
{testIn{true, true, 0, 0, true, 0, 2, operatorv1.Unmanaged}, testOut{true, true, false, false}},
{testIn{true, true, 1, 3, true, 3, 3, operatorv1.Unmanaged}, testOut{true, true, true, false}},
{testIn{true, true, 2, 2, true, 0, 2, operatorv1.Unmanaged}, testOut{false, true, true, false}},
{testIn{true, true, 2, 2, true, 2, 2, operatorv1.Unmanaged}, testOut{false, false, true, false}},
{testIn{true, true, 0, 0, true, 0, 2, operatorv1.ManagementState("")}, testOut{true, true, false, true}},
{testIn{true, true, 1, 3, true, 3, 3, operatorv1.ManagementState("")}, testOut{true, true, true, true}},
{testIn{true, true, 2, 2, true, 0, 2, operatorv1.ManagementState("")}, testOut{false, true, true, true}},
{testIn{true, true, 2, 2, true, 2, 2, operatorv1.ManagementState("")}, testOut{false, false, true, true}},
}

for i, tc := range testCases {
var (
clusterIP string

degraded, progressing, available operatorv1.ConditionStatus
degraded, progressing, available, upgradeable operatorv1.ConditionStatus
)
if tc.inputs.haveClusterIP {
clusterIP = "1.2.3.4"
Expand Down Expand Up @@ -103,6 +112,8 @@ func TestDNSStatusConditions(t *testing.T) {
},
}
}
dns := operatorv1.DNS{}
dns.Spec.ManagementState = tc.inputs.managementState
if tc.outputs.degraded {
degraded = operatorv1.ConditionTrue
} else {
Expand All @@ -118,6 +129,11 @@ func TestDNSStatusConditions(t *testing.T) {
} else {
available = operatorv1.ConditionFalse
}
if tc.outputs.upgradeable {
upgradeable = operatorv1.ConditionTrue
} else {
upgradeable = operatorv1.ConditionFalse
}
expected := []operatorv1.OperatorCondition{
{
Type: operatorv1.OperatorStatusTypeDegraded,
Expand All @@ -131,8 +147,12 @@ func TestDNSStatusConditions(t *testing.T) {
Type: operatorv1.OperatorStatusTypeAvailable,
Status: available,
},
{
Type: operatorv1.OperatorStatusTypeUpgradeable,
Status: upgradeable,
},
}
actual := computeDNSStatusConditions(&operatorv1.DNS{}, clusterIP, tc.inputs.haveDNS, dnsDaemonset, tc.inputs.haveNR, nodeResolverDaemonset)
actual := computeDNSStatusConditions(&dns, clusterIP, tc.inputs.haveDNS, dnsDaemonset, tc.inputs.haveNR, nodeResolverDaemonset)
gotExpected := true
if len(actual) != len(expected) {
gotExpected = false
Expand All @@ -156,7 +176,18 @@ func TestDNSStatusConditions(t *testing.T) {
if !tc.inputs.haveClusterIP {
haveClusterIP = "no cluster ip"
}
description := fmt.Sprintf("%s, %d/%d DNS pods available, %d/%d node-resolver pods available", haveClusterIP, tc.inputs.availDNS, tc.inputs.desireDNS, tc.inputs.availNR, tc.inputs.desireNR)
var managementState string
switch tc.inputs.managementState {
case operatorv1.Managed:
managementState = "Managed"
case operatorv1.Force:
managementState = "Force"
case operatorv1.Removed:
managementState = "Removed"
case operatorv1.Unmanaged:
managementState = "Unmanaged"
}
description := fmt.Sprintf("%s, %d/%d DNS pods available, %d/%d node-resolver pods available, managementState is %s", haveClusterIP, tc.inputs.availDNS, tc.inputs.desireDNS, tc.inputs.availNR, tc.inputs.desireNR, managementState)
Comment on lines +179 to +190
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use tc.inputs.managementState directly in the print statement?

Suggested change
var managementState string
switch tc.inputs.managementState {
case operatorv1.Managed:
managementState = "Managed"
case operatorv1.Force:
managementState = "Force"
case operatorv1.Removed:
managementState = "Removed"
case operatorv1.Unmanaged:
managementState = "Unmanaged"
}
description := fmt.Sprintf("%s, %d/%d DNS pods available, %d/%d node-resolver pods available, managementState is %s", haveClusterIP, tc.inputs.availDNS, tc.inputs.desireDNS, tc.inputs.availNR, tc.inputs.desireNR, managementState)
description := fmt.Sprintf("%s, %d/%d DNS pods available, %d/%d node-resolver pods available, managementState is %s", haveClusterIP, tc.inputs.availDNS, tc.inputs.desireDNS, tc.inputs.availNR, tc.inputs.desireNR, string(tc.inputs.managementState))

We can merge as-is leave that for a follow-up though.

if !gotExpected {
t.Fatalf("%q:\nexpected %#v\ngot %#v", description, expected, actual)
}
Expand Down
36 changes: 36 additions & 0 deletions pkg/operator/controller/status/controller.go
Expand Up @@ -161,6 +161,7 @@ func (r *reconciler) Reconcile(ctx context.Context, request reconcile.Request) (
computeOperatorDegradedCondition(state.haveDNS, &state.dns),
)
co.Status.Versions = computeOperatorStatusVersions(curVersions)
co.Status.Conditions = mergeConditions(co.Status.Conditions, computeOperatorUpgradeableCondition(&state.dns))

if !operatorStatusesEqual(*oldStatus, co.Status) {
if err := r.client.Status().Update(ctx, co); err != nil {
Expand Down Expand Up @@ -341,6 +342,41 @@ func checkDNSAvailable(dns *operatorv1.DNS) bool {
return false
}

// computeOperatorUpgradeableCondition computes the operator's current
// Upgradeable status state by examining the Upgradeable status of the DNS
// operator
func computeOperatorUpgradeableCondition(dns *operatorv1.DNS) configv1.ClusterOperatorStatusCondition {
upgradeable := true
message := ""
for _, cond := range dns.Status.Conditions {
if cond.Type == operatorv1.OperatorStatusTypeUpgradeable {
upgradeable = cond.Status == operatorv1.ConditionTrue
message = cond.Message
}
}
currentUpgradeableCondition := configv1.ClusterOperatorStatusCondition{
Type: configv1.OperatorUpgradeable,
}
if !upgradeable {
currentUpgradeableCondition.Status = configv1.ConditionFalse
currentUpgradeableCondition.Reason = "DNSNotUpgradeable"
if len(message) > 0 {
currentUpgradeableCondition.Message = fmt.Sprintf("DNS %s is not upgradeable: %s", dns.Name, message)
} else {
currentUpgradeableCondition.Message = fmt.Sprintf("DNS %s is not upgradeable", dns.Name)
}
} else {
currentUpgradeableCondition.Status = configv1.ConditionTrue
currentUpgradeableCondition.Reason = "DNSUpgradeable"
if len(message) > 0 {
currentUpgradeableCondition.Message = fmt.Sprintf("DNS %s is upgradeable: %s", dns.Name, message)
} else {
currentUpgradeableCondition.Message = fmt.Sprintf("DNS %s is upgradeable", dns.Name)
}
}
return currentUpgradeableCondition
}

// computeOperatorDegradedCondition computes the operator's current Degraded status state.
func computeOperatorDegradedCondition(haveDNS bool, dns *operatorv1.DNS) configv1.ClusterOperatorStatusCondition {
if !haveDNS {
Expand Down