Skip to content
This repository has been archived by the owner on May 6, 2022. It is now read-only.

Broker Relist #1183

Merged
merged 29 commits into from
Sep 19, 2017
Merged

Broker Relist #1183

merged 29 commits into from
Sep 19, 2017

Conversation

eriknelson
Copy link
Contributor

Initial fields for #1086

@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Aug 31, 2017
@eriknelson eriknelson force-pushed the relist branch 2 times, most recently from eb4a4ce to 1b96007 Compare September 6, 2017 17:07
Copy link
Contributor

@pmorie pmorie left a comment

Choose a reason for hiding this comment

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

Looks like a promising start - you need to add a validation and do a small amount of refactoring. Also, since the CLI argument becomes a dummy, you should hide it. (see options.go under controller-manager).

@@ -60,8 +60,29 @@ type ServiceBrokerSpec struct {
// CABundle is a PEM encoded CA bundle which will be used to validate a Broker's serving certificate.
// +optional
CABundle []byte

// RelistBehavior specifies the type of relist behavior the catalog should exhibit
Copy link
Contributor

Choose a reason for hiding this comment

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

We need to add validations for these fields. See pkg/apis/servicecatalog/validation/broker.go


// RelistBehavior specifies the type of relist behavior the catalog should exhibit
// when relisting ServiceClasses available from a broker
RelistBehavior ServiceBrokerRelistBehavior
Copy link
Contributor

Choose a reason for hiding this comment

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

fields in versioned APIs need to have json tags associated with them. For this field, it would be:

RelistBehavior ServiceBrokerRelistBehavior `json:"relistBehavior"`

You'll need to add these to the fields in this file.

@@ -113,8 +113,8 @@ const (
// shouldReconcileServiceBroker determines whether a broker should be reconciled; it
// returns true unless the broker has a ready condition with status true and
// the controller's broker relist interval has not elapsed since the broker's
// ready condition became true.
func shouldReconcileServiceBroker(broker *v1alpha1.ServiceBroker, now time.Time, relistInterval time.Duration) bool {
// ready condition became true, or if the broker's RelistBehavior is set to Manual
Copy link
Contributor

Choose a reason for hiding this comment

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

missing period

// ready condition became true.
func shouldReconcileServiceBroker(broker *v1alpha1.ServiceBroker, now time.Time, relistInterval time.Duration) bool {
// ready condition became true, or if the broker's RelistBehavior is set to Manual
func shouldReconcileServiceBroker(broker *v1alpha1.ServiceBroker, now time.Time, relistInterval metav1.Duration) bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

Technically you do not need to pass in the relistInterval parameter here, since you're now reading it from the broker.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, I didn't realize you were still reading it as a parameter. You already have the broker here - you can read the value in this method and delete the relistInterval parameter. There needs to ve a validation that ensures that the duration field is set when the mode is 'duration'.

@@ -168,14 +185,16 @@ func (c *controller) reconcileServiceBrokerKey(key string) error {
// processed and should be resubmitted at a later time.
func (c *controller) reconcileServiceBroker(broker *v1alpha1.ServiceBroker) error {
glog.V(4).Infof("Processing ServiceBroker %v", broker.Name)
if broker.Spec.RelistDuration == nil {
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 this TODO is fixed :)

You should be defensive in programming, but some assumptions that you have validated for already are okay. So for instance, you should ensure that you don't dereference a nil pointer for an optional field. However, if that optional field must be set based on a validation, a state where that validation fails in code should be handled like an error.

"Not processing ServiceBroker %v because relist interval has not elapsed since the broker became ready",
broker.Name,
)
if !shouldReconcileServiceBroker(broker, time.Now(), *broker.Spec.RelistDuration) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Your TODO appears to be handled now in shouldReconcileServiceBroker.

@@ -553,6 +554,8 @@ func testReconcileServiceBrokerWithAuth(t *testing.T, authInfo *v1alpha1.Service
}
}

// ERIK:TODO: Write up another test here to confirm an error is bubbled when
// RelistDuration is nil, similar to this?
Copy link
Contributor

Choose a reason for hiding this comment

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

RelistDuration being nil should be handled in shouldReconcileBroker.

@@ -140,7 +141,9 @@ func TestCreateWithNoNamespace(t *testing.T) {
inputServiceBroker := &sc.ServiceBroker{
ObjectMeta: metav1.ObjectMeta{Name: name},
Spec: sc.ServiceBrokerSpec{
URL: "http://my-awesome-broker.io",
URL: "http://my-awesome-broker.io",
Copy link
Contributor

Choose a reason for hiding this comment

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

I am not qualified to review TPR stuff. @arschles @nilebox

@k8s-ci-robot k8s-ci-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Sep 11, 2017
Copy link
Contributor

@pmorie pmorie left a comment

Choose a reason for hiding this comment

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

Looks like validations need to be tweaked a little bit. Left a couple small asks and nits.

Let's do the subresource and porcelain command in a follow-up.

@@ -192,6 +193,11 @@ func FuzzerFor(t *testing.T, version schema.GroupVersion, src rand.Source) *fuzz
// Set the bytes field on the RawExtension
r.Raw = bytes
},
func(bs *servicecatalog.ServiceBrokerSpec, c fuzz.Continue) {
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 surprised that the default fuzzer didn't work for this field. Do you try 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.

Think I did, but I'll pull it and try again.

spec.RelistBehavior = ServiceBrokerRelistBehaviorDuration
}

if spec.RelistDuration == nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

You should only default relist duration if the relist behavior is "Duration". It should not be defaulted for manual behavior.

@@ -68,6 +68,22 @@ func roundTrip(t *testing.T, obj runtime.Object) runtime.Object {
return obj3
}

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

Choose a reason for hiding this comment

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

Tests here need to change according to the logic as I commented above

Copy link
Contributor

Choose a reason for hiding this comment

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

There should be test cases for:

  1. Neither duration or behavior set
  2. Behavior set to manual
  3. Behavior set to duration but no duration provided

Copy link
Contributor

Choose a reason for hiding this comment

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

Still need test cases for these defaults. You need to ensure that after an object starting in each of the states in the above comment is defaults, that the object is in the expected state.


// RelistBehavior specifies the type of relist behavior the catalog should exhibit
// when relisting ServiceClasses available from a broker
RelistBehavior ServiceBrokerRelistBehavior `json:"relistBehavior"`
Copy link
Contributor

Choose a reason for hiding this comment

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

newline separate these to keep it consistent with the rest of the file, same for the other types.go

@@ -99,6 +99,12 @@ func validateServiceBrokerSpec(spec *sc.ServiceBrokerSpec, fldPath *field.Path)
)
}

if spec.RelistBehavior == sc.ServiceBrokerRelistBehaviorDuration && spec.RelistDuration == nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

Question: do you think it is valid for duration to be set if the behavior is manual? It might be. If you switch from duration to manual temporarily, for example, you might not expect to have to unset the duration. Consider what the 'least surprise' is here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, I don't see unit tests for the validations

Copy link
Contributor Author

Choose a reason for hiding this comment

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

do you think it is valid for duration to be set if the behavior is manual? It might be. If you switch from duration to manual temporarily, for example, you might not expect to have to unset the duration.

Agreed. I would be surprised if I had to explicitly unset duration, and instead would expect the duration to simply be ignored.

// reconcile: whether or not the reconciler should run, the return of
// shouldReconcileServiceBroker
// ERIK:TODO: Test new Relist codepaths
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like this TODO still needs to be done, accurate?

Copy link
Contributor Author

@eriknelson eriknelson Sep 12, 2017

Choose a reason for hiding this comment

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

Have a local commit with a bunch of error handling I wanted to run by you. It tests the RelistDuration == nil branch, but I want to make sure I hit the rest of them.

Copy link
Contributor

@pmorie pmorie left a comment

Choose a reason for hiding this comment

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

Looks like the validations and defaults still need to be tested.

Also, validation needed to ensure that the behavior field is set.

// when relisting ServiceClasses available from a broker
RelistBehavior ServiceBrokerRelistBehavior

//RelistDuration is the frequency by which a controller will relist the broker
Copy link
Contributor

Choose a reason for hiding this comment

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

There should be spaces after the // and all godoc comments for fields should end in periods.

type ServiceBrokerRelistBehavior string

const (
// ServiceBrokerRelistBehaviorDuration will allow the RelistDuration frequency to be configured
Copy link
Contributor

Choose a reason for hiding this comment

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

// ServiceBrokerRelistBehaviorDuration indicates that the broker will be relisted automatically after the specified duration has passed.

const (
// ServiceBrokerRelistBehaviorDuration will allow the RelistDuration frequency to be configured
ServiceBrokerRelistBehaviorDuration ServiceBrokerRelistBehavior = "Duration"
// ServiceBrokerRelistBehaviorManual will configure the catalog to only perform future
Copy link
Contributor

Choose a reason for hiding this comment

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

// ServiceBrokerRelistBehaviorManual indicates that the broker is only relisted when the spec of the broker changes.

@@ -68,6 +68,22 @@ func roundTrip(t *testing.T, obj runtime.Object) runtime.Object {
return obj3
}

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

Choose a reason for hiding this comment

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

Still need test cases for these defaults. You need to ensure that after an object starting in each of the states in the above comment is defaults, that the object is in the expected state.

@@ -99,6 +99,12 @@ func validateServiceBrokerSpec(spec *sc.ServiceBrokerSpec, fldPath *field.Path)
)
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Need a validation here to ensure that the relist behavior is set.

Copy link
Contributor

Choose a reason for hiding this comment

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

Still need to update the unit tests for this validation.

}

if broker.Spec.RelistDuration == nil {
glog.V(10).Infof(
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be logged at Error

@eriknelson eriknelson changed the title [WIP] broker relist Broker Relist Sep 13, 2017
valid: true,
},
{
name: "valid broker - manual behavior with behavior",
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: name should be manual behavior with duration instead of manual behavior with beavior

Copy link
Contributor

@jboyd01 jboyd01 left a comment

Choose a reason for hiding this comment

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

lgtm

Copy link
Contributor

@staebler staebler left a comment

Choose a reason for hiding this comment

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

Some nits

Copy link
Contributor

@staebler staebler left a comment

Choose a reason for hiding this comment

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

Generally, LGTM. Some nits.

}

if spec.InsecureSkipTLSVerify && len(spec.CABundle) > 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("caBundle"), spec.CABundle, "caBundle cannot be used when insecureSkipTLSVerify is true"))
}

if "" == spec.RelistBehavior {
allErrs = append(allErrs,
field.Required(fldPath.Child("relistDuration"),
Copy link
Contributor

Choose a reason for hiding this comment

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

The path here should be relistBehavior and the comment should indicate that the broker must have a relistBehavior.

if spec.RelistBehavior == sc.ServiceBrokerRelistBehaviorDuration && spec.RelistDuration == nil {
allErrs = append(
allErrs,
field.Required(fldPath.Child("relistDuration"), "relistDuration must be set if behavior is set to Duration"),
Copy link
Contributor

Choose a reason for hiding this comment

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

This should probably be "relistDuration must be set if relistBehavior is set to Duration", so that it is clear which field is of importance.

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like this still needs to be done

field.Required(fldPath.Child("relistDuration"), "relistDuration must be set if behavior is set to Duration"),
)
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Do we want to enforce that relistRequests be non-negative.

Copy link
Contributor Author

@eriknelson eriknelson Sep 13, 2017

Choose a reason for hiding this comment

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

I had a similar thought. Should the field be a uint? I that normally acceptable?

Copy link
Contributor

Choose a reason for hiding this comment

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

uint is discouraged. All you need to do is add a validation check to ensure it is non-negative. And indicate that restriction in the comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@staebler pushed an update to the comments indicating as such. Validation asserts greater than zero.

)
}

if tc.duration == nil && actualSpec.RelistDuration == nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

This check does not verify that the actual RelistDuration was nil for the "behavior set to manual" test.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There is an open question as to whether or not RelistDuration MUST BE nil given a RelistBehavior of Manual. Is this something that needs to be asserted? CC @pmorie

Copy link
Contributor

Choose a reason for hiding this comment

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

@eriknelson yes, it should be enforced to nil (and checked at the validation stage). similar to union types, where only one branch can be initialized at a time.

"brokers must have a relistDuration"))
}

if spec.RelistBehavior == sc.ServiceBrokerRelistBehaviorDuration && spec.RelistDuration == nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

We need to validate that the RelistDuration is above a reasonable minimum, at least above 0.

},
},
valid: false,
},
Copy link
Contributor

Choose a reason for hiding this comment

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

We also need tests to verify the behavior when RelistBehavior is invalid and empty.

return false
}

if broker.Spec.RelistDuration == nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this check necessary given that we have already performed validation on the Broker Spec to ensure that the RelistDuration is not nil when the RelistBehavior is not Manual?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've been back and forth on this. Are folks generally comfortable with trusting and dereffing a pointer value given a validation?

Copy link
Contributor

Choose a reason for hiding this comment

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

You should always program defensively, IMO.

// when the RelistBehavior is set to ServiceBrokerRelistBehaviorDuration
RelistDuration *metav1.Duration

// RelistRequests is a strictly increasing integer counter that can be manually incremented
Copy link
Contributor

Choose a reason for hiding this comment

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

If we are claiming that this is a strictly increasing integer, then we should add a check in the ValidateUpdate function of the brokerRESTStrategy that validates that the new value is not less than the old value.

reconcile: true,
},
{
name: "ready, duration behavior, nil duration",
Copy link
Contributor

Choose a reason for hiding this comment

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

We shouldn't need to test this. This should be caught by the Broker validator.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If it's being asserted in shouldReconcileBroker, I think it's worth keeping as a test case. Happy to remove if folks feel strongly otherwise.

Copy link
Contributor

Choose a reason for hiding this comment

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

Keep it

@@ -553,6 +585,7 @@ func testReconcileServiceBrokerWithAuth(t *testing.T, authInfo *v1alpha1.Service
}
}

// RelistDuration is nil, similar to this?
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this a stray comment that got placed here accidentally?

@eriknelson
Copy link
Contributor Author

@staebler responded to feedback, thank you!

Copy link
Contributor

@pmorie pmorie left a comment

Choose a reason for hiding this comment

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

Found a couple little nits. Super close to LGTM.

if "" == spec.RelistBehavior {
allErrs = append(allErrs,
field.Required(fldPath.Child("relistBehavior"),
"brokers must have a relistBehavior"))
Copy link
Contributor

Choose a reason for hiding this comment

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

"relist behavior is required"

isValidRelistBehavior := spec.RelistBehavior == "Duration" ||
spec.RelistBehavior == "Manual"
if !isValidRelistBehavior {
errMsg := fmt.Sprintf("unknown relistBehavior found: %v", spec.RelistBehavior)
Copy link
Contributor

Choose a reason for hiding this comment

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

"relist behavior must be "Manual" or "Duration""

Copy link
Contributor

Choose a reason for hiding this comment

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

Or use field.NotSupported which takes a []string of valid values.

Copy link
Contributor

Choose a reason for hiding this comment

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

Or use field.NotSupported which takes a []string of valid values.

"brokers must have a relistBehavior"))
}

isValidRelistBehavior := spec.RelistBehavior == "Duration" ||
Copy link
Contributor

Choose a reason for hiding this comment

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

use the constants from API types

field.Required(fldPath.Child("relistDuration"), "relistDuration must be set if behavior is set to Duration"),
)
}
if spec.RelistRequests < 0 {
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 you always want to apply this validation, even if the behavior is manual

}

if spec.RelistBehavior == sc.ServiceBrokerRelistBehaviorDuration {
if spec.RelistDuration == nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

looks like this is a duplicate of :124, and looks like this can be removed now, see comment about non-negative validation

},
},
valid: false,
},
Copy link
Contributor

Choose a reason for hiding this comment

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

need test for negative relistRequests

reconcile: true,
},
{
name: "ready, duration behavior, nil duration",
Copy link
Contributor

Choose a reason for hiding this comment

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

Keep it

Copy link
Contributor

@nilebox nilebox left a comment

Choose a reason for hiding this comment

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

Generally looks good, but needs code cleanup, more tests and minor fixes (see comments).

)

func addDefaultingFuncs(scheme *runtime.Scheme) error {
return RegisterDefaults(scheme)
}

func SetDefaults_ServiceBrokerSpec(spec *ServiceBrokerSpec) {
isValidRelistBehavior := spec.RelistBehavior == "Duration" ||
Copy link
Contributor

Choose a reason for hiding this comment

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

Reference ServiceBrokerRelistBehaviorDuration and ServiceBrokerRelistBehaviorManual constants instead of inline strings?

Copy link
Contributor

Choose a reason for hiding this comment

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

This code shouldn't be there at all, see below.

isValidRelistBehavior := spec.RelistBehavior == "Duration" ||
spec.RelistBehavior == "Manual"

if !isValidRelistBehavior {
Copy link
Contributor

Choose a reason for hiding this comment

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

Defaults shouldn't handle invalid values, they handle missing values.
Hence, instead of the check above you should check for empty string here.

)
}

if tc.duration == nil && actualSpec.RelistDuration == nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

@eriknelson yes, it should be enforced to nil (and checked at the validation stage). similar to union types, where only one branch can be initialized at a time.

)
}

if spec.RelistBehavior == sc.ServiceBrokerRelistBehaviorDuration && spec.RelistDuration == nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

as mentioned in the other comments thread, you should also check that RelistDuration is nil when RelistBehavior != Duration

@@ -40,7 +41,9 @@ func TestValidateServiceBroker(t *testing.T) {
Name: "test-broker",
},
Spec: servicecatalog.ServiceBrokerSpec{
URL: "http://example.com",
URL: "http://example.com",
RelistBehavior: "Duration",
Copy link
Contributor

Choose a reason for hiding this comment

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

use constant from types (here and below).

URL: "http://example.com",
URL: "http://example.com",
RelistBehavior: "Duration",
RelistDuration: &metav1.Duration{15 & time.Minute},
Copy link
Contributor

@nilebox nilebox Sep 14, 2017

Choose a reason for hiding this comment

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

should be * instead of &, you accidentally perform binary AND operation. here and below.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, thank you. Not at all what I intended.

@@ -140,7 +141,9 @@ func TestCreateWithNoNamespace(t *testing.T) {
inputServiceBroker := &sc.ServiceBroker{
ObjectMeta: metav1.ObjectMeta{Name: name},
Spec: sc.ServiceBrokerSpec{
URL: "http://my-awesome-broker.io",
URL: "http://my-awesome-broker.io",
RelistBehavior: "Duration",
Copy link
Contributor

Choose a reason for hiding this comment

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

use constant

URL: "http://my-awesome-broker.io",
URL: "http://my-awesome-broker.io",
RelistBehavior: "Duration",
RelistDuration: &metav1.Duration{15 * time.Minute},
Copy link
Contributor

Choose a reason for hiding this comment

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

What are we trying to check there by setting those fields? If we want to make sure that serialization and persistence works correctly, you should set values different from default.

* Set default RelistBehavior only in the absence of a value
* Error messages tweaks
* Use correct Behavior constants from types rather than inline strings
* Validate nil RelistDuration when RelistBehavior is set to Manual
* Remove redundant validation
* Fix accidental binary AND
* Test negative value for RelistRequests fails validation
@eriknelson
Copy link
Contributor Author

eriknelson commented Sep 14, 2017

@nilebox @pmorie think I should have addressed your comments in the last couple commits, also rebased and repaired conflicts. Let me know if I missed something, thank you for the reviews!

Copy link
Contributor

@nilebox nilebox left a comment

Choose a reason for hiding this comment

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

@eriknelson see a couple more nits about constants. close to LGTM.

name: "ready, duration behavior, nil duration",
broker: func() *v1alpha1.ServiceBroker {
broker := getTestServiceBrokerWithStatus(v1alpha1.ConditionTrue)
broker.Spec.RelistBehavior = "Duration"
Copy link
Contributor

Choose a reason for hiding this comment

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

const

@@ -192,6 +193,11 @@ func FuzzerFor(t *testing.T, version schema.GroupVersion, src rand.Source) *fuzz
// Set the bytes field on the RawExtension
r.Raw = bytes
},
func(bs *servicecatalog.ServiceBrokerSpec, c fuzz.Continue) {
c.FuzzNoCustom(bs)
bs.RelistBehavior = "Duration"
Copy link
Contributor

Choose a reason for hiding this comment

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

const

name: "ready, manual behavior",
broker: func() *v1alpha1.ServiceBroker {
broker := getTestServiceBrokerWithStatus(v1alpha1.ConditionTrue)
broker.Spec.RelistBehavior = "Manual"
Copy link
Contributor

Choose a reason for hiding this comment

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

const

@eriknelson
Copy link
Contributor Author

@nilebox think I got the last of them. For my edification, I had someone suggest it might be preferred to not use the consts from types in tests in case the values change? I'm probably misunderstanding that, but are there any cases where an inline value might be preferred?

@nilebox
Copy link
Contributor

nilebox commented Sep 15, 2017

@eriknelson if you want to ensure that the constant hasn't changed, I would write a specific test for it. Might be something as trivial as

if ServiceBrokerRelistBehaviorDuration != "Duration" {
  t.Fail();
}

RelistBehavior is effectively a poor man's enum type (Go lacks support for enumeration types), so I don't see any other case where inline string is preferable - even if you want to avoid extra dependency I would still copy all the constants and used them.

Unfortunately, Kubernetes code is full of inline hardcoded strings, and it makes it hard to catch all cases while refactoring. So I personally prefer using constants where it makes sense.

@nilebox nilebox added the LGTM1 label Sep 15, 2017
Copy link
Contributor

@pmorie pmorie left a comment

Choose a reason for hiding this comment

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

Just a couple nits, and also:

  • make sure godoc comments end in a period
  • make sure godoc comments are wrapped at 80 cols

if spec.RelistBehavior == sc.ServiceBrokerRelistBehaviorManual && spec.RelistDuration != nil {
allErrs = append(
allErrs,
field.Required(fldPath.Child("relistDuration"), "relistDuration must not be set if behavior is set to Manual"),
Copy link
Contributor

Choose a reason for hiding this comment

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

s/behavior/relistBehavior/

if spec.RelistBehavior == sc.ServiceBrokerRelistBehaviorDuration && spec.RelistDuration == nil {
allErrs = append(
allErrs,
field.Required(fldPath.Child("relistDuration"), "relistDuration must be set if behavior is set to Duration"),
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like this still needs to be done

@pmorie
Copy link
Contributor

pmorie commented Sep 18, 2017

/test

@pmorie
Copy link
Contributor

pmorie commented Sep 19, 2017

LGTM

@pmorie pmorie added the LGTM2 label Sep 19, 2017
@pmorie pmorie merged commit e9328d3 into kubernetes-retired:master Sep 19, 2017
@pmorie pmorie added this to the 0.0.21 milestone Sep 19, 2017
jboyd01 pushed a commit to openshift/service-catalog that referenced this pull request Sep 20, 2017
* Base commit

* Test updates for passing

* storage_interface_test updates

* NOTE: May not be correct, but was required for passing the tests

* Set default Duration in fuzzer

* RelistDuration + defaults and tests

* Generated code

* Initial controller-manager changes

* Fix bug in the defaults with Duration

As written, was always setting Duration to 15m0s when Behavior was set
to Duration

* PR feedback items + updated tests

* Generated feedback

* Newline separate fields

* Defualt RelistDuration only when set to Duration

* Handle RelistDuration nil when set to Duration

* Log error and return false from shouldReconcileServiceBroker
when RelistDuration is set to nil despite a Duration behavior

* Comment updates, spacing and content

* Validation and default tests

* Bump nil RelistDuration log to error

* Add controller_broker tests to trigger new paths

* Remove todos

* Fix test names

* Minor spacing

* Additional tests and feedback response

* Add comment for non-negative RelistRequests

* PR feedback items

* Set default RelistBehavior only in the absence of a value
* Error messages tweaks
* Use correct Behavior constants from types rather than inline strings
* Validate nil RelistDuration when RelistBehavior is set to Manual
* Remove redundant validation
* Fix accidental binary AND
* Test negative value for RelistRequests fails validation

* Use non-default vals to test storage serialization

* Add updated types.generated.go

* Fix linter complaints

* Prune last of the inline str behaviors

* Error message update based on feedback

* Format API field godocs appropriately
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. LGTM1 LGTM2 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