-
Notifications
You must be signed in to change notification settings - Fork 382
Conversation
this is wicked gnarly to rebase and keep everything working. |
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.
Overall comment: I don't think information about plans should live in two places - it will get out of sync otherwise.
I might be able to be convinced on this eventually, but I think so far we only had consensus on splitting the resources.
Suggest that for now, we should just split the resources, and talk through whether there should be high-level information about plans on the service class later.
@@ -19,6 +19,7 @@ | |||
set -o errexit | |||
set -o nounset | |||
set -o pipefail | |||
set -o xtrace |
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.
Did you mean to commit this?
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.
Yes, I was a little weirded out seeing the other codegen run and not the client-generator.
pkg/apis/servicecatalog/types.go
Outdated
@@ -191,7 +191,7 @@ type ServiceClass struct { | |||
|
|||
// Plans is the list of ServicePlans for this ServiceClass. All | |||
// ServiceClasses have at least one ServicePlan. | |||
Plans []ServicePlan | |||
Plans []Plan |
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.
Probably less bikeshed-accretion risk here to just keep the current 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.
In a pure split, what is this made up of?
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.
Should this now have a slice of v1.LocalObjectReference
?
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're just splitting, plans should just reference the service class and we should remove this array field of ServiceClass
.
Two-way references are very difficult to maintain.
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.
Plan -> ServiceClass
not
ServiceClass -> Plan.
Isn't this an inversion of the current arrangement? Is there any particular justification for either direction?
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'll need to be able to traverse from the serviceclass to the plan quickly - can the controller (or is it "owner"?) property on serviceclass help here?
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.
@duglin
I don't know what that is. Do you mean the BrokerName
? Shouldn't that be some kind of ObjectReferece
?
It sounds like you are disagreeing with the reference direction proposed.
pkg/apis/servicecatalog/types.go
Outdated
@@ -226,8 +226,41 @@ type ServiceClass struct { | |||
AlphaRequires []string | |||
} | |||
|
|||
type Plan struct { | |||
// PlanRef is a reference to the full plan details. | |||
PlanRef v1.LocalObjectReference `json:"planRef"` |
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'm not sure what Plan is vs. ServicePlan - I had thought we agreed to just split them rather than keeping some information in two places.
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 it's going to be profitable to store this information in two places - they will get out of sync.
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 think this might be related something I don't think we resolved... when I GET a serviceclass how much of the Plan is pulled back with it? If there are 300 plans do we want to force the UI/client to do 300 GETs too? See #454 (comment)
Just a thought: it might be worth holding off on this until we can get some clarity on what the kubernetes names of these entities should be. |
@pmorie where can we go push on the naming board or api board or whatever? |
I don't think renaming blocks this. Do we need a separate design? What are thoughts on the references? |
I think talking about this during one of our design sessions would be good. It might also be good to try to split the discussion into smaller pieces, I think there are at least two independent topics: If you could come up with a concrete proposal for each, to help focus the discussion, then we can discuss them on an upcoming call. |
Yeah, I agree with you. I had misread your PR when I made this comment. |
note: don't forget to add rbac for plans |
This should build and finish through the integration tests. I don't think I took out anything of the integration tests, but I also didn't add anything new. |
We can probably turn some of the test verbosity down now... |
Already seen some flakes I would have guessed existed. I'm not sure how tenable the maintenance of this approach is. I'll try and get it passing again, but I think this concept needs another think. I may be over thinking this. |
Seems only TPR was failing. Have attempted a fix. |
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.
Excellent start, found a few nits or apparent TODOs. Only thing I think we should talk about is the type of the service class reference.
contrib/hack/test-apiserver.sh
Outdated
@@ -44,16 +44,19 @@ NO_TTY=1 kubectl config set-cluster service-catalog-cluster --server=https://${D | |||
set -x | |||
NO_TTY=1 kubectl create -f contrib/examples/apiserver/broker.yaml | |||
NO_TTY=1 kubectl create -f contrib/examples/apiserver/serviceclass.yaml | |||
NO_TTY=1 kubectl create -f contrib/examples/apiserver/serviceplan.yaml -v 9 |
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.
is the -v argument intentional here?
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.
debug
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.
now that it appears to be working, can we remove the -v ?
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.
yes. whoops.
pkg/apis/servicecatalog/types.go
Outdated
|
||
// ServiceClassRef is a reference to the service class that | ||
// owns this plan. | ||
ServiceClassRef v1.LocalObjectReference |
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 think that we can use ServiceClassName
here. LocalObjectReference is advantageous when you anticipate needing to make a local reference into a namespaced reference in the future. I don't think we anticipate that here.
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 is ServiceClassName
?
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 think he means just use string
and put the service class's name in there. However, at some point we may need to have namespaced classes/plans at some point - so would keeping LocalObjectRef be safer? In CF-land they have the notion of making certain services available only to certain orgs (they are not globally available to everyone), so it seems very possible we'll need that too at some point.
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.
On a related question, if we allow for serviceclasses to be namespaced in the future will that be a backward incompatible change for our APIs? I think its just a matter of adding a namespace
property when needed, 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.
And... can a resource type be both namespaced and not namespaced? Meaning, can I have one instance of ServiceClass be namespaced and nother one be un-namespaced?
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 seems the more kube-y way to do that to me. LocalObjectRef is a Name.
|
||
// ServiceClassRef is a reference to the service class that | ||
// owns this plan. | ||
ServiceClassRef v1.LocalObjectReference `json:"serviceClassRef"` |
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.
Same comment about typing.
ExternalID: plans[i].ID, | ||
Free: (plans[i].Free != nil && *plans[i].Free), | ||
Description: plans[i].Description, | ||
func convertServicePlans(plans []osb.Plan, serviceClassName string) ([]*v1alpha1.ServicePlan, 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.
I believe that we will need to prefix the name of the service plan with the name of the service class. Plan names are only unique within a service, and not globally. I don't think this yields the greatest names, but we can fix that with porcelain.
Totally open to talking through this in a meeting, and I realize it is an intersection with an unresolved issue (#802).
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.
Fix it later.
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 should discuss this before beta. Morgan can you open an issue and put it in the 0.1.0 milestone so we don't forget.
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.
okay
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.
Circling back in this group of comments for posterity:
We decided in a SIG meeting for now to use $name-$id
as the kubernetes names of services to spur ourselves to finish figuring out what to do with the kubernetes names of these objects.
pkg/controller/controller_binding.go
Outdated
} | ||
|
||
/* |
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.
Looks like an old comment
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.
yea, removing.
pkg/controller/controller_test.go
Outdated
@@ -823,7 +885,7 @@ func TestCatalogConversionServicePlanBindable(t *testing.T) { | |||
t.Fatalf("Failed to unmarshal test catalog: %v", err) | |||
} | |||
|
|||
actual, err := convertCatalog(catalog) | |||
actual, _, err := convertCatalog(catalog) |
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.
Looks like a TODO
} | ||
|
||
// GetAttrs returns labels and fields of a given object for filtering purposes. | ||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, 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.
We might want to make service class name a selectable field (in a follow-up)
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 know what this does.
|
||
// NewSingular returns a new shell of a service servicePlan, according to the given namespace and | ||
// name | ||
func NewSingular(ns, name string) runtime.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.
Is this applicable, since ServicePlan is root-scoped?
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 idea, copied serviceclass.
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.
ok
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 used in TPR storage
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.
ah
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.
and in CRD as well 😉
test/integration.sh
Outdated
@@ -25,7 +25,8 @@ source "${KUBE_ROOT}/hack/lib/init.sh" | |||
runTests() { | |||
kube::etcd::start | |||
|
|||
go test -race -v github.com/kubernetes-incubator/service-catalog/test/integration/... --args -v 10 -logtostderr | |||
go test -race -v -i github.com/kubernetes-incubator/service-catalog/test/integration/... -c \ |
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.
is checking in -c
intentional
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'm curious too
@@ -113,8 +113,12 @@ func TestEtcdHealthCheckerSuccess(t *testing.T) { | |||
} | |||
c := &http.Client{Transport: tr} | |||
resp, err := c.Get(clientconfig.Host + "/healthz") | |||
if nil != err || http.StatusOK != resp.StatusCode { | |||
t.Fatal("health check endpoint should not have failed") | |||
if nil != err { |
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.
separate PR plz
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.
Debugging improvement. Why split it out?
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.
You can split it out if you want it to land sooner. Your choice.
https://travis-ci.org/MHBauer/service-catalog/builds/270170017 works if you don't want to wait for cri-o builds to finish. |
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.
overall this looks good. thanks @MHBauer! also, I am ok with the local object reference.
LGTM
|
||
// NewSingular returns a new shell of a service servicePlan, according to the given namespace and | ||
// name | ||
func NewSingular(ns, name string) runtime.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.
it's used in TPR storage
Everything is green, so I'll squish down into two. |
This still has ServiceInstanceSpec.PlanName as a We have an issue right now with the names of Plans because per the OSB API spec they only need to be unique within a service, but in Kube they need to be unique for the entire cluster. Now, @pmorie suggested that we concat the serviceName and the planName and use that as the planName on the Plan resource. That doesn't yield the greatest UX. However, since ServiceInstanceSpec.PlanName isn't an objectRef and we need to do a manual lookup we can get away with ServiceInstanceSpec.PlanName only being the plan name itself and not the concatenation of ServiceName and PlanName - which means a nicer UX, at least for creating ServiceInstances. Its not great if you ever need to retrieve a Plan by itself because you then need to twiddle names. I'd like to discuss this issue and the names of Plans in general on tomorrow's design call before we merge this. I'm hoping that the net result of this will be to just twiddling of these split resources but in case it ends up requiring a lot more surgery I think having one more day/talk would be good and not delaying it too much. |
pkg/controller/controller.go
Outdated
// a brokerclient to use for a given Instance. | ||
func (c *controller) getServicePlan(name string) (*v1alpha1.ServicePlan, error) { | ||
// use the ref to get the real plan | ||
return c.servicePlanLister.Get(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.
Note - at some point this will need to be scoped to just the service. But its all based on how we deal with names of plans, etc....
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 would be useful to have a TODO here 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.
Not sure I agree with the scope of that. This does exactly and only what it should. TODO should be an issue, maybe?
pkg/controller/controller_binding.go
Outdated
@@ -171,7 +171,8 @@ func (c *controller) reconcileServiceInstanceCredential(binding *v1alpha1.Servic | |||
|
|||
serviceClass, servicePlan, brokerName, brokerClient, err := c.getServiceClassPlanAndServiceBrokerForServiceInstanceCredential(instance, binding) | |||
if err != nil { | |||
return err | |||
glog.Warning("couldn't get the things") |
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.
ok this warning isn't very useful. Can we add more info to it?
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 put it back to not having any log message at all.
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 like the idea of the msg, but I want it to be meaningful
pkg/controller/controller_broker.go
Outdated
@@ -214,7 +218,8 @@ func (c *controller) reconcileServiceBroker(broker *v1alpha1.ServiceBroker) erro | |||
glog.V(5).Infof("Successfully fetched %v catalog entries for ServiceBroker %v", len(brokerCatalog.Services), broker.Name) | |||
|
|||
glog.V(4).Infof("Converting catalog response for ServiceBroker %v into service-catalog API", broker.Name) | |||
catalog, err := convertCatalog(brokerCatalog) | |||
glog.V(4).Infof("Converting catalog response for Broker %v into service-catalog API", broker.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.
s/%v/%q/ so its quoted
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.
dup line anyway
@kibbles-n-bytes Jenkins had a "failure to set github status". Is there a retry in our code when that tries to happen, or is it part of a jenkins plugin we probably can't touch? |
edited, rebased, all green. |
I'm taking off LGTM1 to re-review because this is a huge API change. |
@MHBauer Huh, I've never seen the GitHub status setting fail. Sounds like GitHub was just down for a brief moment. That portion is touchable and I could add a retry if necessary, but I think it's such a rare occurrence that it can wait as a "nice-to-have" feature for the time being. |
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 like the direction of this PR, mostly just nits.
func ValidateServicePlanUpdate(new *sc.ServicePlan, old *sc.ServicePlan) field.ErrorList { | ||
allErrs := field.ErrorList{} | ||
allErrs = append(allErrs, ValidateServicePlan(new)...) | ||
allErrs = append(allErrs, ValidateServicePlan(old)...) |
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.
As far as I can tell, the old one is being sometimes implicitly validated because we need some conversion of types, comparing fields etc.
For example, see https://github.com/kubernetes-incubator/service-catalog/blob/master/vendor/k8s.io/apimachinery/pkg/api/validation/objectmeta.go#L243
There could be errors produced as a result of invalid old object, true, but that was not the primary goal here - it was a side-effect of the need to convert types.
I haven't found any example of validating the old one just for the sake of "best practice".
Seems redundant here to me (could remove in other places in follow-up PRs as well, if we have similar code already).
if getAction != 4 { | ||
t.Errorf("Expected 4 'get' action, got %d", getAction) | ||
if getAction != 5 { | ||
t.Errorf("Expected 5 'get' actions, got %d", getAction) |
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.
Shall we start checking resource types, or at least make sure that all get
/create
were for different types?
### ServiceClass API Changes | ||
|
||
Instead of having an array of ServicePlans defined inline, we have an array of | ||
Reference to ServicePlan. |
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.
Isn't that reverse, ServicePlan
having a reference to a ServiceClass
? Do we still have an array for some reason?
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.
Good catch. I will edit this and review the whole thing to make sure it is correct.
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.
brain fart on my part. I will update and review the whole document.
} | ||
``` | ||
|
||
Classes are not namespaced, so plans are not namespaced. Possibility |
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.
nit: such resources are called "cluster scoped" (as opposed to "namespace scoped") in Kubernetes
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.
okay, will edit.
|
||
Classes are not namespaced, so plans are not namespaced. Possibility | ||
of collision of two ServicePlans from different ServiceClass based on | ||
Name. This will be addressed by concatinating the ServiceClass |
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 wonder if we have the same issue for ServiceClass
already. If so, how did we resolve this?
According to the spec, service name:
MUST be unique across all service objects returned in this response
so it's not globally unique either.
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 an open issue upstream as well.
//var validateServicePlanName = apivalidation.NameIsDNSSubdomain | ||
|
||
const servicePlanNameFmt string = `[-a-z0-9]+` | ||
const servicePlanNameMaxLength int = 63 |
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.
Where did you get this limit from?
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 comes from upstream when the serviceplan name was used as a label key, it was failing.
#1047
I should get rid of that comment above.
errs = append(errs, utilvalidation.MaxLenError(servicePlanNameMaxLength)) | ||
} | ||
if !servicePlanNameRegexp.MatchString(value) { | ||
errs = append(errs, utilvalidation.RegexError(servicePlanNameFmt, "plan-name-0000")) |
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 a bad example I guess :) should provide a legit example with UUID suffix instead.
pkg/controller/controller.go
Outdated
@@ -358,7 +372,15 @@ func (c *controller) getServiceClassPlanAndServiceBrokerForServiceInstanceCreden | |||
} | |||
|
|||
// ServiceBroker utility methods - move? |
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 comment seems to be misplaced now.
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.
oops, thanks.
serviceClasses[i].SetName(svc.Name) | ||
|
||
// set up the plans using the ServiceClass Name | ||
plans, err := convertServicePlans(svc.Plans, svc.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.
nit: pass serviceClasses[i].Name
instead of svc.Name
for cleanliness.
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 do not follow, what do you mean?
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.
2 lines above you take a value from svc.Name
and set it to serviceClass.
convertServicePlans
generates a plan which has a reference to serviceClass, right? So I would prefer to explicitly pass serviceClasses[i].Name
here instead of svc.Name
(even though the value is the same).
Imagine that you would change the code 2 lines-above to something like
serviceClasses[i].SetName(svc.Name + generateUuid())
in this case the name you pass into convertServicePlans
would be out of sync. With my change it wouldn't.
@@ -77,6 +79,9 @@ func (d *defaultServicePlan) Admit(a admission.Attributes) error { | |||
return nil | |||
} | |||
|
|||
// check and default |
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.
I think this was more of a top-level 'what are we doing here' type comment, but in context it is pretty useless. I'll remove it, but I think we should try and get a group together to review the default service plan admission controller.
I hate to add more work here Morgan, but #1210 was merged yesterday that added a new admission controller that blocks changes to an instance's service plan if the plan is not updatable. |
I'll get started on the refresh Monday morning. |
Green Jenkins, phew. |
@@ -75,7 +76,7 @@ func (d *denyPlanChangeIfNotUpdatable) Admit(a admission.Attributes) error { | |||
if err != nil { | |||
if apierrors.IsNotFound(err) { | |||
glog.V(5).Infof("Could not locate service class %v, can not determine if UpdateablePlan.", instance.Spec.ServiceClassName) | |||
return nil | |||
return nil // should this be `return err`? why would we allow the instance in if we cannot determine it is updatable? |
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.
Seems like there's a follow-up issue here - do you want to create one?
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 memory serves me, I tried this with returning an error, it broke unit tests, so I figured this was the desired behavior.
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 suppose this particular thing is not concerned with whether the instance refers to a valid service class. We can let it through on the recognition that it will be caught later in the actual validation stages.
Weird, but I think that is the correct analysis. Thoughts?
I'm concerned that the walkthrough e2es may not be testing the correct version of the code. When I try to run the walkthrough locally, the controller can't create serviceplans for the ups-broker: apiVersion: servicecatalog.k8s.io/v1alpha1
kind: ServiceBroker
metadata:
creationTimestamp: 2017-09-19T13:39:46Z
finalizers:
- kubernetes-incubator/service-catalog
generation: 1
name: ups-broker
resourceVersion: "3"
selfLink: /apis/servicecatalog.k8s.io/v1alpha1/servicebrokers/ups-broker
uid: 00183ac8-9d40-11e7-a37c-0242ac110005
spec:
url: http://ups-broker-ups-broker.ups-broker.svc.cluster.local
status:
conditions:
- lastTransitionTime: 2017-09-19T13:39:46Z
message: 'Error syncing catalog from ServiceBroker. Error reconciling servicePlan
"default-86064792-7ea2-467b-af93-ac9694d96d52" (broker "ups-broker"): serviceplans.servicecatalog.k8s.io
is forbidden: User "system:serviceaccount:catalog:service-catalog-controller-manager"
cannot create serviceplans.servicecatalog.k8s.io at the cluster scope'
reason: ErrorSyncingCatalog
status: "False"
type: Ready
reconciledGeneration: 0 Going to try the e2e next. |
So, I am not sure at all how e2e could be passing, and I found a bug in the rbac setup for which I needed to create https://github.com/MHBauer/service-catalog/pull/3. I think we should ensure that we understand why the tests showed as green before we merge this. |
Adding do-not-merge for now to avoid an accidental merge until we can figure out why the tests appeared to pass. |
Oh ya, missed my own reminder. whoops. |
something weird is going on with lint. |
- logic for separate plan lookups - make the tests keep working - remove plan references from class - nuke plans - defining the serviceplan storage - controller adjustments - remove json unnecessary annotations - getting the storage for apiserver hooked up - prevent service plan ExeternalID changes on update - random test case improvements to assist in debugging - the secret is defining whether or not an object is namespaced in nineteen different places - de-verbose - quotes for doug - more debug information in tpr test
Green again. |
@pmorie verified RBAC rules as per discussion on the slack channel. Merging. |
|
||
// ServiceClassRef is a reference to the service class that | ||
// owns this plan. | ||
ServiceClassRef v1.LocalObjectReference |
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 could be just an Owner Reference with Controller=true?
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 merged, so we can do followups now.
What does controller=true
mean?
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.
@MHBauer Kubernetes object could have multiple OwnerReferences, but only one of them could be a controller ("true owner").
IMO a dedicated ServiceClassRef
makes sense there, and provides a better more transparent UX.
That said, I agree with @ash2k that we should also set OwnerReference to make sure there is no clash between different classes having plans with same UUIDs/names.
It will also prevent deletion of ServiceClass
if it has existing ServicePlan
referencing it.
See pull request #979 for the example of how I set OwnerReference for secret owned by binding.
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 start on #454
need to fix the integration tests, probably e2es as well