-
Notifications
You must be signed in to change notification settings - Fork 2
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
feat: add flag that checks whether any of the plans have been deactivated #115
Conversation
…ated A new flag has been added. The flag `check-deactivated-plans` checks whether any of the plans have been deactivated. If any deactivated plans are found, the execution will fail. [#186597655](https://www.pivotaltracker.com/story/show/186597655)
We have created an issue in Pivotal Tracker to manage this: https://www.pivotaltracker.com/story/show/186638806 The labels on this github issue will be updated when the story is started. |
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.
Mostly this is great. There are a couple of things that definitely need to be resolved, most of my comments are stylistic and can be ignored.
@@ -420,3 +447,173 @@ func fakeResponse() string { | |||
} | |||
` | |||
} | |||
|
|||
// [FAILED] Expected |
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 probably not meant to be in the commit.
internal/ccapi/service_instances.go
Outdated
receiver.Instances[i].OrganizationGUID = orgGUID | ||
receiver.Instances[i].OrganizationName = orgName | ||
for _, instance := range receiver.Instances { | ||
plan := getPlanByGUID(plans, instance.ServicePlanGUID) |
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.
The loop in this function will be run for every service instance, so up to 5000 times. If the number of plans is small, it might be more efficient than the map
lookup that it replaced. I think this is fine, it's just good to be aware of situations where there's a loop within a loop.
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're totally right. I'm going to improve this part to avoid the loop in each iteration
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.
Reviewing the code after your suggestion, I realised that we can simplify the query parameter and the receiver.
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.
Thanks!
internal/ccapi/service_instances.go
Outdated
instance.SpaceName = spaceName | ||
instance.OrganizationGUID = orgGUID | ||
instance.OrganizationName = orgName | ||
instances = append(instances, instance) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having two slices will allocate twice as much memory. Again because we are currently limited to 5000 instances (as pagination is not implemented), I think this will not be a problem.
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.
Thanks for this advice. I usually prefer using value semantics instead of pointer semantics, but I think you are right. I know we’re not going to overflow memory by being limited to 5000 instances at most, but I’m going to change it. In this way we will avoid future problems if someone changes the number 5000 to something greater. On the contrary, if we implement pagination, it will be a perfect time to use value semantics
internal/ccapi/service_instances.go
Outdated
instance.ServicePlanName = plan.Name | ||
instance.ServiceOfferingGUID = plan.ServiceOffering.GUID | ||
instance.ServiceOfferingName = plan.ServiceOffering.Name | ||
instance.ServicePlanMaintenanceInfoVersion = plan.MaintenanceInfoVersion |
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.
Doing the decoration with service plan data here is much nicer than the old implementation.
internal/upgrader/upgrader.go
Outdated
} | ||
} | ||
|
||
func performUpgrade(api CFClient, upgradableInstances []ccapi.ServiceInstance, planVersions map[string]string, parallelUpgrades int, log Logger) error { | ||
func checkDeactivatedPlans(log Logger, upgradableInstances []ccapi.ServiceInstance) error { | ||
var ii []struct{} |
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 as to why this method was chosen rather than having a flag or counter?
deactivatedPlanFound := false
or
deactivatedPlansFound := 0
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 initially added the deactivated plans and logic to add the deactivated offerings. I deleted the offerings code and I did not change the code. As you suggested, I see more suitable to use the boolean flag deactivatedPlanFound := false
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.
Thank you very much!
@@ -74,7 +103,7 @@ func performUpgrade(api CFClient, upgradableInstances []ccapi.ServiceInstance, p | |||
UpgradeableIndex: i, | |||
ServiceInstanceName: instance.Name, | |||
ServiceInstanceGUID: instance.GUID, | |||
MaintenanceInfoVersion: planVersions[instance.ServicePlanGUID], |
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.
Much better!
internal/upgrader/upgrader.go
Outdated
@@ -118,7 +147,7 @@ func performDryRun(upgradableInstances []ccapi.ServiceInstance, log Logger) erro | |||
return nil | |||
} | |||
|
|||
func discoverServicePlans(api CFClient, brokerName string) (map[string]string, error) { | |||
func discoverServicePlans(api CFClient, brokerName string) ([]ccapi.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 wonder whether it could make sense to inline this function?
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.
Let me refactor it and see the benefits. I thought about it because now, the logic in the function is simple, but I did not want to change more code than needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much better. I added the refactor
internal/upgrader/upgrader_test.go
Outdated
Available: false, | ||
Name: "fake-deactivated-plan-1-name", | ||
MaintenanceInfoVersion: "1.5.7", | ||
ServiceOffering: ccapi.ServiceOffering{ |
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.
Here's an example of why it could be cleaner to flatten the ServiceOffering object into just two strings.
internal/upgrader/upgrader_test.go
Outdated
}) | ||
|
||
When("there are no deactivated plans", func() { | ||
It("does the next thing", func() { |
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.
Need to write this test and give it a better name. The aim is to check that if there are no deactivated plans, then it does not fail, and instead performs the next action - such as starting an upgrade or doing a dry run. Could potentially also be tested by running all the other tests with --check-deactivated-plans
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.
Oh yes. Spot on.
Co-authored-by: George Blue <blgm@users.noreply.github.com>
The loop in the function was executed for every service instance, so up to 5000 times. Probably, the number of plans is small, and we believe it is more efficient a map lookupd. Because we populate the instance with the plan, we no longer needed some fields. We simplify the query params and reduce network band usage. [#186597655](https://www.pivotaltracker.com/story/show/186597655)
We use pointer semantics instead of value semantics. We may change it in the future if we implement pagination. [#186597655](https://www.pivotaltracker.com/story/show/186597655)
Thank you very much @blgm for your help |
Checklist: