@@ -36,7 +36,7 @@ import (
3636 "github.com/red-hat-storage/odf-operator/controllers"
3737)
3838
39- type ClusterServiceVersionDeploymentScaler struct {
39+ type ClusterServiceVersionMutator struct {
4040 client.Client
4141
4242 Decoder admission.Decoder
@@ -45,12 +45,13 @@ type ClusterServiceVersionDeploymentScaler struct {
4545 odfOperatorConfigAccessMutex sync.Mutex
4646 odfOperatorConfigMapResourceVersion string
4747 odfOwnedCsvNames map [string ]bool
48+ rookOperatorCsvName string
4849}
4950
5051//+kubebuilder:rbac:groups=operators.coreos.com,resources=clusterserviceversions,verbs=get;patch
5152//+kubebuilder:rbac:groups="",resources=configmaps,verbs=get
5253
53- func (r * ClusterServiceVersionDeploymentScaler ) Handle (ctx context.Context , req admission.Request ) admission.Response {
54+ func (r * ClusterServiceVersionMutator ) Handle (ctx context.Context , req admission.Request ) admission.Response {
5455
5556 logger := log .FromContext (ctx )
5657 logger .Info ("request received for csv review" )
@@ -66,23 +67,37 @@ func (r *ClusterServiceVersionDeploymentScaler) Handle(ctx context.Context, req
6667 return admission .Errored (http .StatusInternalServerError , fmt .Errorf ("failed to build config: %v" , err ))
6768 }
6869
69- if ok := r .isCsvManagedByOdf (csv ); ! ok {
70- logger .Info ("ignoring csv as it is not a csv managed by ODF" )
71- return admission .Allowed ("csv is not managed by ODF" )
72- }
70+ mutate := false
7371
74- running , err := r .isPreviousCsvHasRunningDeployments (ctx , logger , csv )
75- if err != nil {
76- logger .Error (err , "failed getting replicas from csv" )
77- return admission .Errored (http .StatusInternalServerError , fmt .Errorf ("failed getting replicas from csv: %v" , err ))
72+ if r .isCsvManagedByOdf (csv ) {
73+ running , err := r .isPreviousCsvHasRunningDeployments (ctx , logger , csv )
74+ if err != nil {
75+ logger .Error (err , "failed getting replicas from csv" )
76+ return admission .Errored (http .StatusInternalServerError , fmt .Errorf ("failed getting replicas from csv: %v" , err ))
77+ }
78+ if ! running {
79+ r .scaleDownCsvDeployments (logger , csv )
80+ mutate = true
81+ }
7882 }
7983
80- if running {
81- logger .Info ("ignoring csv as the previous csv deployments are running" )
82- return admission .Allowed ("previous csv deployments are running" )
84+ if csv .Name == r .rookOperatorCsvName {
85+ hostNetwork , err := r .isPreviousRookCsvHasHostNetwork (ctx , logger , csv )
86+ if err != nil {
87+ logger .Error (err , "failed checking previous rook csv hostNetwork" )
88+ return admission .Errored (http .StatusInternalServerError , fmt .Errorf ("failed checking previous rook csv hostNetwork: %v" , err ))
89+ }
90+ if hostNetwork {
91+ logger .Info ("mutating csv: enabling hostNetwork for rook operator" )
92+ r .enableHostNetworkOnRookOperator (csv )
93+ mutate = true
94+ }
8395 }
8496
85- r .scaleDownCsvDeployments (logger , csv )
97+ if ! mutate {
98+ logger .Info ("ignoring csv as no mutation required" )
99+ return admission .Allowed ("no csv mutation required" )
100+ }
86101
87102 marshaledCsv , err := json .Marshal (csv )
88103 if err != nil {
@@ -93,7 +108,7 @@ func (r *ClusterServiceVersionDeploymentScaler) Handle(ctx context.Context, req
93108 return admission .PatchResponseFromRaw (req .Object .Raw , marshaledCsv )
94109}
95110
96- func (r * ClusterServiceVersionDeploymentScaler ) loadOdfConfigMapData (ctx context.Context , logger logr.Logger ) error {
111+ func (r * ClusterServiceVersionMutator ) loadOdfConfigMapData (ctx context.Context , logger logr.Logger ) error {
97112
98113 configmap , err := controllers .GetOdfConfigMap (ctx , r .Client , logger )
99114 if err != nil {
@@ -113,6 +128,9 @@ func (r *ClusterServiceVersionDeploymentScaler) loadOdfConfigMapData(ctx context
113128 logger .Info ("skipping the record from the configmap" , "key" , key , "value" , rawValue )
114129 return
115130 }
131+ if record .Pkg == "rook-ceph-operator" {
132+ r .rookOperatorCsvName = record .Csv
133+ }
116134
117135 r .odfOwnedCsvNames [record .Csv ] = true
118136 })
@@ -123,25 +141,16 @@ func (r *ClusterServiceVersionDeploymentScaler) loadOdfConfigMapData(ctx context
123141 return nil
124142}
125143
126- func (r * ClusterServiceVersionDeploymentScaler ) isPreviousCsvHasRunningDeployments (ctx context.Context , logger logr.Logger , csv * opv1a1.ClusterServiceVersion ) (bool , error ) {
127-
128- if csv . Spec . Replaces == "" {
129- logger .Info ( "csv.Spec.Replaces is not populated " )
130- return false , nil
144+ func (r * ClusterServiceVersionMutator ) isPreviousCsvHasRunningDeployments (ctx context.Context , logger logr.Logger , csv * opv1a1.ClusterServiceVersion ) (bool , error ) {
145+ deployments , err := r . getDeploymentsFromPreviousCsv ( ctx , logger , csv )
146+ if err != nil {
147+ logger .Error ( err , "failed getting previous csv deployments " )
148+ return false , err
131149 }
132-
133- prevCsv := & opv1a1.ClusterServiceVersion {}
134- key := client.ObjectKey {Name : csv .Spec .Replaces , Namespace : csv .Namespace }
135-
136- if err := r .Client .Get (ctx , key , prevCsv ); errors .IsNotFound (err ) {
137- // new install where an previous csv does not exists
150+ if len (deployments ) == 0 {
138151 return false , nil
139- } else if err != nil {
140- logger .Error (err , "failed getting previous csv" )
141- return false , err
142152 }
143153
144- deployments := prevCsv .Spec .InstallStrategy .StrategySpec .DeploymentSpecs
145154 for i := range deployments {
146155 deployment := & deployments [i ]
147156 if deployment .Spec .Replicas == nil || * deployment .Spec .Replicas > 0 {
@@ -154,7 +163,7 @@ func (r *ClusterServiceVersionDeploymentScaler) isPreviousCsvHasRunningDeploymen
154163 return false , nil
155164}
156165
157- func (r * ClusterServiceVersionDeploymentScaler ) scaleDownCsvDeployments (logger logr.Logger , csv * opv1a1.ClusterServiceVersion ) {
166+ func (r * ClusterServiceVersionMutator ) scaleDownCsvDeployments (logger logr.Logger , csv * opv1a1.ClusterServiceVersion ) {
158167
159168 logger .Info ("mutating requested csv" )
160169
@@ -163,12 +172,59 @@ func (r *ClusterServiceVersionDeploymentScaler) scaleDownCsvDeployments(logger l
163172 }
164173}
165174
166- func (r * ClusterServiceVersionDeploymentScaler ) isCsvManagedByOdf (csv * opv1a1.ClusterServiceVersion ) bool {
175+ func (r * ClusterServiceVersionMutator ) isPreviousRookCsvHasHostNetwork (ctx context.Context , logger logr.Logger , csv * opv1a1.ClusterServiceVersion ) (bool , error ) {
176+ deployments , err := r .getDeploymentsFromPreviousCsv (ctx , logger , csv )
177+ if err != nil {
178+ logger .Error (err , "failed getting previous csv deployments" )
179+ return false , err
180+ }
181+ if len (deployments ) == 0 {
182+ logger .Info ("no previous deployments found" )
183+ return false , nil
184+ }
185+ for i := range deployments {
186+ deployment := & deployments [i ]
187+ if deployment .Name == "rook-ceph-operator" && deployment .Spec .Template .Spec .HostNetwork {
188+ return true , nil
189+ }
190+ }
191+
192+ return false , nil
193+ }
194+
195+ func (r * ClusterServiceVersionMutator ) enableHostNetworkOnRookOperator (csv * opv1a1.ClusterServiceVersion ) {
196+ for i := range csv .Spec .InstallStrategy .StrategySpec .DeploymentSpecs {
197+ csv .Spec .InstallStrategy .StrategySpec .DeploymentSpecs [i ].Spec .Template .Spec .HostNetwork = true
198+ }
199+ }
200+
201+ func (r * ClusterServiceVersionMutator ) getDeploymentsFromPreviousCsv (ctx context.Context , logger logr.Logger , csv * opv1a1.ClusterServiceVersion ) ([]opv1a1.StrategyDeploymentSpec , error ) {
202+ if csv .Spec .Replaces == "" {
203+ logger .Info ("csv.Spec.Replaces is not populated" )
204+ return nil , nil
205+ }
206+
207+ prevCsv := & opv1a1.ClusterServiceVersion {}
208+ key := client.ObjectKey {Name : csv .Spec .Replaces , Namespace : csv .Namespace }
209+
210+ if err := r .Client .Get (ctx , key , prevCsv ); errors .IsNotFound (err ) {
211+ // new install where an previous csv does not exists
212+ return nil , nil
213+ } else if err != nil {
214+ logger .Error (err , "failed getting previous csv" )
215+ return nil , err
216+ }
217+
218+ return prevCsv .Spec .InstallStrategy .StrategySpec .DeploymentSpecs , nil
219+
220+ }
221+
222+ func (r * ClusterServiceVersionMutator ) isCsvManagedByOdf (csv * opv1a1.ClusterServiceVersion ) bool {
167223
168224 return r .odfOwnedCsvNames [csv .Name ]
169225}
170226
171- func (r * ClusterServiceVersionDeploymentScaler ) SetupWebhookWithManager (mgr ctrl.Manager ) error {
227+ func (r * ClusterServiceVersionMutator ) SetupWebhookWithManager (mgr ctrl.Manager ) error {
172228
173229 mgr .GetWebhookServer ().Register (controllers .CsvWebhookPath , & webhook.Admission {Handler : r })
174230
0 commit comments