-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create a CSV webhook #516
base: main
Are you sure you want to change the base?
Create a CSV webhook #516
Conversation
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: iamniting The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
a57ca02
to
263ec5e
Compare
@@ -25,6 +25,7 @@ namePrefix: odf-operator- | |||
# endpoint w/o any authn/z, please comment the following line. | |||
patchesStrategicMerge: | |||
- manager_auth_proxy_patch.yaml | |||
- manager_webhook_patch.yaml |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this required?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It has webhook related changes port and volume details.
controllers/webhook.go
Outdated
csvWebhook := admrv1.MutatingWebhook{ | ||
Name: WebhookName, | ||
ClientConfig: admrv1.WebhookClientConfig{ | ||
Service: &admrv1.ServiceReference{ | ||
Name: WebhookServiceName, | ||
Path: ptr.To(odfwebhook.WebhookPath), | ||
Port: ptr.To(int32(443)), | ||
}, | ||
}, | ||
Rules: []admrv1.RuleWithOperations{ | ||
{ | ||
Rule: admrv1.Rule{ | ||
APIGroups: []string{"operators.coreos.com"}, | ||
APIVersions: []string{"v1alpha1"}, | ||
Resources: []string{"clusterserviceversions"}, | ||
Scope: ptr.To(admrv1.NamespacedScope), | ||
}, | ||
Operations: []admrv1.OperationType{admrv1.Create}, | ||
}, | ||
}, | ||
SideEffects: ptr.To(admrv1.SideEffectClassNone), | ||
TimeoutSeconds: ptr.To(int32(30)), | ||
AdmissionReviewVersions: []string{"v1"}, | ||
// fail the validation if webhook can't be reached | ||
FailurePolicy: ptr.To(admrv1.Fail), | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is recreated in every func invocation, why can't move this to a template and deep copy whatever is required?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added as a variable.
controllers/webhook.go
Outdated
webhookService := corev1.Service{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: WebhookServiceName, | ||
Namespace: operatorNamespace, | ||
}, | ||
Spec: corev1.ServiceSpec{ | ||
Ports: []corev1.ServicePort{ | ||
{ | ||
Name: "https", | ||
Port: 443, | ||
Protocol: corev1.ProtocolTCP, | ||
TargetPort: intstr.FromInt32(9443), | ||
}, | ||
}, | ||
Selector: map[string]string{ | ||
"app.kubernetes.io/name": "odf-operator", | ||
}, | ||
Type: corev1.ServiceTypeClusterIP, | ||
}, | ||
} | ||
|
||
svc := &corev1.Service{ | ||
ObjectMeta: webhookService.ObjectMeta, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is recreated in every func invocation, why can't move this to a template and deep copy whatever is required?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added as a variable.
does this PR needs a push? where are you registering the webhook? |
No it is getting created in |
|
295aff4
to
0b0498b
Compare
I fixed it, It was missed, It is called in the main. |
eaf99a2
to
94351a1
Compare
kind: Service | ||
metadata: | ||
annotations: | ||
service.beta.openshift.io/serving-cert-secret-name: webhook-server-cert |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better to have a prefix for this secret as well as other operators could be using generic names.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
renamed it to odf-operator-webhook-server-cert
- get | ||
- list | ||
- update | ||
- watch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we also need delete perms to delete the webhook upon DF uninstallation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Who will delete this? We can not even have an owner ref added to the webhook.
func(ctx context.Context, obj client.Object) []reconcile.Request { | ||
logger := log.FromContext(ctx) | ||
ssList := &odfv1alpha1.StorageSystemList{} | ||
err := r.Client.List(ctx, ssList, &client.ListOptions{Namespace: r.OperatorNamespace}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
err := r.Client.List(ctx, ssList, &client.ListOptions{Namespace: r.OperatorNamespace}) | |
err := r.Client.List(ctx, ssList, client.InNamespace(r.OperatorNamespace) |
i think using cmd construction options is more ergonomically
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
if err != nil { | ||
return ctrl.Result{}, err | ||
} | ||
|
||
err = r.ensureSubscriptions(logger, req.NamespacedName.Namespace) | ||
err = ensureWebhook(r.ctx, r.Client, logger, r.OperatorNamespace) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is webhook deployment in two controllers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Subscriptions are handled from these 2 controllers. any of these can be triggered first, and we need to make sure we have the webhook before subscriptions.
err := mgr.Add(manager.RunnableFunc(func(ctx context.Context) error { | ||
|
||
logger := log.FromContext(ctx) | ||
err := ensureWebhook(ctx, r.Client, logger, r.OperatorNamespace) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
third instance of same reconcile function, Runnable runs in parallel to all reconcilers and doesn't have any priority afair.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should not cause any issues i believe, This was created so that even if we hit other issues, we still create the webhook and odf-deps subs.
WebhookPath = "/mutate-operators-coreos-com-v1alpha1-csv" | ||
) | ||
|
||
var ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
vars' declared here should form a template w/ a facility to change the names and fill the info dynamically during reconcile.
better have only servicespec here and in webhook no name, namespace selector which'll be replaced in a single place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What will be the benefits of that?
return admission.PatchResponseFromRaw(req.Object.Raw, marshaledInstance) | ||
} | ||
|
||
func (r *ClusterServiceVersionDefaulter) getOldCsvReplicas(instance *opv1a1.ClusterServiceVersion) (int32, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rather than instance
, csv
is more discoverable as param var.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i would prefer instance, because that is being used and created by scaffolding mostly at controller layers.
webhook/csv.go
Outdated
} | ||
|
||
for _, pkgName := range controllers.PkgNames { | ||
if strings.HasPrefix(instance.ObjectMeta.Name, pkgName) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ObjectMeta and TypeMeta is embedded into the struct and could directly use .Name
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
return 0, nil | ||
} | ||
|
||
func (r *ClusterServiceVersionDefaulter) mutateCsv(instance *opv1a1.ClusterServiceVersion, replicas *int32) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we need a func here, this is neither a single unit nor being called multiple times.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This func is the place where all the changes are made to the csv. This func is called Default in scafolding. It is also easy to track that what and where changes are made to the csv.
|
||
func (r *ClusterServiceVersionDefaulter) getOldCsvReplicas(instance *opv1a1.ClusterServiceVersion) (int32, error) { | ||
|
||
if instance.Spec.Replaces == "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so this is a new operator from this release and should we also check if we have the name/package in our records or else this will always stay scaled down?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it is a new package, we should scale down by default, We should scale it up by the controller if needed.
Signed-off-by: Nitin Goyal <nigoyal@redhat.com>
Signed-off-by: Nitin Goyal <nigoyal@redhat.com>
Signed-off-by: Nitin Goyal <nigoyal@redhat.com>
Signed-off-by: Nitin Goyal <nigoyal@redhat.com>
@iamniting: The following tests failed, say
Full PR test history. Your PR dashboard. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here. |
Signed-off-by: Nitin Goyal nigoyal@redhat.com