Skip to content

Commit cf4b87d

Browse files
authored
Parametrize job cluster role and image (#214)
* Add pre-requisite checks to build scripts * Improved switches descriptions * Add temporary dapper Dockerfile to ignored files * Implemented ability to parameterize job cluster role used by jobs managing helm charts * Implemented ability to parameterize job image used by jobs managing helm charts * Skip lint dot-imports check on *_test.go files --------- Signed-off-by: Piotr Minkina <[email protected]>
1 parent 4fd2026 commit cf4b87d

File tree

10 files changed

+89
-18
lines changed

10 files changed

+89
-18
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
.DS_Store
22
/.dapper
33
/.idea
4+
/Dockerfile.dapper*
5+
!/Dockerfile.dapper
46
/bin
57
/dist
68
helm-controller

.golangci.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@
3636
{
3737
"linters": "revive",
3838
"text": "unused-parameter"
39+
},
40+
{
41+
"path": "_test\\.go$",
42+
"text": "dot-imports: should not use dot imports"
3943
}
4044
]
4145
}

main.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@ var (
2626
)
2727

2828
type HelmController struct {
29-
Kubeconfig string `short:"k" usage:"Kubernetes config files, e.g. $HOME/.kube/config" env:"KUBECONFIG"`
30-
MasterURL string `short:"m" usage:"Kubernetes cluster master URL" env:"MASTERURL"`
31-
Namespace string `short:"n" usage:"Namespace to watch, empty means it will watch CRDs in all namespaces." env:"NAMESPACE"`
32-
Threads int `short:"t" usage:"Threadiness level to set, defaults to 2." default:"2" env:"THREADS"`
33-
ControllerName string `usage:"Unique name to identify this controller that is added to all HelmCharts tracked by this controller" default:"helm-controller" env:"CONTROLLER_NAME"`
34-
NodeName string `usage:"Name of the node this controller is running on" env:"NODE_NAME"`
35-
PprofPort int `usage:"Port to publish HTTP server runtime profiling data in the format expected by the pprof visualization tool. Only enabled if in debug mode" default:"6060"`
29+
Kubeconfig string `short:"k" usage:"Kubernetes config files, e.g. $HOME/.kube/config. May be set via KUBECONFIG env var." env:"KUBECONFIG"`
30+
MasterURL string `short:"m" usage:"Kubernetes cluster master URL. May be set via MASTERURL env var." env:"MASTERURL"`
31+
Namespace string `short:"n" usage:"Namespace to watch, empty means it will watch CRDs in all namespaces. May be set via NAMESPACE env var." env:"NAMESPACE"`
32+
Threads int `short:"t" usage:"Threadiness level to set. May be set via THREADS env var." default:"2" env:"THREADS"`
33+
ControllerName string `usage:"Unique name to identify this controller that is added to all HelmCharts tracked by this controller. May be set via CONTROLLER_NAME env var." default:"helm-controller" env:"CONTROLLER_NAME"`
34+
NodeName string `usage:"Name of the node this controller is running on. May be set via NODE_NAME env var." env:"NODE_NAME"`
35+
JobClusterRole string `usage:"Name of the cluster role to use for jobs created to manage helm charts. May be set via JOB_CLUSTER_ROLE env var." default:"cluster-admin" env:"JOB_CLUSTER_ROLE"`
36+
DefaultJobImage string `usage:"Default image to use by jobs managing helm charts. May be set via DEFAULT_JOB_IMAGE env var." env:"DEFAULT_JOB_IMAGE"`
37+
PprofPort int `usage:"Port to publish HTTP server runtime profiling data in the format expected by the pprof visualization tool. Only enabled if in debug mode." default:"6060"`
3638
}
3739

3840
func (a *HelmController) Run(cmd *cobra.Command, args []string) error {
@@ -60,8 +62,10 @@ func (a *HelmController) Run(cmd *cobra.Command, args []string) error {
6062
}
6163

6264
opts := common.Options{
63-
Threadiness: a.Threads,
64-
NodeName: a.NodeName,
65+
Threadiness: a.Threads,
66+
NodeName: a.NodeName,
67+
JobClusterRole: a.JobClusterRole,
68+
DefaultJobImage: a.DefaultJobImage,
6569
}
6670

6771
if err := opts.Validate(); err != nil {

pkg/controllers/chart/chart.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ var (
6060

6161
type Controller struct {
6262
systemNamespace string
63+
jobClusterRole string
6364
managedBy string
6465
helms helmcontroller.HelmChartController
6566
helmCache helmcontroller.HelmChartCache
@@ -72,8 +73,12 @@ type Controller struct {
7273
apiServerPort string
7374
}
7475

75-
func Register(ctx context.Context,
76-
systemNamespace, managedBy, apiServerPort string,
76+
func Register(
77+
ctx context.Context,
78+
systemNamespace,
79+
managedBy,
80+
jobClusterRole string,
81+
apiServerPort string,
7782
k8s kubernetes.Interface,
7883
apply apply.Apply,
7984
recorder record.EventRecorder,
@@ -90,6 +95,7 @@ func Register(ctx context.Context,
9095

9196
c := &Controller{
9297
systemNamespace: systemNamespace,
98+
jobClusterRole: jobClusterRole,
9399
managedBy: managedBy,
94100
helms: helms,
95101
helmCache: helmCache,
@@ -346,7 +352,7 @@ func (c *Controller) getJobAndRelatedResources(chart *v1.HelmChart) (*batch.Job,
346352
valuesSecret,
347353
contentConfigMap,
348354
serviceAccount(chart),
349-
roleBinding(chart),
355+
roleBinding(chart, c.jobClusterRole),
350356
}, nil
351357
}
352358

@@ -537,7 +543,7 @@ func valuesSecretAddConfig(secret *corev1.Secret, config *v1.HelmChartConfig) {
537543
}
538544
}
539545

540-
func roleBinding(chart *v1.HelmChart) *rbac.ClusterRoleBinding {
546+
func roleBinding(chart *v1.HelmChart, jobClusterRole string) *rbac.ClusterRoleBinding {
541547
return &rbac.ClusterRoleBinding{
542548
TypeMeta: metav1.TypeMeta{
543549
APIVersion: "rbac.authorization.k8s.io/v1",
@@ -549,7 +555,7 @@ func roleBinding(chart *v1.HelmChart) *rbac.ClusterRoleBinding {
549555
RoleRef: rbac.RoleRef{
550556
Kind: "ClusterRole",
551557
APIGroup: "rbac.authorization.k8s.io",
552-
Name: "cluster-admin",
558+
Name: jobClusterRole,
553559
},
554560
Subjects: []rbac.Subject{
555561
{

pkg/controllers/chart/chart_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ func TestDeleteJob(t *testing.T) {
5353
assert.Equal("helm-delete-traefik", job.Name)
5454
}
5555

56+
func TestInstallJobImage(t *testing.T) {
57+
assert := assert.New(t)
58+
chart := NewChart()
59+
chart.Spec.JobImage = "custom-job-image"
60+
job, _, _ := job(chart, "6443")
61+
assert.Equal("custom-job-image", job.Spec.Template.Spec.Containers[0].Image)
62+
}
63+
5664
func TestInstallArgs(t *testing.T) {
5765
assert := assert.New(t)
5866
stringArgs := strings.Join(args(NewChart()), " ")

pkg/controllers/common/options.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import "fmt"
44

55
// Options defines options that can be set on initializing the Helm Controller
66
type Options struct {
7-
Threadiness int
8-
NodeName string
7+
Threadiness int
8+
NodeName string
9+
JobClusterRole string
10+
DefaultJobImage string
911
}
1012

1113
func (opts Options) Validate() error {

pkg/controllers/controllers.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,15 @@ func Register(ctx context.Context, systemNamespace, controllerName string, cfg c
7272
controllerName = "helm-controller"
7373
}
7474

75+
// apply custom DefaultJobImage option to Helm before starting charts controller
76+
if opts.DefaultJobImage != "" {
77+
chart.DefaultJobImage = opts.DefaultJobImage
78+
}
79+
7580
chart.Register(ctx,
7681
systemNamespace,
7782
controllerName,
83+
opts.JobClusterRole,
7884
"6443",
7985
appCtx.K8s,
8086
appCtx.Apply,
@@ -91,6 +97,8 @@ func Register(ctx context.Context, systemNamespace, controllerName string, cfg c
9197
appCtx.Core.Secret())
9298

9399
klog.Infof("Starting helm controller with %d threads", opts.Threadiness)
100+
klog.Infof("Using cluster role '%s' for jobs managing helm charts", opts.JobClusterRole)
101+
klog.Infof("Using default image '%s' for jobs managing helm charts", chart.DefaultJobImage)
94102

95103
if len(systemNamespace) == 0 {
96104
klog.Info("Starting helm controller with no namespace")

scripts/e2e

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ K3S_VERSION=v1.25.9-k3s1
77

88
cd $(dirname $0)/..
99

10+
if [[ ! -f 'bin/helm-controller-image.txt' ]]; then
11+
echo "Run 'make package' first."
12+
exit 1
13+
fi
14+
1015
setup_k8s(){
1116
# Using k3s with embedded helm controller disabled
1217
docker pull rancher/k3s:$K3S_VERSION

scripts/package

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ SUFFIX="-${ARCH}"
88

99
cd $(dirname $0)/..
1010

11+
if [[ ! -f 'bin/helm-controller' ]]; then
12+
echo "Run 'make build' first."
13+
exit 1
14+
fi
15+
1116
TAG=${TAG:-${VERSION}${SUFFIX}}
1217
REPO=${REPO:-rancher}
1318

test/framework/controller.go

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ func (f *Framework) setupController(ctx context.Context) error {
2222
return err
2323
}
2424

25+
_, err = f.ClientSet.RbacV1().ClusterRoles().Create(ctx, f.getCr(), metav1.CreateOptions{})
26+
if err != nil {
27+
return err
28+
}
29+
2530
_, err = f.ClientSet.RbacV1().ClusterRoleBindings().Create(ctx, f.getCrb(), metav1.CreateOptions{})
2631
if err != nil {
2732
return err
@@ -94,7 +99,10 @@ func (f *Framework) getDeployment() *appsv1.Deployment {
9499
Name: f.Name,
95100
Image: getImage(),
96101
Command: []string{"helm-controller"},
97-
Args: []string{"--namespace", "helm-controller"},
102+
Args: []string{
103+
"--namespace", "helm-controller",
104+
"--job-cluster-role", f.Name,
105+
},
98106
},
99107
},
100108
},
@@ -110,6 +118,25 @@ func getImage() string {
110118
return "rancher/helm-controller:latest"
111119
}
112120

121+
func (f *Framework) getCr() *v1.ClusterRole {
122+
return &v1.ClusterRole{
123+
ObjectMeta: metav1.ObjectMeta{
124+
Name: f.Name,
125+
},
126+
Rules: []v1.PolicyRule{
127+
{
128+
APIGroups: []string{"*"},
129+
Resources: []string{"*"},
130+
Verbs: []string{"*"},
131+
},
132+
{
133+
NonResourceURLs: []string{"*"},
134+
Verbs: []string{"*"},
135+
},
136+
},
137+
}
138+
}
139+
113140
func (f *Framework) getCrb() *v1.ClusterRoleBinding {
114141
return &v1.ClusterRoleBinding{
115142
ObjectMeta: metav1.ObjectMeta{
@@ -118,7 +145,7 @@ func (f *Framework) getCrb() *v1.ClusterRoleBinding {
118145
RoleRef: v1.RoleRef{
119146
APIGroup: "rbac.authorization.k8s.io",
120147
Kind: "ClusterRole",
121-
Name: "cluster-admin",
148+
Name: f.Name,
122149
},
123150
Subjects: []v1.Subject{
124151
{

0 commit comments

Comments
 (0)