Skip to content

Commit cead385

Browse files
committed
webhook: mutate rook op csv if previeous csv had hostNetwork enabled
updated webhook to mutate rook-opearator csv if the previous rook-op csv had hostNetwork enabled for rook-op deployment Signed-off-by: Rohan Gupta <[email protected]>
1 parent f0955eb commit cead385

File tree

2 files changed

+90
-34
lines changed

2 files changed

+90
-34
lines changed

main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ func main() {
154154
os.Exit(1)
155155
}
156156

157-
if err = (&webhook.ClusterServiceVersionDeploymentScaler{
157+
if err = (&webhook.ClusterServiceVersionMutator{
158158
Client: mgr.GetClient(),
159159
Decoder: admission.NewDecoder(mgr.GetScheme()),
160160
OperatorNamespace: operatorNamespace,

webhook/csv.go

Lines changed: 89 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)