Skip to content

Commit 3d04fb9

Browse files
bors[bot]zegl
andauthored
Merge #362
362: Support policy/v1 PodDisruptionBudget r=zegl a=zegl Support and recommend policy/v1 if using Kubernetes v1.21 or later. This updates #360 ``` RELNOTE: Support policy/v1 of PodDisruptionBudget. If --kubernetes-version is set to v1.21 or later, policy/v1 will be recommended over policy/v1beta1 ``` Co-authored-by: Gustav Westling <[email protected]>
2 parents 7da2723 + 4bffd12 commit 3d04fb9

17 files changed

+114
-19
lines changed

domain/kube-score.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
autoscalingv1 "k8s.io/api/autoscaling/v1"
77
corev1 "k8s.io/api/core/v1"
88
networkingv1 "k8s.io/api/networking/v1"
9-
policyv1beta1 "k8s.io/api/policy/v1beta1"
109
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1110
)
1211

@@ -128,7 +127,8 @@ type CronJobs interface {
128127
}
129128

130129
type PodDisruptionBudget interface {
131-
PodDisruptionBudget() policyv1beta1.PodDisruptionBudget
130+
Namespace() string
131+
PodDisruptionBudgetSelector() *metav1.LabelSelector
132132
FileLocationer
133133
}
134134

parser/internal/pdb/pod.go

+27-4
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,43 @@
11
package pod
22

33
import (
4+
policyv1 "k8s.io/api/policy/v1"
45
policyv1beta1 "k8s.io/api/policy/v1beta1"
6+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
57

68
ks "github.com/zegl/kube-score/domain"
79
)
810

9-
type PodDisruptionBudget struct {
11+
type PodDisruptionBudgetV1beta1 struct {
1012
Obj policyv1beta1.PodDisruptionBudget
1113
Location ks.FileLocation
1214
}
1315

14-
func (p PodDisruptionBudget) PodDisruptionBudget() policyv1beta1.PodDisruptionBudget {
15-
return p.Obj
16+
func (p PodDisruptionBudgetV1beta1) PodDisruptionBudgetSelector() *metav1.LabelSelector {
17+
return p.Obj.Spec.Selector
1618
}
1719

18-
func (p PodDisruptionBudget) FileLocation() ks.FileLocation {
20+
func (p PodDisruptionBudgetV1beta1) Namespace() string {
21+
return p.Obj.Namespace
22+
}
23+
24+
func (p PodDisruptionBudgetV1beta1) FileLocation() ks.FileLocation {
25+
return p.Location
26+
}
27+
28+
type PodDisruptionBudgetV1 struct {
29+
Obj policyv1.PodDisruptionBudget
30+
Location ks.FileLocation
31+
}
32+
33+
func (p PodDisruptionBudgetV1) PodDisruptionBudgetSelector() *metav1.LabelSelector {
34+
return p.Obj.Spec.Selector
35+
}
36+
37+
func (p PodDisruptionBudgetV1) FileLocation() ks.FileLocation {
1938
return p.Location
2039
}
40+
41+
func (p PodDisruptionBudgetV1) Namespace() string {
42+
return p.Obj.Namespace
43+
}

parser/parse.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"fmt"
66
"io/ioutil"
7+
policyv1 "k8s.io/api/policy/v1"
78
"log"
89
"strings"
910

@@ -322,7 +323,13 @@ func decodeItem(cnf config.Configuration, s *parsedObjects, detectedVersion sche
322323
case policyv1beta1.SchemeGroupVersion.WithKind("PodDisruptionBudget"):
323324
var disruptBudget policyv1beta1.PodDisruptionBudget
324325
errs.AddIfErr(decode(fileContents, &disruptBudget))
325-
dbug := internalpdb.PodDisruptionBudget{disruptBudget, fileLocation}
326+
dbug := internalpdb.PodDisruptionBudgetV1beta1{disruptBudget, fileLocation}
327+
s.podDisruptionBudgets = append(s.podDisruptionBudgets, dbug)
328+
s.bothMetas = append(s.bothMetas, ks.BothMeta{disruptBudget.TypeMeta, disruptBudget.ObjectMeta, dbug})
329+
case policyv1.SchemeGroupVersion.WithKind("PodDisruptionBudget"):
330+
var disruptBudget policyv1.PodDisruptionBudget
331+
errs.AddIfErr(decode(fileContents, &disruptBudget))
332+
dbug := internalpdb.PodDisruptionBudgetV1{disruptBudget, fileLocation}
326333
s.podDisruptionBudgets = append(s.podDisruptionBudgets, dbug)
327334
s.bothMetas = append(s.bothMetas, ks.BothMeta{disruptBudget.TypeMeta, disruptBudget.ObjectMeta, dbug})
328335

score/disruptionbudget/disruptionbudget.go

+3-4
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,12 @@ func Register(allChecks *checks.Checks, budgets ks.PodDisruptionBudgets) {
1818
}
1919

2020
func hasMatching(budgets []ks.PodDisruptionBudget, namespace string, lables map[string]string) (bool, error) {
21-
for _, b := range budgets {
22-
budget := b.PodDisruptionBudget()
23-
if budget.Namespace != namespace {
21+
for _, budget := range budgets {
22+
if budget.Namespace() != namespace {
2423
continue
2524
}
2625

27-
selector, err := metav1.LabelSelectorAsSelector(budget.Spec.Selector)
26+
selector, err := metav1.LabelSelectorAsSelector(budget.PodDisruptionBudgetSelector())
2827
if err != nil {
2928
return false, fmt.Errorf("failed to create selector: %v", err)
3029
}

score/poddisruptionbudget_test.go

+18-8
Original file line numberDiff line numberDiff line change
@@ -8,40 +8,50 @@ import (
88

99
func TestStatefulSetPodDisruptionBudgetMatches(t *testing.T) {
1010
t.Parallel()
11-
testExpectedScore(t, "statefulset-poddisruptionbudget-matches.yaml", "StatefulSet has PodDisruptionBudget", scorecard.GradeAllOK)
11+
testExpectedScore(t, "statefulset-poddisruptionbudget-v1beta1-matches.yaml", "StatefulSet has PodDisruptionBudget", scorecard.GradeAllOK)
1212
}
1313

1414
func TestStatefulSetPodDisruptionBudgetExpressionMatches(t *testing.T) {
1515
t.Parallel()
16-
testExpectedScore(t, "statefulset-poddisruptionbudget-expression-matches.yaml", "StatefulSet has PodDisruptionBudget", scorecard.GradeAllOK)
16+
testExpectedScore(t, "statefulset-poddisruptionbudget-v1beta1-expression-matches.yaml", "StatefulSet has PodDisruptionBudget", scorecard.GradeAllOK)
1717
}
1818

1919
func TestStatefulSetPodDisruptionBudgetExpressionNoMatch(t *testing.T) {
2020
t.Parallel()
21-
testExpectedScore(t, "statefulset-poddisruptionbudget-expression-no-match.yaml", "StatefulSet has PodDisruptionBudget", scorecard.GradeCritical)
21+
testExpectedScore(t, "statefulset-poddisruptionbudget-v1beta1-expression-no-match.yaml", "StatefulSet has PodDisruptionBudget", scorecard.GradeCritical)
2222
}
2323

2424
func TestStatefulSetPodDisruptionBudgetNoMatch(t *testing.T) {
2525
t.Parallel()
26-
testExpectedScore(t, "statefulset-poddisruptionbudget-no-match.yaml", "StatefulSet has PodDisruptionBudget", scorecard.GradeCritical)
26+
testExpectedScore(t, "statefulset-poddisruptionbudget-v1beta1-no-match.yaml", "StatefulSet has PodDisruptionBudget", scorecard.GradeCritical)
2727
}
2828

2929
func TestDeploymentPodDisruptionBudgetMatches(t *testing.T) {
3030
t.Parallel()
31-
testExpectedScore(t, "deployment-poddisruptionbudget-matches.yaml", "Deployment has PodDisruptionBudget", scorecard.GradeAllOK)
31+
testExpectedScore(t, "deployment-poddisruptionbudget-v1beta1-matches.yaml", "Deployment has PodDisruptionBudget", scorecard.GradeAllOK)
3232
}
3333

3434
func TestDeploymentPodDisruptionBudgetExpressionMatches(t *testing.T) {
3535
t.Parallel()
36-
testExpectedScore(t, "deployment-poddisruptionbudget-expression-matches.yaml", "Deployment has PodDisruptionBudget", scorecard.GradeAllOK)
36+
testExpectedScore(t, "deployment-poddisruptionbudget-v1beta1-expression-matches.yaml", "Deployment has PodDisruptionBudget", scorecard.GradeAllOK)
3737
}
3838

3939
func TestDeploymentPodDisruptionBudgetExpressionNoMatch(t *testing.T) {
4040
t.Parallel()
41-
testExpectedScore(t, "deployment-poddisruptionbudget-expression-no-match.yaml", "Deployment has PodDisruptionBudget", scorecard.GradeCritical)
41+
testExpectedScore(t, "deployment-poddisruptionbudget-v1beta1-expression-no-match.yaml", "Deployment has PodDisruptionBudget", scorecard.GradeCritical)
4242
}
4343

4444
func TestDeploymentPodDisruptionBudgetNoMatch(t *testing.T) {
4545
t.Parallel()
46-
testExpectedScore(t, "deployment-poddisruptionbudget-no-match.yaml", "Deployment has PodDisruptionBudget", scorecard.GradeCritical)
46+
testExpectedScore(t, "deployment-poddisruptionbudget-v1beta1-no-match.yaml", "Deployment has PodDisruptionBudget", scorecard.GradeCritical)
47+
}
48+
49+
func TestDeploymentPodDisruptionBudgetV1Matches(t *testing.T) {
50+
t.Parallel()
51+
testExpectedScore(t, "deployment-poddisruptionbudget-v1-matches.yaml", "Deployment has PodDisruptionBudget", scorecard.GradeAllOK)
52+
}
53+
54+
func TestDeploymentPodDisruptionBudgetV1NoMatch(t *testing.T) {
55+
t.Parallel()
56+
testExpectedScore(t, "deployment-poddisruptionbudget-v1-no-match.yaml", "Deployment has PodDisruptionBudget", scorecard.GradeCritical)
4757
}

score/stable/stable_version.go

+3
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ func metaStableAvailable(kubernetsVersion config.Semver) func(meta domain.BothMe
3939
"batch/v1beta1": {
4040
"CronJob": recommendedApi{"batch/v1", config.Semver{1, 21}},
4141
},
42+
"policy/v1beta1": {
43+
"PodDisruptionBudget": recommendedApi{"policy/v1", config.Semver{1, 21}},
44+
},
4245
}
4346

4447
score.Grade = scorecard.GradeAllOK

score/stable/stable_version_test.go

+7
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,10 @@ func TestStableVersionIngress(t *testing.T) {
3030
assert.Equal(t, scorecard.GradeWarning, scoreNew.Grade)
3131
assert.Equal(t, []scorecard.TestScoreComment{{Path: "", Summary: "The apiVersion and kind extensions/v1beta1/Ingress is deprecated", Description: "It's recommended to use networking.k8s.io/v1beta1 instead which has been available since Kubernetes v1.14", DocumentationURL: ""}}, scoreNew.Comments)
3232
}
33+
34+
func TestStableVersionPodDisruptionBudget(t *testing.T) {
35+
newKubernetes := metaStableAvailable(config.Semver{1, 21})
36+
scoreNew := newKubernetes(ks.BothMeta{TypeMeta: v1.TypeMeta{Kind: "PodDisruptionBudget", APIVersion: "policy/v1beta1"}})
37+
assert.Equal(t, scorecard.GradeWarning, scoreNew.Grade)
38+
assert.Equal(t, []scorecard.TestScoreComment{{Path: "", Summary: "The apiVersion and kind policy/v1beta1/PodDisruptionBudget is deprecated", Description: "It's recommended to use policy/v1 instead which has been available since Kubernetes v1.21", DocumentationURL: ""}}, scoreNew.Comments)
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
apiVersion: policy/v1
2+
kind: PodDisruptionBudget
3+
metadata:
4+
name: app-budget
5+
spec:
6+
minAvailable: 2
7+
selector:
8+
matchLabels:
9+
app: foo
10+
---
11+
apiVersion: apps/v1
12+
kind: Deployment
13+
metadata:
14+
name: statefulset-test-1
15+
spec:
16+
template:
17+
metadata:
18+
labels:
19+
app: foo
20+
spec:
21+
containers:
22+
- name: foobar
23+
image: foo:bar
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
apiVersion: policy/v1
2+
kind: PodDisruptionBudget
3+
metadata:
4+
name: app-budget
5+
spec:
6+
minAvailable: 2
7+
selector:
8+
matchLabels:
9+
app: not-foo
10+
---
11+
apiVersion: apps/v1
12+
kind: Deployment
13+
metadata:
14+
name: statefulset-test-1
15+
spec:
16+
template:
17+
metadata:
18+
labels:
19+
app: foo
20+
spec:
21+
containers:
22+
- name: foobar
23+
image: foo:bar

0 commit comments

Comments
 (0)