Skip to content

Commit 9245541

Browse files
rsrchboyarttor
authored andcommitted
Add PodDisruptionBudget processor
1 parent eb3bebe commit 9245541

File tree

6 files changed

+185
-3
lines changed

6 files changed

+185
-3
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
apiVersion: policy/v1
2+
kind: PodDisruptionBudget
3+
metadata:
4+
name: {{ include "app.fullname" . }}-myapp-pdb
5+
labels:
6+
app: nginx
7+
{{- include "app.labels" . | nindent 4 }}
8+
spec:
9+
minAvailable: {{ .Values.myappPdb.minAvailable }}
10+
maxUnavailable: {{ .Values.myappPdb.maxUnavailable }}
11+
selector:
12+
matchLabels:
13+
app: nginx
14+
{{- include "app.selectorLabels" . | nindent 6 }}

examples/app/values.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ myapp:
8484
repository: gcr.io/kubebuilder/kube-rbac-proxy
8585
tag: v0.8.0
8686
replicas: 3
87+
myappPdb:
88+
minAvailable: 2
8789
myappService:
8890
ports:
8991
- name: https

pkg/app/app.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@ package app
22

33
import (
44
"context"
5-
"github.com/arttor/helmify/pkg/file"
6-
"github.com/arttor/helmify/pkg/processor/job"
7-
"github.com/arttor/helmify/pkg/processor/statefulset"
85
"io"
96
"os"
107
"os/signal"
118
"syscall"
129

10+
"github.com/arttor/helmify/pkg/file"
11+
"github.com/arttor/helmify/pkg/processor/job"
12+
"github.com/arttor/helmify/pkg/processor/poddisruptionbudget"
13+
"github.com/arttor/helmify/pkg/processor/statefulset"
14+
1315
"github.com/sirupsen/logrus"
1416

1517
"github.com/arttor/helmify/pkg/config"
@@ -64,6 +66,7 @@ func Start(stdin io.Reader, config config.Config) error {
6466
webhook.MutatingWebhook(),
6567
job.NewCron(),
6668
job.NewJob(),
69+
poddisruptionbudget.New(),
6770
).WithDefaultProcessor(processor.Default())
6871
if len(config.Files) != 0 {
6972
file.Walk(config.Files, config.FilesRecursively, func(filename string, fileReader io.Reader) {
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package poddisruptionbudget
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"io"
7+
"strings"
8+
9+
"github.com/arttor/helmify/pkg/processor"
10+
11+
"github.com/arttor/helmify/pkg/helmify"
12+
yamlformat "github.com/arttor/helmify/pkg/yaml"
13+
"github.com/iancoleman/strcase"
14+
policyv1 "k8s.io/api/policy/v1"
15+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
16+
"k8s.io/apimachinery/pkg/runtime"
17+
"k8s.io/apimachinery/pkg/runtime/schema"
18+
"sigs.k8s.io/yaml"
19+
)
20+
21+
const (
22+
pdbTempSpec = `
23+
spec:
24+
minAvailable: {{ .Values.%[1]s.minAvailable }}
25+
maxUnavailable: {{ .Values.%[1]s.maxUnavailable }}
26+
selector:
27+
%[2]s
28+
{{- include "%[3]s.selectorLabels" . | nindent 6 }}`
29+
)
30+
31+
var pdbGVC = schema.GroupVersionKind{
32+
Group: "policy",
33+
Version: "v1",
34+
Kind: "PodDisruptionBudget",
35+
}
36+
37+
// New creates processor for k8s Service resource.
38+
func New() helmify.Processor {
39+
return &pdb{}
40+
}
41+
42+
type pdb struct{}
43+
44+
// Process k8s Service object into template. Returns false if not capable of processing given resource type.
45+
func (r pdb) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstructured) (bool, helmify.Template, error) {
46+
if obj.GroupVersionKind() != pdbGVC {
47+
return false, nil, nil
48+
}
49+
pdb := policyv1.PodDisruptionBudget{}
50+
err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, &pdb)
51+
if err != nil {
52+
return true, nil, fmt.Errorf("%w: unable to cast to pdb", err)
53+
}
54+
spec := pdb.Spec
55+
values := helmify.Values{}
56+
57+
meta, err := processor.ProcessObjMeta(appMeta, obj)
58+
if err != nil {
59+
return true, nil, err
60+
}
61+
62+
name := appMeta.TrimName(obj.GetName())
63+
shortName := strings.TrimPrefix(name, "controller-manager-")
64+
shortNameCamel := strcase.ToLowerCamel(shortName)
65+
66+
selector, _ := yaml.Marshal(pdb.Spec.Selector)
67+
selector = yamlformat.Indent(selector, 4)
68+
selector = bytes.TrimRight(selector, "\n ")
69+
70+
if spec.MaxUnavailable != nil {
71+
_, err := values.Add(spec.MaxUnavailable.IntValue(), shortNameCamel, "maxUnavailable")
72+
if err != nil {
73+
return true, nil, err
74+
}
75+
}
76+
77+
if spec.MinAvailable != nil {
78+
_, err := values.Add(spec.MinAvailable.IntValue(), shortNameCamel, "minAvailable")
79+
if err != nil {
80+
return true, nil, err
81+
}
82+
}
83+
84+
res := meta + fmt.Sprintf(pdbTempSpec, shortNameCamel, selector, appMeta.ChartName())
85+
return true, &result{
86+
name: shortName,
87+
data: res,
88+
values: values,
89+
}, nil
90+
}
91+
92+
type result struct {
93+
name string
94+
data string
95+
values helmify.Values
96+
}
97+
98+
func (r *result) Filename() string {
99+
return r.name + ".yaml"
100+
}
101+
102+
func (r *result) Values() helmify.Values {
103+
return r.values
104+
}
105+
106+
func (r *result) Write(writer io.Writer) error {
107+
_, err := writer.Write([]byte(r.data))
108+
return err
109+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package poddisruptionbudget
2+
3+
import (
4+
"os"
5+
"testing"
6+
7+
"github.com/arttor/helmify/pkg/metadata"
8+
9+
"github.com/arttor/helmify/internal"
10+
"github.com/stretchr/testify/assert"
11+
)
12+
13+
const pdbYaml = `apiVersion: policy/v1
14+
kind: PodDisruptionBudget
15+
metadata:
16+
labels:
17+
control-plane: controller-manager
18+
name: my-operator-controller-manager-pdb
19+
namespace: my-operator-system
20+
spec:
21+
minAvailable: 2
22+
selector:
23+
matchLabels:
24+
control-plane: controller-manager`
25+
26+
func Test_pdb_Process(t *testing.T) {
27+
var testInstance pdb
28+
29+
t.Run("processed", func(t *testing.T) {
30+
obj := internal.GenerateObj(pdbYaml)
31+
processed, tt, err := testInstance.Process(&metadata.Service{}, obj)
32+
_ = tt.Write(os.Stdout)
33+
assert.NoError(t, err)
34+
assert.Equal(t, true, processed)
35+
})
36+
t.Run("skipped", func(t *testing.T) {
37+
obj := internal.TestNs
38+
processed, _, err := testInstance.Process(&metadata.Service{}, obj)
39+
assert.NoError(t, err)
40+
assert.Equal(t, false, processed)
41+
})
42+
}

test_data/sample-app.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,3 +334,15 @@ spec:
334334
resources:
335335
requests:
336336
storage: 1Gi
337+
---
338+
apiVersion: policy/v1
339+
kind: PodDisruptionBudget
340+
metadata:
341+
labels:
342+
app: nginx
343+
name: myapp-pdb
344+
spec:
345+
minAvailable: 2
346+
selector:
347+
matchLabels:
348+
app: nginx

0 commit comments

Comments
 (0)