Skip to content

Commit a73fc01

Browse files
yevgeny-shnaidmank8s-ci-robot
authored andcommitted
Introducing MBSC controller
MBSC controller is responsible for handling building and signing of the images based on the Spec of the MBSC object The flow is as following: 1. get the running build or sign pods and update the MBSC status based on those pods 2. process the spec of the MBSC object. For each image and action verify if it has already been completed successfully. If not - call the buildsign package, which will know how to handle new requests, or updates to the existing pods 3. run garbage-collect - delete succeesfully completed build/sign pods.
1 parent ebe89d0 commit a73fc01

File tree

4 files changed

+563
-7
lines changed

4 files changed

+563
-7
lines changed

config/rbac/role.yaml

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,34 +68,46 @@ rules:
6868
- apiGroups:
6969
- kmm.sigs.x-k8s.io
7070
resources:
71-
- moduleimagesconfigs
72-
- nodemodulesconfigs
71+
- modulebuildsignconfigs
7372
verbs:
7473
- create
75-
- delete
7674
- get
7775
- list
7876
- patch
77+
- update
7978
- watch
8079
- apiGroups:
8180
- kmm.sigs.x-k8s.io
8281
resources:
83-
- modules
82+
- modulebuildsignconfigs/status
83+
- modules/status
84+
- preflightvalidations/status
8485
verbs:
8586
- get
86-
- list
8787
- patch
8888
- update
89+
- apiGroups:
90+
- kmm.sigs.x-k8s.io
91+
resources:
92+
- moduleimagesconfigs
93+
- nodemodulesconfigs
94+
verbs:
95+
- create
96+
- delete
97+
- get
98+
- list
99+
- patch
89100
- watch
90101
- apiGroups:
91102
- kmm.sigs.x-k8s.io
92103
resources:
93-
- modules/status
94-
- preflightvalidations/status
104+
- modules
95105
verbs:
96106
- get
107+
- list
97108
- patch
98109
- update
110+
- watch
99111
- apiGroups:
100112
- kmm.sigs.x-k8s.io
101113
resources:
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
/*
2+
Copyright 2022.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package controllers
18+
19+
import (
20+
"context"
21+
"errors"
22+
"fmt"
23+
24+
kmmv1beta1 "github.com/kubernetes-sigs/kernel-module-management/api/v1beta1"
25+
"github.com/kubernetes-sigs/kernel-module-management/internal/api"
26+
"github.com/kubernetes-sigs/kernel-module-management/internal/buildsign"
27+
"github.com/kubernetes-sigs/kernel-module-management/internal/kernel"
28+
"github.com/kubernetes-sigs/kernel-module-management/internal/mbsc"
29+
"github.com/kubernetes-sigs/kernel-module-management/internal/utils"
30+
v1 "k8s.io/api/core/v1"
31+
ctrl "sigs.k8s.io/controller-runtime"
32+
"sigs.k8s.io/controller-runtime/pkg/client"
33+
"sigs.k8s.io/controller-runtime/pkg/log"
34+
"sigs.k8s.io/controller-runtime/pkg/reconcile"
35+
)
36+
37+
const MBSCReconcilerName = "MBSCReconciler"
38+
39+
// mbscReconciler reconciles a ModuleBuldSignConfig object
40+
type mbscReconciler struct {
41+
reconHelperAPI mbscReconcilerHelperAPI
42+
}
43+
44+
func NewMBSCReconciler(
45+
client client.Client,
46+
buildSignAPI buildsign.Manager,
47+
mbscAPI mbsc.MBSC,
48+
) *mbscReconciler {
49+
reconHelperAPI := newMBSCReconcilerHelper(client, buildSignAPI, mbscAPI)
50+
return &mbscReconciler{
51+
reconHelperAPI: reconHelperAPI,
52+
}
53+
}
54+
55+
// SetupWithManager sets up the controller with the Manager.
56+
func (r *mbscReconciler) SetupWithManager(mgr ctrl.Manager, kernelLabel string) error {
57+
return ctrl.NewControllerManagedBy(mgr).
58+
For(&kmmv1beta1.ModuleBuildSignConfig{}).
59+
Owns(&v1.Pod{}).
60+
Named(MBSCReconcilerName).
61+
Complete(
62+
reconcile.AsReconciler[*kmmv1beta1.ModuleBuildSignConfig](mgr.GetClient(), r),
63+
)
64+
}
65+
66+
//+kubebuilder:rbac:groups=kmm.sigs.x-k8s.io,resources=modulebuildsignconfigs,verbs=get;list;watch;update;patch;create
67+
//+kubebuilder:rbac:groups=kmm.sigs.x-k8s.io,resources=modulebuildsignconfigs/status,verbs=get;update;patch
68+
//+kubebuilder:rbac:groups="core",resources=secrets,verbs=get;list;watch
69+
//+kubebuilder:rbac:groups="core",resources=configmaps,verbs=get;list;watch
70+
//+kubebuilder:rbac:groups="core",resources=pods,verbs=create;list;watch;delete
71+
72+
func (r *mbscReconciler) Reconcile(ctx context.Context, mbscObj *kmmv1beta1.ModuleBuildSignConfig) (ctrl.Result, error) {
73+
res := ctrl.Result{}
74+
75+
logger := log.FromContext(ctx)
76+
77+
if mbscObj.GetDeletionTimestamp() != nil {
78+
// [TODO] delete build/sign pods
79+
return res, nil
80+
}
81+
82+
err := r.reconHelperAPI.updateStatus(ctx, mbscObj)
83+
if err != nil {
84+
return res, fmt.Errorf("failed to update MSBC %s status based on the result of the builds: %v", mbscObj.Name, err)
85+
}
86+
87+
err = r.reconHelperAPI.processImagesSpecs(ctx, mbscObj)
88+
if err != nil {
89+
return res, fmt.Errorf("failed to process images of MSBC %s: %v", mbscObj.Name, err)
90+
}
91+
92+
logger.Info("run garbage collector for build/sign pods")
93+
err = r.reconHelperAPI.garbageCollect(ctx, mbscObj)
94+
if err != nil {
95+
return res, fmt.Errorf("failed to run garbage collector for MBSC %s: %v", mbscObj.Name, err)
96+
}
97+
98+
return res, nil
99+
}
100+
101+
//go:generate mockgen -source=mbsc_reconciler.go -package=controllers -destination=mock_mbsc_reconciler.go mbscReconcilerHelperAPI
102+
103+
type mbscReconcilerHelperAPI interface {
104+
updateStatus(ctx context.Context, mbscObj *kmmv1beta1.ModuleBuildSignConfig) error
105+
processImagesSpecs(ctx context.Context, mbscObj *kmmv1beta1.ModuleBuildSignConfig) error
106+
garbageCollect(ctx context.Context, mbscObj *kmmv1beta1.ModuleBuildSignConfig) error
107+
}
108+
109+
type mbscReconcilerHelper struct {
110+
client client.Client
111+
buildSignAPI buildsign.Manager
112+
mbscAPI mbsc.MBSC
113+
}
114+
115+
func newMBSCReconcilerHelper(client client.Client, buildSignAPI buildsign.Manager, mbscAPI mbsc.MBSC) mbscReconcilerHelperAPI {
116+
return &mbscReconcilerHelper{
117+
client: client,
118+
buildSignAPI: buildSignAPI,
119+
mbscAPI: mbscAPI,
120+
}
121+
}
122+
123+
func (mrh *mbscReconcilerHelper) updateStatus(ctx context.Context, mbscObj *kmmv1beta1.ModuleBuildSignConfig) error {
124+
errs := make([]error, 0, len(mbscObj.Spec.Images))
125+
patchFrom := client.MergeFrom(mbscObj.DeepCopy())
126+
for _, imageSpec := range mbscObj.Spec.Images {
127+
status, err := mrh.buildSignAPI.GetStatus(ctx, mbscObj.Name, mbscObj.Namespace, imageSpec.ModuleImageSpec.KernelVersion,
128+
imageSpec.Action, &mbscObj.ObjectMeta)
129+
if err != nil || status == kmmv1beta1.BuildOrSignStatus("") {
130+
// either we could not get the status or the status is empty
131+
errs = append(errs, err)
132+
continue
133+
}
134+
mrh.mbscAPI.SetImageStatus(mbscObj, imageSpec.Image, imageSpec.Action, status)
135+
}
136+
137+
err := mrh.client.Status().Patch(ctx, mbscObj, patchFrom)
138+
errs = append(errs, err)
139+
return errors.Join(errs...)
140+
}
141+
142+
func (mrh *mbscReconcilerHelper) processImagesSpecs(ctx context.Context, mbscObj *kmmv1beta1.ModuleBuildSignConfig) error {
143+
logger := log.FromContext(ctx)
144+
errs := make([]error, 0, len(mbscObj.Spec.Images))
145+
for _, imageSpec := range mbscObj.Spec.Images {
146+
imageStatus := mrh.mbscAPI.GetImageStatus(mbscObj, imageSpec.Image, imageSpec.Action)
147+
if imageStatus == kmmv1beta1.ActionSuccess {
148+
// in case action succeeded - skip to the next image. Otherwise, action had not been handled yet, or is being handled, or already failed.
149+
// in that case the Sync API will take care of what is needed to be done
150+
continue
151+
}
152+
mld := createMLD(mbscObj, &imageSpec.ModuleImageSpec)
153+
err := mrh.buildSignAPI.Sync(ctx, mld, true, &mbscObj.ObjectMeta, imageSpec.Action)
154+
if err != nil {
155+
errs = append(errs, err)
156+
logger.Info(utils.WarnString("sync for image %s, action %s failed: %v"), imageSpec.Image, imageSpec.Action, err)
157+
}
158+
}
159+
return errors.Join(errs...)
160+
}
161+
162+
func (mrh *mbscReconcilerHelper) garbageCollect(ctx context.Context, mbscObj *kmmv1beta1.ModuleBuildSignConfig) error {
163+
logger := log.FromContext(ctx)
164+
165+
// Garbage collect for successfully finished build pods
166+
deleted, err := mrh.buildSignAPI.GarbageCollect(ctx, mbscObj.Name, mbscObj.Namespace, kmmv1beta1.BuildImage, &mbscObj.ObjectMeta)
167+
if err != nil {
168+
return fmt.Errorf("could not garbage collect build objects: %v", err)
169+
}
170+
171+
logger.Info("Garbage-collected Build objects", "names", deleted)
172+
173+
// Garbage collect for successfully finished sign pods
174+
deleted, err = mrh.buildSignAPI.GarbageCollect(ctx, mbscObj.Name, mbscObj.Namespace, kmmv1beta1.SignImage, &mbscObj.ObjectMeta)
175+
if err != nil {
176+
return fmt.Errorf("could not garbage collect sign objects: %v", err)
177+
}
178+
179+
logger.Info("Garbage-collected Sign objects", "names", deleted)
180+
181+
return nil
182+
}
183+
184+
func createMLD(mbscObj *kmmv1beta1.ModuleBuildSignConfig, imageSpec *kmmv1beta1.ModuleImageSpec) *api.ModuleLoaderData {
185+
return &api.ModuleLoaderData{
186+
Name: mbscObj.Name,
187+
Namespace: mbscObj.Namespace,
188+
ContainerImage: imageSpec.Image,
189+
Build: imageSpec.Build,
190+
Sign: imageSpec.Sign,
191+
Owner: mbscObj,
192+
KernelVersion: imageSpec.KernelVersion,
193+
KernelNormalizedVersion: kernel.NormalizeVersion(imageSpec.KernelVersion),
194+
ImageRepoSecret: mbscObj.Spec.ImageRepoSecret,
195+
RegistryTLS: imageSpec.RegistryTLS,
196+
}
197+
}

0 commit comments

Comments
 (0)