-
Notifications
You must be signed in to change notification settings - Fork 62
✨ Add support for installing bundles with webhooks #1914
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
base: main
Are you sure you want to change the base?
Conversation
✅ Deploy Preview for olmv1 ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1914 +/- ##
==========================================
+ Coverage 66.77% 68.35% +1.57%
==========================================
Files 75 76 +1
Lines 6335 6806 +471
==========================================
+ Hits 4230 4652 +422
- Misses 1841 1874 +33
- Partials 264 280 +16
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
94e5940
to
af66253
Compare
APIVersion: admissionregistrationv1.SchemeGroupVersion.String(), | ||
}, | ||
ObjectMeta: metav1.ObjectMeta{ | ||
GenerateName: fmt.Sprintf("%s-", generateName), |
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.
Using GenerateName
is what OLMv0 does, correct? I think it does this so that multiple validating/mutating webhook configuration objects can be created when own/single namespace bundles are installed multiple times.
That is an anti-goal for OLMv1, so perhaps it makes sense to deviate from OLMv0's use of GenerateName
in this case.
Unless there is a really strong reason not to, I'd prefer to use a deterministic name here instead, as that would ultimately make the set of on-cluster objects deterministic as well. I'm sure there are many benefits, but one that comes to mind is that ClusterExtension SAs would be able to specify the deterministic name in advance when setting up RBAC for get/update/patch/delete
verbs with the correct resourceName
.
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.
Another benefit: using a deterministic name here means that this webhook can only be installed once, regardless of the install modes supported by the extension. That is directly in line with one of the stated invariants of OLMv1 (no two cluster extensions can manage the same object)
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've changed it to use Name
instead. I'm trying to think if there's foot gun potential. I might be a little more defensive here and ensure that any -
suffix is removed from what is defined in the CSV to avoid any bad name errors.
We might already, but I'll double check and ensure that all webhook names defined in the CSV (for a particular type of webhook) are unique.
I guess if there is a naming clash, i.e. two different bundles call their webhook "my-webhook", the user can just install the bundle in another namespace as an escape hatch...wdyt?
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, now I understand better the @joelanford recommendation/idea: https://redhat-internal.slack.com/archives/C0881N26CGP/p1745960594662879?thread_ts=1745942335.360109&cid=C0881N26CGP
I am OK with since in OLMv1 we should have one instance of each project only the cluster
👍
@@ -17,6 +19,21 @@ func ObjectNameForBaseAndSuffix(base string, suffix string) string { | |||
return fmt.Sprintf("%s-%s", base, suffix) | |||
} | |||
|
|||
func ToUnstructured(obj client.Object) (*unstructured.Unstructured, error) { | |||
gvk := obj.GetObjectKind().GroupVersionKind() |
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.
A client.Object
is not guaranteed to have a populated GVK. If we need guarantees about setting the GVK on the unstructured type, we should also pass in a scheme so that we can lookup the GVK based on the object type.
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.
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.
For now, I've just hardened it by checking if version and kind are empty. I don't think we need to add the complexity of passing a scheme. At least not for now =D
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 we want the GKV and use it is the right approach then, I think we should use the controller-runtime implementation to do so ( GVKForObject ): https://github.com/kubernetes-sigs/controller-runtime/blob/main/pkg/client/apiutil/apimachinery.go#L95C6-L95C18
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 don't think we need it right now. The precondition for the function is that the client.Object will carry the GVK. If not, then error. But, I'd say check how we're using it in this PR and let me know if that's not the right way to create an object with GVK.
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.
Do you think that's acceptable since we only use it with CertManager? That way, we'll have the GKV. Is that what you were thinking?
af66253
to
165086d
Compare
@@ -13,6 +13,7 @@ const ( | |||
// Ex: SomeFeature featuregate.Feature = "SomeFeature" | |||
PreflightPermissions featuregate.Feature = "PreflightPermissions" | |||
SingleOwnNamespaceInstallSupport featuregate.Feature = "SingleOwnNamespaceInstallSupport" | |||
WebhookSupport featuregate.Feature = "WebhookSupport" |
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 we want to add support for new providers later, how do you envision that looking from a feature gate standpoint?
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.
From what I understand, downstream will use a different provider, but the implementation remains the same.
I don’t see a strong need to support multiple providers upstream for now — downstream will likely stick with one as well. Since this is under an alpha flag, we have flexibility to adjust later.
So I think this is fine as-is and no need to optimize prematurely. We can revisit if we decide to support more providers in the future.
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 great! My only open question (that I already left in a code comment) is how we would introduce more certificate providers in the future?
Presumably we'd want a feature gate per provider, so that each provider could mature independently? If so, should we have CertManagerWebhookSupport
for the current feature gate name?
I don't think we have to answer that question or change what we've got in the PR right now, so approving!
0d8545d
to
8e6b15e
Compare
8e6b15e
to
eed9c38
Compare
Signed-off-by: Per Goncalves da Silva <[email protected]>
Signed-off-by: Per Goncalves da Silva <[email protected]>
Signed-off-by: Per Goncalves da Silva <[email protected]>
Signed-off-by: Per Goncalves da Silva <[email protected]>
Signed-off-by: Per Goncalves da Silva <[email protected]>
eed9c38
to
3cebd58
Compare
if _, ok := webhookNameSetByType[wh.Type]; !ok { | ||
webhookNameSetByType[wh.Type] = sets.Set[string]{} | ||
} | ||
if webhookNameSetByType[wh.Type].Has(wh.GenerateName) { |
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.
Hi @perdasilva
we would need to do more checks than that:
- The name cannot have more than : 253-character limit
- The name need to be a valid DNS name;
We can use apimachinery to verify if is valid with: https://pkg.go.dev/k8s.io/apimachinery/pkg/util/validation#IsDNS1123Subdomain
So, it seems to be missing in the validator.
Could we please add this check?
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 can add it. But, I think a better approach would be (if it's possible) to validate the csv against its openapi schema. But I don't know that there's a simple way to do that =S
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 did we do in operator-sdk? Do we have any bundle validation code/library we can rip out from that?
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 can add it. But, I think a better approach would be (if it's possible) to validate the csv against its openapi schema. But I don't know that there's a simple way to do that =S
That is definitely a nice idea. 👍
We’d need to try using the markers for validation: https://book.kubebuilder.io/reference/markers/crd-validation
Add the annotations and re-generate the CRDs where the types are defined.
I think it would be something like
// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
// +kubebuilder:validation:MaxLength=253
// +kubebuilder:validation:MinLength=1
what did we do in operator-sdk? Do we have any bundle validation code/library we can rip out from that?
I think we should consider checking this at runtime, since currently it isn’t validated. But, maybe it's a bit of an overstatement, though—if the name is invalid, the same check used by k8s.io/apimachinery/pkg/util/validation (IsDNS1123Subdomain) will be enforced by Kubernetes itself.
In the past, we used IsDNS1123Subdomain for scaffolding in the SDK (see: https://github.com/operator-framework/operator-sdk/pull/953/files). The SDK uses Kubebuilder, and in Kubebuilder we also rely on the same validation logic (we just copied it to avoid adding a dependency). See; https://github.com/search?q=repo%3Akubernetes-sigs%2Fkubebuilder%20IsDNS1123Subdomain&type=code
If we decide to add the check then, IMO the best approach is to use the checks from k8s.io/apimachinery/pkg/util/validation instead any internal lib.
@@ -0,0 +1,122 @@ | |||
package render_test |
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.
Could we just add an e2e test before merging, or at plan to do so in a follow-up?
We might be able to reuse something from here:
https://github.com/search?q=repo%3Ak8s-operatorhub%2Fcommunity-operators%20generateName&type=code
(Since we’re using real operators) — this could help validate that the webhooks are working correctly.
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.
Everything looks great to me! 👍
Awesome work 🥇
Just one thought: I think it would be valuable to have some e2e tests covering install/upgrade scenarios with webhooks.
Do you think we could add those before merging? Or, since the feature is behind a flag, maybe we could make sure to cover that in a follow-up?
Other small nits (nice-to-haves): #1914 (comment)
Aside from that, I'm all good with it.
/lgtm
/approved
Description
Depends on #1893
Adds webhook support to bundle renderer with certificate management. Based on Joe's PoC #1506
Only the cert-manager provisioner is implemented in this PR. In a follow up, we'll add the openshift-serviceca provisioner and a way to configure OLM for one or the other.
Reviewer Checklist