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

feat: add flag that checks whether any of the plans have been deactivated #115

Merged
merged 11 commits into from
Dec 11, 2023

Conversation

zucchinidev
Copy link
Contributor

@zucchinidev zucchinidev commented Dec 7, 2023

Checklist:

blgm and others added 2 commits December 4, 2023 15:46
…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)
@cf-gitbot
Copy link

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.

Copy link
Member

@blgm blgm left a 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.

README.md Outdated Show resolved Hide resolved
@@ -420,3 +447,173 @@ func fakeResponse() string {
}
`
}

// [FAILED] Expected
Copy link
Member

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.

receiver.Instances[i].OrganizationGUID = orgGUID
receiver.Instances[i].OrganizationName = orgName
for _, instance := range receiver.Instances {
plan := getPlanByGUID(plans, instance.ServicePlanGUID)
Copy link
Member

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.

Copy link
Contributor Author

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

Copy link
Contributor Author

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks!

instance.SpaceName = spaceName
instance.OrganizationGUID = orgGUID
instance.OrganizationName = orgName
instances = append(instances, instance)
Copy link
Member

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.

Copy link
Contributor Author

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

instance.ServicePlanName = plan.Name
instance.ServiceOfferingGUID = plan.ServiceOffering.GUID
instance.ServiceOfferingName = plan.ServiceOffering.Name
instance.ServicePlanMaintenanceInfoVersion = plan.MaintenanceInfoVersion
Copy link
Member

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.

}
}

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{}
Copy link
Member

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

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 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

Copy link
Contributor Author

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],
Copy link
Member

Choose a reason for hiding this comment

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

Much better!

@@ -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) {
Copy link
Member

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?

Copy link
Contributor Author

@zucchinidev zucchinidev Dec 8, 2023

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.

Copy link
Contributor Author

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

Available: false,
Name: "fake-deactivated-plan-1-name",
MaintenanceInfoVersion: "1.5.7",
ServiceOffering: ccapi.ServiceOffering{
Copy link
Member

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.

})

When("there are no deactivated plans", func() {
It("does the next thing", func() {
Copy link
Member

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh yes. Spot on.

zucchinidev and others added 8 commits December 8, 2023 12:04
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)
@zucchinidev
Copy link
Contributor Author

Thank you very much @blgm for your help

@zucchinidev zucchinidev requested a review from blgm December 8, 2023 16:36
@blgm blgm merged commit ce54f11 into main Dec 11, 2023
6 checks passed
@blgm blgm deleted the deactivated-plans branch December 11, 2023 12:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Development

Successfully merging this pull request may close these issues.

3 participants