Skip to content

Commit

Permalink
add PDB trackability and unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
britaniar committed Dec 20, 2024
1 parent cb0c5f7 commit eff3b10
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 1 deletion.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ require (
k8s.io/apimachinery v0.30.3
k8s.io/client-go v0.30.3
k8s.io/component-base v0.30.2
k8s.io/component-helpers v0.28.3
k8s.io/klog/v2 v2.130.1
k8s.io/metrics v0.25.2
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8
Expand Down
23 changes: 23 additions & 0 deletions pkg/controllers/work/apply_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"go.uber.org/atomic"
appv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
policyv1 "k8s.io/api/policy/v1"
apiextensionshelpers "k8s.io/apiextensions-apiserver/pkg/apihelpers"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
Expand All @@ -41,6 +42,7 @@ import (
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/tools/record"
"k8s.io/component-helpers/apps/poddisruptionbudget"
"k8s.io/klog/v2"
"k8s.io/utils/ptr"
ctrl "sigs.k8s.io/controller-runtime"
Expand Down Expand Up @@ -453,6 +455,9 @@ func trackResourceAvailability(gvr schema.GroupVersionResource, curObj *unstruct
case utils.CustomResourceDefinitionGVR:
return trackCRDAvailability(curObj)

case utils.PodDisruptionBudgetGVR:
return trackPDBAvailability(curObj)

default:
if isDataResource(gvr) {
klog.V(2).InfoS("Data resources are available immediately", "gvr", gvr, "resource", klog.KObj(curObj))
Expand All @@ -463,6 +468,24 @@ func trackResourceAvailability(gvr schema.GroupVersionResource, curObj *unstruct
}
}

func trackPDBAvailability(curObj *unstructured.Unstructured) (ApplyAction, error) {
var pdb policyv1.PodDisruptionBudget
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(curObj.Object, &pdb); err != nil {
return errorApplyAction, controller.NewUnexpectedBehaviorError(err)
}
// Check if conditions are up-to-date
if poddisruptionbudget.ConditionsAreUpToDate(&pdb) {
if cond := meta.FindStatusCondition(pdb.Status.Conditions, policyv1.DisruptionAllowedCondition); cond != nil {
if cond.Status == metav1.ConditionTrue && cond.Reason == policyv1.SufficientPodsReason {
klog.V(2).InfoS("PodDisruptionBudget is available", "pdb", klog.KObj(curObj))
return manifestAvailableAction, nil
}
}
}
klog.V(2).InfoS("Still need to wait for PodDisruptionBudget to be available", "pdb", klog.KObj(curObj))
return manifestNotAvailableYetAction, nil
}

func trackCRDAvailability(curObj *unstructured.Unstructured) (ApplyAction, error) {
var crd apiextensionsv1.CustomResourceDefinition
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(curObj.Object, &crd); err != nil {
Expand Down
101 changes: 100 additions & 1 deletion pkg/controllers/work/apply_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1420,8 +1420,107 @@ func TestTrackResourceAvailability(t *testing.T) {
expected: manifestNotAvailableYetAction,
err: nil,
},
"Test PodDisruptionBudget available": {
gvr: utils.PodDisruptionBudgetGVR,
obj: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "policy/v1",
"kind": "PodDisruptionBudget",
"metadata": map[string]interface{}{
"name": "test-pdb",
"namespace": "default",
"generation": 2,
},
"spec": map[string]interface{}{
"minAvailable": 1,
},
"status": map[string]interface{}{
"currentHealthy": 2,
"desiredHealthy": 1,
"observedGeneration": 2,
"disruptionsAllowed": 1,
"expectedPods": 1,
"conditions": []interface{}{
map[string]interface{}{
"type": "DisruptionAllowed",
"status": "True",
"reason": "SufficientPods",
"observedGeneration": 2,
},
},
},
},
},
expected: manifestAvailableAction,
err: nil,
},
"Test PodDisruptionBudget unavailable (condition not up-to-date)": {
gvr: utils.PodDisruptionBudgetGVR,
obj: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "policy/v1",
"kind": "PodDisruptionBudget",
"metadata": map[string]interface{}{
"name": "test-pdb",
"namespace": "default",
"generation": 2,
},
"spec": map[string]interface{}{
"minAvailable": 1,
},
"status": map[string]interface{}{
"currentHealthy": 2,
"desiredHealthy": 1,
"observedGeneration": 1,
"disruptionsAllowed": 1,
"expectedPods": 1,
"conditions": []interface{}{
map[string]interface{}{
"type": "DisruptionAllowed",
"status": "True",
"reason": "SufficientPods",
},
},
},
},
},
expected: manifestNotAvailableYetAction,
err: nil,
},
"Test PodDisruptionBudget unavailable": {
gvr: utils.PodDisruptionBudgetGVR,
obj: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "policy/v1",
"kind": "PodDisruptionBudget",
"metadata": map[string]interface{}{
"name": "test-pdb",
"namespace": "default",
"generation": 2,
},
"spec": map[string]interface{}{
"minAvailable": 1,
},
"status": map[string]interface{}{
"currentHealthy": 1,
"desiredHealthy": 1,
"observedGeneration": 2,
"disruptionsAllowed": 1,
"expectedPods": 1,
"conditions": []interface{}{
map[string]interface{}{
"type": "DisruptionAllowed",
"status": "False",
"reason": "InsufficientPods",
},
},
},
},
},
expected: manifestNotAvailableYetAction,
err: nil,
},
}

for name, tt := range tests {
t.Run(name, func(t *testing.T) {
action, err := trackResourceAvailability(tt.gvr, tt.obj)
Expand Down
7 changes: 7 additions & 0 deletions pkg/utils/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
discoveryv1 "k8s.io/api/discovery/v1"
policyv1 "k8s.io/api/policy/v1"
rbacv1 "k8s.io/api/rbac/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/api/equality"
Expand Down Expand Up @@ -263,6 +264,12 @@ var (
Kind: "Pod",
}

PodDisruptionBudgetGVR = schema.GroupVersionResource{
Group: policyv1.GroupName,
Version: policyv1.SchemeGroupVersion.Version,
Resource: "poddisruptionbudgets",
}

RoleMetaGVK = metav1.GroupVersionKind{
Group: rbacv1.SchemeGroupVersion.Group,
Version: rbacv1.SchemeGroupVersion.Version,
Expand Down

0 comments on commit eff3b10

Please sign in to comment.