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

Dependency factory #337

Merged
merged 5 commits into from
Sep 29, 2021
Merged

Dependency factory #337

merged 5 commits into from
Sep 29, 2021

Conversation

g-gaston
Copy link
Member

Resolves #310

In order to facilitate adding/removing/changing the dependencies for our types and at the same time reduce the duplicated code/work at the cmd level (that's where we usually do DI), this OR add a factory to build a dependency graph.

It's a pretty simple implementation but it achieves:

  • Only building whatever is necessary based on the input
  • Only build each entity once
  • Graph encapsulation (the caller doesn't need to know anything about the dependencies)
  • Changing the graph is fairly simple

Some drawbacks:

  • It requires to write a bit of boring code every time we want to add a new entity to the graph
  • It requires to mark the dependencies for a certain entity explicitly (no inference)

There is definitely room for improvement but I believe the current state is good enough to start using it.

I also considered using https://github.com/google/wire instead, but with the amount of dependencies we have, it was going to take the same amount of time to learn how to use it than the time that saves by generating the boilerplate code. It's something that we could reconsider in the future if we start spending too much time adding entities to the factory.

There might be other places where we can use the factory (maybe E2E tests). I just started with the commands since they were the most obvious place.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@abhay-krishna abhay-krishna added approved size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Sep 28, 2021
Copy link
Member

@danbudris danbudris left a comment

Choose a reason for hiding this comment

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

so....to make sure I understand.

you're maintaining a stack of idempotent dependency creation functions; each ensures that its own dependencies are included in the stack before it, if necessary.

When we .Build() the dependency graph , each dependency is built in first-in-first-out order, ensuring that each dependency is built in the correct order, without repeating (the 'idempotent' nil checks).

Is that right?

@g-gaston
Copy link
Member Author

so....to make sure I understand.

you're maintaining a stack of idempotent dependency creation functions; each ensures that its own dependencies are included in the stack before it, if necessary.

When we .Build() the dependency graph , each dependency is built in first-in-first-out order, ensuring that each dependency is built in the correct order, without repeating (the 'idempotent' nil checks).

Is that right?

That's correct :)

Copy link
Member

@vivek-koppuru vivek-koppuru left a comment

Choose a reason for hiding this comment

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

Neat! Looks a lot cleaner now 😄

Comment on lines +43 to +45
WithExecutableBuilder(ctx, clusterSpec.UseImageMirror(eksaToolsImage.VersionedImage())).
WithWriterFolder(clusterSpec.Name).
WithDiagnosticCollectorImage(clusterSpec.VersionsBundle.Eksa.DiagnosticCollector.VersionedImage())
Copy link
Member

Choose a reason for hiding this comment

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

What's the motivation of keeping these here vs with all the other With* methods? Is it because these are the ones we think are common regardless of command and provider? I notice that we include the diagnostic collector image which we don't use in all the commands.

If we don't need these methods, then we would only need a New method. I was thinking about whether something like below made more sense.

deps := dependencies.New().
                 WithSpec(spec).
                 WithExecutableBuilder(...)
                 ...

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, this method is just a helper when creating dependencies based on a particular clusterSpec. In that case, there are certain configurations that are always the same. The collector image is not always used but is always the same for the same clusterSpec, that's why is here.
To be precise, these With* methods in the helper are slightly different than the other ones, since they don't necessarily build dependencies, but they configure the factory to be able to build the real dependencies.

Regarding New(), I believe that'sNewFactory(), isn't it? (it' called NewFactory instead of just New because it doesn't build the dependencies but a factory to build dependencies)

Copy link
Member

Choose a reason for hiding this comment

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

I get the distinction now, this looks good to me

Copy link
Member

@vivek-koppuru vivek-koppuru 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

@mrajashree mrajashree left a comment

Choose a reason for hiding this comment

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

🚀

@abhay-krishna
Copy link
Member

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: danbudris, g-gaston, mrajashree, vivek-koppuru

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:
  • OWNERS [danbudris,g-gaston,mrajashree,vivek-koppuru]

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

@abhay-krishna abhay-krishna merged commit e54ec13 into aws:main Sep 29, 2021
rothgar pushed a commit to rothgar/eks-anywhere that referenced this pull request Nov 20, 2021
* Move skip ip check option to method argument in provider factory

* Fixed package name for kubectl client

* Add constructor to build local executable builder

* Add dependency factory

* Updated commands in cmd to use the dependency factory
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved lgtm 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.

Dependency factory
5 participants