-
Notifications
You must be signed in to change notification settings - Fork 74
Add trigger controller #1094
Add trigger controller #1094
Conversation
Skipping CI for Draft Pull Request. |
…rigger-controller
pkg/reconciler/broker/broker.go
Outdated
// TODO Maybe get rid of BrokerMutation and add Delete() and Upsert(broker) methods to TargetsConfig. Now we always | ||
// delete or update the entire broker entry and we don't need partial updates per trigger. | ||
// The code can be simplified to r.targetsConfig.Upsert(brokerConfigEntry) | ||
// First delete the broker entry. |
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 had written a targets config reconciler which supports the interface you want here and allows directly constructing the broker config proto rather than working with the mutation interface: #914. Directly constructing the proto is a bit nicer since we are not constrained to using the mutation interface and individual mutations do not need to be threadsafe. I had closed that since the brokercell reconciler was meant to replace this but maybe it is worth reviving after this PR is merged since the brokercell reconciler is not yet ready.
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.
Once we do #1054, we can start moving the target-config reconciliation to brokercell reconciler (assuming a static brokercell).
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 disagree that updating proto is better. Reconciler shouldn't worry about the internals of targets config. Again, I'm likely biased but just giving my voice.
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 am not sure I follow what do you mean by "internals" of targets config. Currently the UpsertTargets
interface already takes in a config.Target
object. What I am suggesting here is to add an interface to take in config.Broker
because now we don't need to upsert each trigger one by one, it's always all or nothing. If we think the config.Broker
proto is "internal", we can always add another abstraction but I don't think it's needed.
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.
config.Broker
is bit different from config.Target
IMO. The "internal" I'm referring to is the map in the config.Broker
. To construct a config.Broker
, you will have to "manually" create the map rather than having the lib handle that. On the other side, config.Target
is pure data.
var filterBroker = pkgreconciler.AnnotationFilterFunc(eventingv1beta1.BrokerClassAnnotationKey, brokerv1beta1.BrokerClass, false /*allowUnset*/) | ||
|
||
func NewController(ctx context.Context, cmw configmap.Watcher) *controller.Impl { | ||
// TODO initialize project ID here via env var or metadata. |
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 we want to support reconciling across multiple projects?
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 say no for now unless there are some compelling use cases. Do you have any use case in mind ?
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 haven't heard of a need for reconciling across multiple projects.
Notes for a future PR: Using an env var here makes tests more complicated. One option for setting project ID in this and other controllers is to add it to the context created in cmd/controller/main.go. Then controllers have a uniform way of getting the global project ID if they need it, and there's only one piece of code responsible for retrieving the project id from metadata or env var.
…rigger-controller
var filterBroker = pkgreconciler.AnnotationFilterFunc(eventingv1beta1.BrokerClassAnnotationKey, brokerv1beta1.BrokerClass, false /*allowUnset*/) | ||
|
||
func NewController(ctx context.Context, cmw configmap.Watcher) *controller.Impl { | ||
// TODO initialize project ID here via env var or metadata. |
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 haven't heard of a need for reconciling across multiple projects.
Notes for a future PR: Using an env var here makes tests more complicated. One option for setting project ID in this and other controllers is to add it to the context created in cmd/controller/main.go. Then controllers have a uniform way of getting the global project ID if they need it, and there's only one piece of code responsible for retrieving the project id from metadata or env var.
// Call Finalizer anyway in case the Trigger still holds GCP Broker related resources. | ||
// If a Trigger used to point to a GCP Broker but now has a Broker with a different brokerclass, | ||
// we should clean up resources related to GCP Broker. | ||
return r.FinalizeKind(ctx, t) |
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 a trigger is created for a broker that doesn't have this broker class, will the googlecloud
finalizer be added anyway? I think it's automatically added in genreconciler when FinalizeKind is present, before Reconcile is even called. So most likely every Trigger will have the googlecloud
finalizer even if they use another broker class.
I think that means that every trigger with a different broker class will be finalized on every update. The unit test of a trigger with a not found broker seems to confirm this (because it finalizes that trigger). Might want to confirm with a real-world test.
If that behavior is confirmed then we should disable the automatic finalizer logic in genreconciler (by renaming FinalizeKind). Then we can add the finalizer only to Triggers that point to a googlecloud broker.
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.
Your understanding is correct. I forgot to add a TODO here to explain the finalizer scenario and future improvements.
I think that means that every trigger with a different broker class will be finalized on every update.
Correct. This is unnecessary and it will also cause read operation on the topic and pull subscription.
we should disable the automatic finalizer logic in genreconciler (by renaming FinalizeKind).
Unfortunately if we do this, the FinalizeKind logic won't be called when the trigger object is deleted. The genreconciler will do nothing because it thinks there is no finalizer to call if the reconciler doesn't implement FinalizeKind.
I have thought about this and came up with a few options:
- The current behavior. Pros: least effort; Cons: unnecessary FinalizeKind calls for non-GCP broker.
- Use a custom controller instead of genreconciler. This essentially means we need to copy most of the genreconciler boil plate code and make some modifications.
- Upstream genreconciler changes to make it more flexible, specifically, add a
FilterKind
interface to let the genreconciler skip a trigger if it doesn't point to a GCP broker. I have proposed this interface before genreconciler should support Filtering knative/pkg#1149
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 personally prefer Option 3. If this sounds good to you, I will add a TODO for 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.
Dumb question: why would we reconcile such a trigger (trigger not pointing a gcp broker) in the first place? Broker in trigger spec is immutable.
Also for option 2, there might not be that much boilerplate code from just the FinalizeKind. We can still use the majority of the genreconciler.
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 would we reconcile such a trigger (trigger not pointing a gcp broker) in the first place? Broker in trigger spec is immutable.
Consider this scenario. A trigger was pointed to a gcp broker. Then the broker was updated to use a different brokerclass. Now we want to tear down trigger pubsub resources. We don't know if users will actually do this. But in theory they can.
We could do option 2 but I really don't like the trigger controller to be "special".
I don't think it's very high priority because: 1. users are likely to only use gcp broker. 2. even if they use a different broker, this results in a couple of unnecessary calls to pubsub. not great but doesn't really hurt too much.
For the above reasons I prefer to have a clean solution.
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 broker could be deleted and replaced with a broker with a different class. From the trigger controller's perspective, this will be the same as a broker changing class.
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.
Right it's immutable. But you can still delete a broker and recreate it with a different brokerclass.
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's fine to defer this for later. I'd love to end up at option 3, but realistically I'd probably attempt option 2 first, then move the new code upstream later. It will be easier to justify as an upstream option once we have a demonstrated solution.
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.
SG. Created an issue to follow up #1164
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.
Nothing blocking. Just an idea: if we can (or already?) label the trigger with the initial broker class, then even if the broker got recreated with a different class we can still handle that deterministically, right?
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.
Having a couple of questions
|
||
r.Logger.Info("Setting up event handlers") | ||
|
||
triggerInformer.Informer().AddEventHandlerWithResyncPeriod(controller.HandleAll(impl.Enqueue), reconciler.DefaultResyncPeriod) |
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 we need to filter on trigger label eventing.BrokerLabelKey
?
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.
No because we need to be able to reconcile orphaned triggers without a broker.
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.
When would that happen? It seems trigger spec broker and broker class are both immutable.
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.
Sorry let me clarify. Do mean filter on the existence of the label or actually check the broker is GCP broker?
Let me assume you meant the latter . If you delete a broker, then its triggers become orphaned. We'd like to be able to still delete the triggers (in this case reconcile is a noop).
// Call Finalizer anyway in case the Trigger still holds GCP Broker related resources. | ||
// If a Trigger used to point to a GCP Broker but now has a Broker with a different brokerclass, | ||
// we should clean up resources related to GCP Broker. | ||
return r.FinalizeKind(ctx, t) |
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.
Dumb question: why would we reconcile such a trigger (trigger not pointing a gcp broker) in the first place? Broker in trigger spec is immutable.
Also for option 2, there might not be that much boilerplate code from just the FinalizeKind. We can still use the majority of the genreconciler.
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.
/lgtm
/hold for @yolocs to take a look |
…ller should handle this
The following is the coverage report on the affected files.
|
/retest |
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.
/lgtm
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: grantr, liu-cong 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 |
/lgtm |
/unhold |
/retest |
The following jobs failed:
Job pull-google-knative-gcp-integration-tests expended all 3 retries without success. |
/retest |
Fixes #1053
I tried to reuse existing code as much as I can to reduce the amount of changes. I will have follow up PRs to do some cleanup and refactoring.
Proposed Changes
googlecloud
brokerclass, or they have thegooglecloud
finalizer.targets-config
reconciliation logicRelease Note
Docs