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

Steve controller #597

Merged
merged 14 commits into from
Apr 9, 2018
Merged

Steve controller #597

merged 14 commits into from
Apr 9, 2018

Conversation

vaikas
Copy link
Contributor

@vaikas vaikas commented Apr 5, 2018

Addresses Issue #412

Proposed Changes

  • Implement basic controller that reconciles service object into underlying route/configuration objects
  • Add sample/service to demonstrate both auto rollout as well as pinned

@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 Apr 5, 2018
@vaikas vaikas requested a review from grantr April 5, 2018 22:36
@vaikas
Copy link
Contributor Author

vaikas commented Apr 5, 2018

/assign @evankanderson

@vaikas
Copy link
Contributor Author

vaikas commented Apr 5, 2018

/retest

Ville Aikas and others added 2 commits April 6, 2018 12:14
@google-prow-robot google-prow-robot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Apr 6, 2018
Copy link
Contributor

@grantr grantr left a comment

Choose a reason for hiding this comment

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

This was easier to review than I expected; thanks @vaikas-google for making it easy to understand. I have a few minor comments.


var (
controllerKind = v1alpha1.SchemeGroupVersion.WithKind("Service")
routeProcessItemCount = prometheus.NewCounterVec(prometheus.CounterOpts{
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably should be called serviceProcessItemCount

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yep, done.


glog.Infof("Service controller Init")

// obtain references to a shared index informer for the Services and
Copy link
Contributor

Choose a reason for hiding this comment

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

This comment appears to be incomplete (Services and...)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done.

return err
}
}
config.SetGeneration(existing.GetGeneration())
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure I understand why this line is necessary. Can you add a comment explaining it? In particular, is it still needed when the apiserver is setting Generation for CRDs?

return err
}
}
route.SetGeneration(existing.GetGeneration())
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment as above could be here too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's not. For updates, I first had set the ResourceVersion (and just set the Generation as well). So, once I just switched to overwriting only the spec, I couldn't recall if the Generation was handled correctly forgot to go back and check.

loooong way to say, it's not necessary, yanked.


revisionName := ""
if service.Spec.Pinned != nil {
revisionName = service.Spec.Pinned.RevisionName
Copy link
Contributor

Choose a reason for hiding this comment

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

Is service.Spec.Pinned.RevisionName allowed to be empty here (by the webhook)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

tt := v1alpha1.TrafficTarget{
Percent: 100,
}
if len(revisionName) != 0 {
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 odd to me that MakeServiceConfiguration uses service.Spec.RunLatest to determine which configuration to use, while MakeServiceRoute uses the length of revisionName, relying on the implicit contract that an empty revision name means the service is in RunLatest mode. Is there a reason for that difference?

If MakeServiceRoute used the same method as MakeServiceConfiguration, maybe there wouldn't be a need for the revisionName parameter or the conditional at https://github.com/elafros/elafros/pull/597/files#diff-2f50e493d103b0bd9f2ac68800d40201R278.

WDYT @vaikas-google?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great suggestion! Done.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Exposed a bug in the tests too btw :)

)

func testNothing(t *testing.T) {
return
Copy link
Contributor

Choose a reason for hiding this comment

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

Intended to be filled in later? 😉

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yep, added TODO as felt this was getting a bit large already.

@@ -1,4 +1,4 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd recommend removing changes to this file since it's not related to the PR and might cause a merge conflict if someone else already fixed it in master.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hm, odd. I assume this is from the update-codegen? At least I do not recall doing this.

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 from hack/update-deps.sh

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, so when I take it out, I get this:
vaikas@vaikas-linux3:~/projects/go/src/github.com/elafros/elafros$ bazel test pkg/...
ERROR: /home/vaikas/projects/go/src/github.com/elafros/elafros/pkg/queue/BUILD.bazel:11:1: name 'go_test' is not defined (did you mean 'sh_test'?)
ERROR: package contains errors: pkg/queue
ERROR: error loading package 'pkg/queue': Package 'pkg/queue' contains errors
INFO: Elapsed time: 0.241s
FAILED: Build did NOT complete successfully (1 packages loaded)
ERROR: Couldn't start the build. Unable to run tests

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah sorry, my comment was unclear. I meant remove this change from the PR, leaving it unstaged in your local checkout. Just don't stage this particular file when committing.

It's fine to ignore this advice, since merge conflicts are unlikely anyway (the file will have the same generated content in all recent branches). At this point it's probably more work to try to remove this change than keep it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed :)

Copy link
Contributor

Choose a reason for hiding this comment

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

Turns out these were also fixed by @bobcatfish in #599


```
NAME HOSTS ADDRESS PORTS AGE
route-example-ela-ingress demo.myhost.net 80 14s
Copy link
Contributor

Choose a reason for hiding this comment

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

I think route-example should be replaced with service-example here and elsewhere in this file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done.


copy := existing.DeepCopy()
copy.Spec = config.Spec
_, err = configClient.Update(copy)
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this update the configuration if it hasn't changed? I think maybe the webhook makes the update a noop if there are no patches. IIUC that behavior is required here, because we need to be able to update a service without creating a new revision.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it doesn't diff yet, so will just update. webhook should cause the right thing to happen.
I added a few TODOs.

@vaikas
Copy link
Contributor Author

vaikas commented Apr 6, 2018

Thanks @grantr I believe I addressed all the comments (and it exposed a test bug 👍 ), PTAL.

Copy link
Contributor

@grantr grantr left a comment

Choose a reason for hiding this comment

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

/lgtm

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

@evankanderson evankanderson left a comment

Choose a reason for hiding this comment

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

We really need a CLI so that the READMEs don't have so much crummy boilerplate (and automatic DNS setup for the same).

A bunch of medium-size comments, but no major red flags. Thanks for including the sample.


// NewController initializes the controller and is called by the generated code
// Registers eventhandlers to enqueue events
//TODO(vaikas): somewhat generic (generic behavior)
Copy link
Member

Choose a reason for hiding this comment

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

I don't understand your TODO here -- what needs to be done (in case someone else wanted to pick it up and do it)

Copy link
Contributor

Choose a reason for hiding this comment

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

These TODOs are copied from the other controllers. They identify functions that have no variance across the controller types and could be moved to the shared controller package. That was the original intent anyway - they might not be accurate anymore. In particular, some controllers now create multiple informers, so the NewController methods are no longer generic.

I'm fine with removing these. Anyone investigating how to generalize controller code will certainly do their own analysis.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

leftover cruft, removed.


glog.Infof("Service controller Init")

// obtain references to a shared index informer for the Services and
Copy link
Member

Choose a reason for hiding this comment

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

You lost the end of your sentence here.

// as syncing informer caches and starting workers. It will block until stopCh
// is closed, at which point it will shutdown the workqueue and wait for
// workers to finish processing their current work items.
//TODO(grantr): generic
Copy link
Member

Choose a reason for hiding this comment

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

Again, TODO not clear.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

leftover cruft from other skeleton controllers, removed.

}

glog.Info("Starting workers")
// Launch two workers to process Service resources
Copy link
Member

Choose a reason for hiding this comment

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

This comment seems unnecessary and also wrong.

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 true in practice because threadiness is always two due to https://github.com/elafros/elafros/blob/master/cmd/ela-controller/main.go#L44. The controller isn't supposed to know that though, and this comment probably shouldn't either.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

leftover cruft from other skeleton controllers, removed.


// processNextWorkItem will read a single work item off the workqueue and
// attempt to process it, by calling the updateServiceEvent.
//TODO(vaikas): generic
Copy link
Member

Choose a reason for hiding this comment

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

TODO what

Copy link
Contributor Author

Choose a reason for hiding this comment

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

again, leftover cruft.

if apierrs.IsNotFound(err) {
_, err := configClient.Create(config)
return err
}
Copy link
Member

Choose a reason for hiding this comment

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

Do you want to bail/return on other errors?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yup, done.

if apierrs.IsNotFound(err) {
_, err := routeClient.Create(route)
return err
}
Copy link
Member

Choose a reason for hiding this comment

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

Ditto on returning err here if Get fails on the existing with something other than not found.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yup, done.

return err
}
}
route.SetGeneration(existing.GetGeneration())
Copy link
Member

Choose a reason for hiding this comment

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

Ditto here as well on modifying the input route with some fields but not others.

}
}

func createServiceWithRunLatest() *v1alpha1.Service {
Copy link
Member

Choose a reason for hiding this comment

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

It's slightly odd that this function is reused in service_route_test.go, though I don't have an immediate better suggestion.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I could've created createServiceConfigurationTestWithRunLatest :) or something like that, you're ok though with this?

Copy link
Member

Choose a reason for hiding this comment

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

I am. I was wondering if a service_object_creators or the like for common test infra would make sense here, but I'm fine with this, too.

"testing"
)

func testNothing(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

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

Do you want a TODO here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

already did :) You must have looked at the older version?

@google-prow-robot google-prow-robot removed the lgtm Indicates that a PR is ready to be merged. label Apr 6, 2018
@vaikas
Copy link
Contributor Author

vaikas commented Apr 6, 2018

Thanks @evankanderson for the review, I removed bunch of carry-over cruft todos and fixed the error cases. PTAL.

@evankanderson
Copy link
Member

It looks like I went through while you were addressing Grant's comments. I have a few more comments, but this generally LGTM:

#597 (comment)
#597 (comment)

@vaikas
Copy link
Contributor Author

vaikas commented Apr 7, 2018

allrighty, made the changes and added a todo for type checking. PTAL.

Copy link
Member

@mattmoor mattmoor left a comment

Choose a reason for hiding this comment

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

This seems like a reasonable skeleton to me, but I think I'd like to see us deeply specify the semantics we have in mind before we get too deep into implementing the controller logic and its tests.

glog.Infof("Running reconcile Service for %s\n%+v\n", service.Name, service)

config := MakeServiceConfiguration(service)
if err = c.reconcileConfiguration(config); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

err :=

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it's already defined above in 249?

@mattmoor
Copy link
Member

mattmoor commented Apr 9, 2018

/lgtm

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

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: grantr, mattmoor, vaikas-google

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:
  • OWNERS [mattmoor,vaikas-google]

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@google-prow-robot google-prow-robot merged commit 9891c18 into knative:master Apr 9, 2018
@evankanderson evankanderson mentioned this pull request Apr 18, 2018
6 tasks
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/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants