Skip to content
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

Invert the relationship between controller.Base and derivatives. #1770

Merged
merged 2 commits into from
Aug 1, 2018

Conversation

mattmoor
Copy link
Member

The way we use controller.Base today is very reminiscent of OOP; it is effectively trying to be a base class, and many things are painful trying to write this way in Go (e.g. we cannot simply make Reconcile an abstract method to be implemented by derivatives).

With this change, we will instead move to a model where Base becomes Impl and takes an instance of the following interface:

package controller

type Reconciler interface {
  Reconcile(key string) error
}

In this model, controller.Impl is the single shared controller implementation, and the NewController methods become responsible for instantiating it with the appropriate implementation of Reconciler and wiring the appropriate events up via the informers.

This cleans up the separation between ./pkg/controller and ./pkg/controller/foo, and will hopefully start to make the latter quite small. The plan is to share the former via knative/pkg in a subsequent change. I'm debating followup changes such as moving to a ./pkg/reconciler/foo structure, once only Reconcilers live in this repo.

Fixes: #1505

cc @evankanderson @vaikas-google @n3wscott @grantr @imjasonh

@google-prow-robot google-prow-robot added approved Indicates a PR has been approved by an approver from all required OWNERS files. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Jul 31, 2018
@dprotaso
Copy link
Member

dprotaso commented Jul 31, 2018 via email

@mattmoor
Copy link
Member Author

These test failures are quite weird, I wonder if I need to rebase or something...

@mattmoor
Copy link
Member Author

Oh yeah, Chen's change....

The way we use `controller.Base` today is very reminiscent of OOP; it is effectively trying to be a base class, and many things are painful trying to write this way in Go (e.g. we cannot simply make `Reconcile` an abstract method to be implemented by derivatives).

With this change, we will instead move to a model where `Base` becomes `Impl` and takes an instance of the following interface:
```go
package controller

type Reconciler interface {
  Reconcile(key string) error
}
```

In this model, `controller.Impl` is the single shared controller implementation, and the `NewController` methods become responsible for instantiating it with the appropriate implementation of `Reconciler` and wiring the appropriate events up via the informers.

This cleans up the separation between `./pkg/controller` and `./pkg/controller/foo`, and will hopefully start to make the latter quite small.  Ultimately the plan is to share the former via `knative/pkg`.

Fixes: knative#1505
@mattmoor
Copy link
Member Author

mattmoor commented Aug 1, 2018

/test pull-knative-serving-integration-tests

mattmoor added a commit to mattmoor/pkg that referenced this pull request Aug 1, 2018
The `controller.go` is from: knative/serving#1770, however, this adds 100% coverage of `controller.go`, which we have been missing in `knative/serving`.

Fixes: knative#8
@mattmoor
Copy link
Member Author

mattmoor commented Aug 1, 2018

FWIW, I also have knative/pkg#33 in flight, which adds 100% coverage of controller.go. I didn't bother adding it here because we don't have any tests for it today, and the plan was to move it anyways.

@mattmoor
Copy link
Member Author

mattmoor commented Aug 1, 2018

I think that (in the move to knative/pkg) I am going to add a context.Context to the Reconcile() signature. I find having context.TODO() sprinkled everywhere to be a bit of an eyesore. This will also let us pass the logkey to NewBase and share code like this:

// loggerWithServiceInfo enriches the logs with service name and namespace.
func loggerWithServiceInfo(logger *zap.SugaredLogger, ns string, name string) *zap.SugaredLogger {
	return logger.With(zap.String(commonlogkey.Namespace, ns), zap.String(logkey.Service, name))
}

and this:

	// Wrap our logger with the additional context of the configuration that we are reconciling.
	logger := loggerWithServiceInfo(c.Logger, namespace, name)
	ctx := logging.WithLogger(context.TODO(), logger)

I may then also make the Logger on the Base Reconciler private, so that folks access it through the context.Context. Thoughts?

mattmoor added a commit to mattmoor/pkg that referenced this pull request Aug 1, 2018
The `controller.go` is from: knative/serving#1770, however, this adds 100% coverage of `controller.go`, which we have been missing in `knative/serving`.

This also adds a `context.Context` to the `Reconcile` signature, to enable better sharing of logger setup across controllers.

Fixes: knative#8
syncHandler func(string) error,
controllerName string) error {

func (c *Impl) Run(threadiness int, stopCh <-chan struct{}) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you update the comment for this method?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

// Launch workers to process Revision resources
logger.Info("Starting workers")
logger := c.logger
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment above this mentions Revisions, which feels like a copy/paste oversight.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

// Launch workers to process Revision resources
logger.Info("Starting workers")
logger := c.logger
logger.Info("Starting controller and workers")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit of a shame that we're losing the controller kind in this log message, but I think we should be able to see that in the structured logging, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're actually not. This message appears in a JSON blob that has been decorated with this context (in some form) already.

mattmoor added a commit to mattmoor/pkg that referenced this pull request Aug 1, 2018
The `controller.go` is from: knative/serving#1770, however, this adds 100% coverage of `controller.go`, which we have been missing in `knative/serving`.

This also adds a `context.Context` to the `Reconcile` signature, to enable better sharing of logger setup across controllers.

Fixes: knative#8
@jonjohnsonjr
Copy link
Contributor

/lgtm
/approve

@google-prow-robot google-prow-robot added the lgtm Indicates that a PR is ready to be merged. label Aug 1, 2018
@google-prow-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: jonjohnsonjr, mattmoor

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 /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@knative-metrics-robot
Copy link

The following is the coverage report on pkg/.
Say /test pull-knative-serving-go-coverage to run the coverage report again

File Old Coverage New Coverage Delta
pkg/controller/autoscaling/autoscaling.go Do not exist 82.6%
pkg/controller/route/cruds.go 92.6% 92.7% 0.1
pkg/controller/route/labels.go 93.5% 92.3% -1.2
pkg/controller/route/route.go 96.6% 96.6% 0.1
pkg/controller/revision/revision.go 85.0% 85.1% 0.1
pkg/controller/service/service.go 91.3% 92.4% 1.1

@mattmoor
Copy link
Member Author

mattmoor commented Aug 1, 2018

/test pull-knative-serving-integration-tests

@google-prow-robot google-prow-robot merged commit 09e9ed0 into knative:master Aug 1, 2018
@mattmoor mattmoor deleted the reconciler branch August 1, 2018 19:27
google-prow-robot pushed a commit to knative/pkg that referenced this pull request Aug 1, 2018
The `controller.go` is from: knative/serving#1770, however, this adds 100% coverage of `controller.go`, which we have been missing in `knative/serving`.

This also adds a `context.Context` to the `Reconcile` signature, to enable better sharing of logger setup across controllers.

Fixes: #8
ZhiminXiang pushed a commit to ZhiminXiang/serving-1 that referenced this pull request Aug 2, 2018
…tive#1770)

* Invert the relationship between controller.Base and derivatives.

The way we use `controller.Base` today is very reminiscent of OOP; it is effectively trying to be a base class, and many things are painful trying to write this way in Go (e.g. we cannot simply make `Reconcile` an abstract method to be implemented by derivatives).

With this change, we will instead move to a model where `Base` becomes `Impl` and takes an instance of the following interface:
```go
package controller

type Reconciler interface {
  Reconcile(key string) error
}
```

In this model, `controller.Impl` is the single shared controller implementation, and the `NewController` methods become responsible for instantiating it with the appropriate implementation of `Reconciler` and wiring the appropriate events up via the informers.

This cleans up the separation between `./pkg/controller` and `./pkg/controller/foo`, and will hopefully start to make the latter quite small.  Ultimately the plan is to share the former via `knative/pkg`.

Fixes: knative#1505

* Address Jon code review feedback.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants