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

Refactor Context into separate cloudup and nodeup types #14444

Merged
merged 1 commit into from
Dec 18, 2022

Conversation

johngmyers
Copy link
Member

@johngmyers johngmyers commented Oct 22, 2022

This separates the Context, Task, and related types to distinguish those used in cloudup from those used in nodeup. Followup PRs will move some fields only used in cloudup into CloudupContext.

The basics of this refactor are:

type Context[T SubContext] struct {
	 ...

	T T
}

type SubContext interface {
	CloudupContext | NodeupContext
}
type CloudupContext struct{}
type NodeupContext struct{}

type Task[T SubContext] interface {
	Run(*Context[T]) error
}

type ModelBuilderContext[T SubContext] struct {
	Tasks              map[string]Task[T]
	LifecycleOverrides map[string]Lifecycle
}

@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. area/nodeup labels Oct 22, 2022
@k8s-ci-robot k8s-ci-robot requested review from drekle and liranp October 22, 2022 20:32
@k8s-ci-robot k8s-ci-robot added area/provider/aws Issues or PRs related to aws provider area/provider/azure Issues or PRs related to azure provider area/provider/digitalocean Issues or PRs related to digitalocean provider area/provider/gcp Issues or PRs related to gcp provider area/provider/hetzner Issues or PRs related to Hetzner provider area/provider/openstack Issues or PRs related to openstack provider area/provider/spotinst Issues or PRs related to spotinst provider labels Oct 22, 2022
@johngmyers
Copy link
Member Author

/retest

@olemarkus
Copy link
Member

I really like this change, but since it introduces generics and such, I'll let others the opportunity to voice their opinions as well.

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Oct 23, 2022
@hakman
Copy link
Member

hakman commented Oct 23, 2022

Let's keep this open until @justinsb has a chance to take a look. Also, keep in mind that KubeCon NA is next week.

@justinsb
Copy link
Member

Is there a broader goal here @johngmyers ? I do think we should adopt generics, and I do like the idea of separating the cloud and node tasks from each other. But right now this puts relatively complex type signatures into every Task. I tried using a type alias (type NodeTask Task[NodeupContext]), but then go did not treat map[string]NodeTask the same as map[string]Task[NodeupContext]. That might get fixed over time, but right now this is made awkward by the current limitations of generics.

@johngmyers
Copy link
Member Author

@justinsb the goal is fundamentally to make it clear through the type system that the two different types of tasks have different things available to them. When I was refactoring the PKI code I was particularly frustrated by the fact that, without generics, I couldn't represent through the type system that cloudup tasks could create new keypairs, whereas nodeup tasks could only read the keypairs that already existed.

I'm also a bit annoyed that nodeup tasks have to implement HasLifecycle, though this PR doesn't address that.

@justinsb
Copy link
Member

OK, I think it's a good goal, the generic syntax is just pretty awkward right now. I'm almost inclined to see if we can just make them different types and not use generics, but when I've tried it ends up with problems on the execution engine and localtarget. So I appreciate that you actually got this working :-) Can we discuss more in office hours?

@johngmyers
Copy link
Member Author

/hold
/kind office-hours

@k8s-ci-robot k8s-ci-robot added do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. kind/office-hours labels Oct 26, 2022
@justinsb
Copy link
Member

I had a rough go in #14457, let's talk about the alternatives...

I would really like to use generics BTW, the place which really bugs me is if we can replace our reflection-backed dispatching on the Render / Find etc methods with something like

type NodeTask[T] interface {
  Find(c *fi.NodeContext) (*T, error)
  Render(c *fi.NodeContext, a,e, changes *T) (error)
...
}

@johngmyers
Copy link
Member Author

We might be able to handle things like Find/Render with interfaces, like HasAddress is implemented.

@johngmyers
Copy link
Member Author

Could we implement a DefaultDeltaTask struct which would be embedded by all the Tasks that want the DefaultDeltaRunbehavior?

type DefaultDeltaRun[T SubContext] struct {
   // Name *string ?
}

func (e *DefaultDeltaRun[T])) Run(c *fi.Context[T]) error {
  //Similar to body of current DefaultDeltaRunMethod
}

@johngmyers
Copy link
Member Author

Might need to be

type DefaultDeltaRun[T HasFind, C SubContext] struct {
   // Name *string ?
}

func (e *DefaultDeltaRun[T, C])) Run(c *fi.Context[C]) error {
  //Similar to body of current DefaultDeltaRunMethod
}

@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Oct 30, 2022
@johngmyers
Copy link
Member Author

johngmyers commented Nov 1, 2022

To answer my question about DefaultDeltaTask:

I tried creating:

type DeltaRun struct{}

var _ Task = &DeltaRun{}

func (d *DeltaRun) Run(c *Context) error {
	return defaultDeltaRunMethod(d, c)
}

I also had to make fi.getDependencies() ignore anonymous struct fields.

The problem was that defaultDeltaRunMethod got a reference to the embedded empty struct, not the enclosing struct, so reflection didn't find any of the enclosing struct's methods.

I then tried:

type HasFind interface {
	Task
	Find(c *Context) (HasFind, error)
}

and then modifying (*executor) forkJoin():

			if hasFind, ok := ts.task.(HasFind); ok {
				results[index] = defaultDeltaRunMethod(hasFind, e.context)
			} else {
				results[index] = ts.task.Run(e.context)
			}

There were two problems:

  1. Go doesn't permit union types to have methods, so I couldn't define Task itself to be a type that contains either Run or Find. That means HasFind still had to define a Run method (that would be never called).

  2. In order for the (HasFind) type assertion to work, all the Find methods had to weaken the type of their first return value to HasFind. I couldn't find a way in Go to type-assert that it had to be a pointer to its own type.

In all, such a refactor doesn't look like it would gain much.

@justinsb
Copy link
Member

I think I had a breakthrough ... I like the approach, my objection has always been about exposing the generic implementation to all the tasks etc.

While type definitions didn't work right (type CloudupTask Task[CloudupContext] confused the compiler), type aliases did work type CloudupTask = Task[CloudupContext].

I've sent a PR to this PR: johngmyers#21 ... although I'm not sure that the tests are running there, so I might have to send a WIP PR here instead.

Let me know what you think @johngmyers ... I can probably rebase if needed, but this would make me happy - we get generics, we split the types, and we don't have to repeat the generic type names everywhere.

I don't love my name CloudupSubContext, but one good thing there is that these names shouldn't escape outside of fi, so they can be awkward :-)

@k8s-ci-robot k8s-ci-robot removed the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Dec 17, 2022
@k8s-ci-robot k8s-ci-robot added the area/provider/scaleway Issues or PRs related to Scaleway provider label Dec 17, 2022
@k8s-ci-robot k8s-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Dec 17, 2022
@johngmyers
Copy link
Member Author

/retest

@johngmyers
Copy link
Member Author

/hold cancel

@k8s-ci-robot k8s-ci-robot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Dec 17, 2022
@johngmyers
Copy link
Member Author

Failing e2e tests should be fixed by #14800

@johngmyers
Copy link
Member Author

/retest

@johngmyers
Copy link
Member Author

@justinsb is this good to go now?

@justinsb
Copy link
Member

I'm good with it if you are :-)

/approve
/lgtm

/hold to make sure you're happy too @johngmyers

This is really nice BTW - thanks for doing this!

@k8s-ci-robot k8s-ci-robot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Dec 18, 2022
@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Dec 18, 2022
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: justinsb

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Dec 18, 2022
@johngmyers
Copy link
Member Author

/hold cancel

@k8s-ci-robot k8s-ci-robot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Dec 18, 2022
@k8s-ci-robot k8s-ci-robot merged commit 741ca8f into kubernetes:master Dec 18, 2022
@k8s-ci-robot k8s-ci-robot added this to the v1.26 milestone Dec 18, 2022
@johngmyers johngmyers deleted the task-generic branch December 18, 2022 21:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. area/nodeup area/provider/aws Issues or PRs related to aws provider area/provider/azure Issues or PRs related to azure provider area/provider/digitalocean Issues or PRs related to digitalocean provider area/provider/gcp Issues or PRs related to gcp provider area/provider/hetzner Issues or PRs related to Hetzner provider area/provider/openstack Issues or PRs related to openstack provider area/provider/scaleway Issues or PRs related to Scaleway provider area/provider/spotinst Issues or PRs related to spotinst provider cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants