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

Implement Build Providers as Plugins #2125

Open
2 tasks
richbai90 opened this issue Jun 1, 2022 · 11 comments
Open
2 tasks

Implement Build Providers as Plugins #2125

richbai90 opened this issue Jun 1, 2022 · 11 comments
Labels
suggestion Idea for maintainers to consider. Do not take this issue until triaged.

Comments

@richbai90
Copy link

What design is being proposed?
Move build provider functionality to plugin architecture

Additional Context
There are a few questions open now (#2097 #1823 #1665 #1366 ...) about configuring various components of the build container that porter runs in. These issues have various work arounds or have been put on hold pending further review. Security concerns, implementation details, and other questions stall these proposals. I suggest in order to allow the core team to focus their energy on the core product, allowing build providers to be created via plugins. I see the following benefits in this:

  • Improve maintenance by modularizing source code
  • Promote CNAB standard by making Porter a tool for implementing CNAB workflows without dependency on one technology
  • FutureProofing Porter by being ready to adopt the newest technologies if/when Docker phases out
  • Provide esoteric features to those with specific use cases that don't align with the core goals of Porter/CNAB
  • Allow Core team to maintain core features and official build providers

Risks/Concerns
Allowing anyone to create a build provider raises possibilities of security risks, as well as potential tech debt, and maintenance issues. That said, it's not any more risky than the current plugin functionality, and I assume that the core team will adopt the docker provider as an officially maintained plugin.

What other approaches were considered?
Many work-arounds, hacks, and other fragile methods

Implementation details
I have done my best to replicate the existing plugin architecture for build providers at https://github.com/richbai90/porter-advanced-build-plugins It compiles, but I'm not a go expert (started learning for this project) so I'm sure it could be improved.

Checklist

  • An announcement of this proposal has been sent to the Porter mailing list: https://porter.sh/mailing-list
  • This proposal has remained open for at least one week, to allow time for community feedback.
@richbai90
Copy link
Author

Moving discussion to mailing list. Will reopen if this gains traction

@carolynvs carolynvs reopened this Jun 1, 2022
@carolynvs
Copy link
Member

Thanks for the proposal, @richbai90! I'm reopening because we just need a heads up of proposals sent to the mailing list (so people know that it exists). The discussion doesn't have to happen there though.

@carolynvs
Copy link
Member

Right now we have 2 components in Porter that aren't plugins but could become plugins if needed:

  • build drivers - responsible for building the OCI image associated with the bundle. Porter v0.38 has a docker build driver, which was replaced in v1 with a buildkit driver. In the future, it would be great to have a podman driver.
  • runtime drivers - responsible for running the bundle container. We have a few runtime drivers: debug (just prints out some helpful info but doesn't run a a container), docker, and kubernetes (used by the porter operator).

When you say "build provider" I'm guessing that you actually are interested in making the runtime drivers pluggable since the issues you linked to are mostly interested in changing how much access the system that the porter client is running on.

Runtime drivers are actually a CNAB concept, and are not implemented in Porter. You can find the implementations of the above runtime drivers here in the cnab-go library: https://github.com/cnabio/cnab-go/tree/main/driver

If you wanted to try prototyping Porter to support different implementations, I'd recommend that you point porter at a fork of the cnab-go library and tweak https://github.com/getporter/porter/blob/release/v1/pkg/cnab/drivers/drivers.go (work off of the release/v1 branch) so that Porter knows how to select your new driver.

I think you could get pretty far with minimal changes to Porter and without having to try to change Porter to switch from "drivers to plugins" which would be a bunch of extra work when all you are interested in is proving out a new type of driver.

I'm down for making either build or runtime drivers pluggable if that's what ends up making sense. In the meantime, I am really interested in seeing how you expose the host to to the bundle through the new driver. As you have seen, I've been a bit stuck on what's a good way to do while working within the confines of the CNAB spec. 😀 If we can make it work with the current CNAB spec that's best, but at times Porter does make changes with the intention of circling back and updating the CNAB spec to match after we've vetted a feature (like we are doing with dependencies).

I'm happy to help answer questions or bounce ideas back and forth as you work on a new driver!

@richbai90
Copy link
Author

That sounds great, I'll give that a shot. I still think making something pluggable makes a lot of sense long term for both build drivers and runtime drivers. You already mentioned supporting Podman as a build driver, and I'm sure there are other tools that might make sense in various use cases. Allowing individuals and teams to support their own use cases and benefit the community at the same time seems to fit nicely into the ethos of this project.

@richbai90
Copy link
Author

@carolynvs Can you explain extensions as they relate to drivers? I've read the spec, and understand that extensions are a means of extending the underlying json bundle with custom metadata that may or may not be required to successfully perform an action on the bundle.

The confusing part to me is that in the case of Docker for instance, Docker is a build driver, runtime driver, and mixin. The Docker extension permits the setting of the privileged flag, but this is required only when using the Docker mixin. Notwithstanding, the extension is declared in the porter source under cnab/drivers/docker.go. This suggests to me that the extension is actually a mandatory piece of the runtime or builder, but I can't figure out how it's all related.

One other thing I'm trying to figure out, how is a driver registered as a runtime or build driver? I see in the porter source that the docker driver is registered with buildx in pkg/build/buildkit/buildx.go but I don't see where the runtime behavior is specified.

@carolynvs
Copy link
Member

Yup, I'm fine with making them plugins eventually. In the meantime though I'm suggesting changing the driver so that you can prototype the new features without also having to take on making the drivers plugin friendly. 👍

@richbai90
Copy link
Author

Upon further examination I think I've answered my own questions. Please let me know if I'm off track

The confusing part to me is that in the case of Docker for instance, Docker is a build driver, runtime driver, and mixin. The Docker extension permits the setting of the privileged flag, but this is required only when using the Docker mixin. Notwithstanding, the extension is declared in the porter source under cnab/drivers/docker.go. This suggests to me that the extension is actually a mandatory piece of the runtime or builder, but I can't figure out how it's all related.

I mistook the path, it's actually under cnab/docker.go and isn't related to the docker driver, but is an extension to make features of the docker mixin work correctly (IE privileged flag). It might be good to expose that to the mixin architecture but that's for another day.

One other thing I'm trying to figure out, how is a driver registered as a runtime or build driver? I see in the porter source that the docker driver is registered with buildx in pkg/build/buildkit/buildx.go but I don't see where the runtime behavior is specified.

It's not. A driver implements a simple interface, Run whichexecutes the operation inside of the invocation image and Handles which receives an ImageType* and answers whether this driver supports that type. The rest is implementation specific. In the case of docker its exec function handles the functionality of a given operation. Where porter gets involved in all of this is still a bit fuzzy to me

@carolynvs
Copy link
Member

Where porter gets involved in all of this is still a bit fuzzy to me

I'm not sure what you mean by that? The docker and k8s CNAB drivers have a simple interface like you pointed out, and there isn't any way to run them independently from Porter. Porter handles waves hands everything else that sets up getting to the point where we can ask the CNAB driver to execute a bundle. 😀

I see in the porter source that the docker driver is registered with buildx in pkg/build/buildkit/buildx.go but I don't see where the runtime behavior is specified.

Porter's install command (and the others that run a bundle) have a --driver flag that eventually is handled in the cnab package, where porter selects a CNAB driver to use to execute the bundle.

https://github.com/getporter/porter/blob/release/v1/pkg/cnab/drivers/drivers.go

@richbai90
Copy link
Author

Porter's install command (and the others that run a bundle) have a --driver flag that eventually is handled in the cnab package, where porter selects a CNAB driver to use to execute the bundle.

That answers my question. Basically how porter interfaces with the CNAB package. I apologize for not being on top of this issue, I had to tackle another more pressing concern, but I'm back to this. Thank you for leaving it open.

@carolynvs
Copy link
Member

I'm happy to leave it open as it's a great suggestion. No need to apologize for only engaging when you have time, that's pretty much the expectation for all of us. If you have any more questions, just let me know. 👍

@richbai90
Copy link
Author

I have a working implementation in PR #2167. This case was pretty easy since the the go-cnab api exposes all the options available to the docker go package, so I didn't need to make any changes to the go-cnab library. It doesn't make drivers pluggable, but for a near term solution it should solve most of the needs. The best part about it is that on its own it changes very little because there are no Mixins that take advantage of the options. It does open a world of capabilities to Mixin developers that would benefit from these sorts of options.

@carolynvs carolynvs added the suggestion Idea for maintainers to consider. Do not take this issue until triaged. label Jul 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
suggestion Idea for maintainers to consider. Do not take this issue until triaged.
Projects
None yet
Development

No branches or pull requests

2 participants