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

Simplify waiting for the instance to be done #1636

Closed
wants to merge 2 commits into from

Conversation

zen-dog
Copy link
Contributor

@zen-dog zen-dog commented Aug 6, 2020

Summary:
previous logic relied on figuring out the plan in progress and the plan status from the instance status. However, since 1.15 this can be simplified by using the Spec.PlanExecution which already has the relevant information.

Signed-off-by: Aleksey Dukhovniy alex.dukhovniy@googlemail.com

Summary:
previous logic relied on figuring out the plan in progress and the plan status from the instance status. However, since 1.15 this can be simplified by using the `Spec.PlanExecution` which already has the relevant information.

Signed-off-by: Aleksey Dukhovniy <alex.dukhovniy@googlemail.com>
Copy link
Contributor

@alenkacz alenkacz left a comment

Choose a reason for hiding this comment

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

Still have couple of questions before I am ready to approve :)

@@ -120,7 +120,7 @@ func status(kc *kudo.Client, options *Options, ns string) error {
} else {
break
}
done, err := kc.IsInstanceDone(instance, nil)
done, err := kc.IsInstanceDone(instance, instance.Spec.PlanExecution.PlanName)
Copy link
Contributor

Choose a reason for hiding this comment

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

why are you passing in instance as well as field on that instance? 🤔 should we just pass in an instance?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good eye ;) basically, because I don't know how this method will be used:

  1. the passed instance has to be the one returned by Create/Update/Patch method because it has the PlanExecution.PlanName field set to the right plan
  2. if you simply fetch the instance later, the plan might be already done (which is not a big deal), or there might be already another plan (from a later update) in progress

Passing a plan explicitly was an attempt to make the usage of this method slightly safer.

@@ -73,12 +73,13 @@ func Package(
return nil
}

if err := install.Instance(client, resources.Instance); err != nil {
installed, err := install.Instance(client, resources.Instance)
Copy link
Contributor

Choose a reason for hiding this comment

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

hmm why is this better than what was here before? 🤔

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 ok with this, tbh, it enforces the "always use the returned object if you create one" pattern... It allows you to update the object later one:

pod := corev1.Pod{ ... }
pod := client.Create(pod)
pod.metadata.Labels["something"] = "addedlabel"
pod := client.Update(pod)

This won't work if you try to do:

pod := corev1.Pod{ ... }
client.Create(pod)
pod.metadata.Labels["something"] = "addedlabel"
client.Update(pod)

because of the added fields from the api-server...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

see my comment above

Copy link
Member

@ANeumann82 ANeumann82 left a comment

Choose a reason for hiding this comment

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

Looks generally good, needs a bit of cleanup though

status := lastPlanStatus.Status
if status.IsFinished() {
clog.V(2).Printf("plan status for %q is finished\n", instance.Name)
func (c *Client) IsInstanceDone(instance *v1beta1.Instance, plan string) (bool, 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 think this func should move to the "instance_helpers.go" and have the instance as the receiver. I'm not sure why it's part of the kudo.Client..

And then it should probably be something like

func (i *v1beta1.Instance) IsPlanDone(plan string) (bool, error) {

Maybe with an additional

func ( i *v1beta1.Instance) IsCurrentPlanDone() (bool, error) {

@@ -73,12 +73,13 @@ func Package(
return nil
}

if err := install.Instance(client, resources.Instance); err != nil {
installed, err := install.Instance(client, resources.Instance)
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 ok with this, tbh, it enforces the "always use the returned object if you create one" pattern... It allows you to update the object later one:

pod := corev1.Pod{ ... }
pod := client.Create(pod)
pod.metadata.Labels["something"] = "addedlabel"
pod := client.Update(pod)

This won't work if you try to do:

pod := corev1.Pod{ ... }
client.Create(pod)
pod.metadata.Labels["something"] = "addedlabel"
client.Update(pod)

because of the added fields from the api-server...

Comment on lines 277 to 278
// IsInstanceDone provides a check on instance to see if it is "finished" without retries
// oldInstance is nil if there is no previous instance
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 should probably be adjusted. I have no idea what "finished" means in the context here... Also, oldInstance isn't a parameter anymore

Copy link
Member

@porridge porridge left a comment

Choose a reason for hiding this comment

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

TBH I'm not a big fan of using spec for holding status information, and still hope this can be changed at some point. This change seems to move us further away from that...

@zen-dog
Copy link
Contributor Author

zen-dog commented Aug 7, 2020

TBH I'm not a big fan of using spec for holding status information, and still hope this can be changed at some point. This change seems to move us further away from that...

The introduced logic relies on Spec.PlanExecution.PlanName which expresses the user intent to run a plan (e.g. from kudoctl plan trigger...). This field belongs certainly to a Spec and not to Status. The Spec.PlanExecution.Status field on the other hand is only used for logging.

@porridge
Copy link
Member

TBH I'm not a big fan of using spec for holding status information, and still hope this can be changed at some point. This change seems to move us further away from that...

The introduced logic relies on Spec.PlanExecution.PlanName which expresses the user intent to run a plan (e.g. from kudoctl plan trigger...). This field belongs certainly to a Spec and not to Status.

Well, if it was purely intent, then we would not be able to determine state from it, but yet we do :-)
Since the value is controlled by the webhook which in turn looks at status, the boundary between state and status has become quite fuzzy. This is one of my concerns...

…o instance

Signed-off-by: Andreas Neumann <aneumann@mesosphere.com>
Copy link
Member

@ANeumann82 ANeumann82 left a comment

Choose a reason for hiding this comment

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

lgtm 🚢

@zen-dog
Copy link
Contributor Author

zen-dog commented Oct 7, 2020

We discussed this offline with @ANeumann82 a while ago and I don't remember the exact reasoning but we were both not happy with this PR. Something about handling the "edginess" of waiting for a plan to be over.

@zen-dog zen-dog closed this Oct 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants