@@ -2,11 +2,18 @@ package buildsign
22
33import (
44 "context"
5+ "errors"
6+ "fmt"
57
68 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9+ "k8s.io/apimachinery/pkg/runtime"
10+ "sigs.k8s.io/controller-runtime/pkg/client"
711
812 kmmv1beta1 "github.com/kubernetes-sigs/kernel-module-management/api/v1beta1"
913 "github.com/kubernetes-sigs/kernel-module-management/internal/api"
14+ "github.com/kubernetes-sigs/kernel-module-management/internal/kernel"
15+ "github.com/kubernetes-sigs/kernel-module-management/internal/utils"
16+ "sigs.k8s.io/controller-runtime/pkg/log"
1017)
1118
1219//go:generate mockgen -source=manager.go -package=buildsign -destination=mock_manager.go
@@ -17,3 +24,129 @@ type Manager interface {
1724 Sync (ctx context.Context , mld * api.ModuleLoaderData , pushImage bool , action kmmv1beta1.BuildOrSignAction , owner metav1.Object ) error
1825 GarbageCollect (ctx context.Context , name , namespace string , action kmmv1beta1.BuildOrSignAction , owner metav1.Object ) ([]string , error )
1926}
27+
28+ type manager struct {
29+ client client.Client
30+ resourceManager ResourceManager
31+ }
32+
33+ func NewManager (client client.Client , resourceManager ResourceManager , scheme * runtime.Scheme ) Manager {
34+ return & manager {
35+ client : client ,
36+ resourceManager : resourceManager ,
37+ }
38+ }
39+
40+ func (m * manager ) GetStatus (ctx context.Context , name , namespace , kernelVersion string ,
41+ action kmmv1beta1.BuildOrSignAction , owner metav1.Object ) (kmmv1beta1.BuildOrSignStatus , error ) {
42+
43+ normalizedKernel := kernel .NormalizeVersion (kernelVersion )
44+ foundResource , err := m .resourceManager .GetResourceByKernel (ctx , name , namespace , normalizedKernel , action , owner )
45+ if err != nil {
46+ if ! errors .Is (err , ErrNoMatchingBuildSignResource ) {
47+ return kmmv1beta1 .BuildOrSignStatus ("" ), fmt .Errorf ("failed to get resource %s/%s, action %s: %v" ,
48+ namespace , name , action , err )
49+ }
50+ return kmmv1beta1 .BuildOrSignStatus ("" ), nil
51+ }
52+ status , err := m .resourceManager .GetResourceStatus (foundResource )
53+ if err != nil {
54+ return kmmv1beta1 .BuildOrSignStatus ("" ), fmt .Errorf ("failed to get status for the resource %s/%s, action %s: %v" ,
55+ foundResource .GetNamespace (), foundResource .GetName (), action , err )
56+ }
57+ switch status {
58+ case StatusCompleted :
59+ return kmmv1beta1 .ActionSuccess , nil
60+ case StatusFailed :
61+ return kmmv1beta1 .ActionFailure , nil
62+ }
63+
64+ // any other status means the resource is still not finished, returning empty status
65+ return kmmv1beta1 .BuildOrSignStatus ("" ), nil
66+ }
67+
68+ func (m * manager ) Sync (ctx context.Context , mld * api.ModuleLoaderData , pushImage bool , action kmmv1beta1.BuildOrSignAction ,
69+ owner metav1.Object ) error {
70+
71+ logger := log .FromContext (ctx )
72+ var (
73+ resourceTemplate metav1.Object
74+ err error
75+ )
76+ switch action {
77+ case kmmv1beta1 .BuildImage :
78+ logger .Info ("Building in-cluster" )
79+ resourceTemplate , err = m .resourceManager .MakeBuildTemplate (ctx , mld , owner , pushImage )
80+ case kmmv1beta1 .SignImage :
81+ logger .Info ("Signing in-cluster" )
82+ resourceTemplate , err = m .resourceManager .MakeSignTemplate (ctx , mld , owner , pushImage )
83+ default :
84+ return fmt .Errorf ("invalid action %s" , action )
85+ }
86+
87+ if err != nil {
88+ return fmt .Errorf ("could not make the resource's template template: %v" , err )
89+ }
90+
91+ resource , err := m .resourceManager .GetResourceByKernel (ctx , mld .Name , mld .Namespace , mld .KernelNormalizedVersion ,
92+ action , owner )
93+
94+ if err != nil {
95+ if ! errors .Is (err , ErrNoMatchingBuildSignResource ) {
96+ return fmt .Errorf ("error getting the %s resource: %v" , action , err )
97+ }
98+
99+ logger .Info ("Creating resource" )
100+ err = m .resourceManager .CreateResource (ctx , resourceTemplate )
101+ if err != nil {
102+ return fmt .Errorf ("could not create resource: %v" , err )
103+ }
104+
105+ return nil
106+ }
107+
108+ changed , err := m .resourceManager .IsResourceChanged (resource , resourceTemplate )
109+ if err != nil {
110+ return fmt .Errorf ("could not determine if the resource has changed: %v" , err )
111+ }
112+
113+ if changed {
114+ logger .Info ("The module's spec has been changed, deleting the current resource so a new one can be created" ,
115+ "name" , resource .GetName (), "action" , action )
116+ err = m .resourceManager .DeleteResource (ctx , resource )
117+ if err != nil {
118+ logger .Info (utils .WarnString (fmt .Sprintf ("failed to delete %s resource %s: %v" , action , resource .GetName (), err )))
119+ }
120+ }
121+
122+ return nil
123+ }
124+
125+ func (m * manager ) GarbageCollect (ctx context.Context , name , namespace string , action kmmv1beta1.BuildOrSignAction ,
126+ owner metav1.Object ) ([]string , error ) {
127+
128+ resources , err := m .resourceManager .GetModuleResources (ctx , name , namespace , action , owner )
129+ if err != nil {
130+ return nil , fmt .Errorf ("failed to get %s resources for mbsc %s/%s: %v" , action , namespace , name , err )
131+ }
132+
133+ logger := log .FromContext (ctx )
134+ errs := make ([]error , 0 , len (resources ))
135+ deleteResourceNames := make ([]string , 0 , len (resources ))
136+ for _ , obj := range resources {
137+ isPhaseSucceed , err := m .resourceManager .HasResourcesCompletedSuccessfully (ctx , obj )
138+ if err != nil {
139+ return nil , fmt .Errorf ("failed to check if resource %s succeeded: %v" , obj .GetName (), err )
140+ }
141+ if isPhaseSucceed {
142+ err = m .resourceManager .DeleteResource (ctx , obj )
143+ errs = append (errs , err )
144+ if err != nil {
145+ logger .Info (utils .WarnString ("failed to delete %s resource %s in garbage collection: %v" ), action , obj .GetName (), err )
146+ continue
147+ }
148+ deleteResourceNames = append (deleteResourceNames , obj .GetName ())
149+ }
150+ }
151+ return deleteResourceNames , errors .Join (errs ... )
152+ }
0 commit comments