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

Allow custom provisioning hooks #5972

Closed
maxking opened this issue Mar 5, 2018 · 3 comments
Closed

Allow custom provisioning hooks #5972

maxking opened this issue Mar 5, 2018 · 3 comments
Labels
builder/docker core Core components of Packer enhancement

Comments

@maxking
Copy link

maxking commented Mar 5, 2018

Right now, common.StepProvision.Run() uses packer.HookProvision to invoke the different provisioners. However, packer.HookProvision is hard-coded and there is no way to actually change the provisioning behavior.

Why would I need to do something like that?
My current use case is to use docker builder to create "layered" images. Since by default, packer commits the container after all the provisioners have run, it creates a single layer. By adding a CommitStep after every provisioner runs, I think I can have a good way to do layering and separating different contents in layers. Please let me know if you have any other/better way achieve this.

So, the way I plan to do this by having a separate implementation of Hook interface defined in packer/hooks.go and use that in common.StepProvision.Run() by allowing a configuration (called as a template in packer world?) to define what provision_hook I want to use. Then, my implmentation of Hook interface would take care of adding a CommitStep after each provisioner has run.

Do you think that makes any sense?

@mwhooker
Copy link
Contributor

mwhooker commented Mar 5, 2018

I looked into the hooks a while ago in order to do something similar, but found it wasn't as flexible as I needed it to be. fwiw my solution was to modify packer/provisioner.go directly 😭

I sympathize with your desire. I think committing between provisions makes a lot of sense, but I can't recommend modifying the hooking mechanism. We can't really support changes to this system, as our efforts now are focused on replacing it.

Take a look at builder/docker/communicator_test.go, where we use the Hooks to mock out tests.
What if you replaced the HookProvision hook in the docker builder with one that wraps the existing provisioners? I think that's something that might work okay.

	// Add hooks so the provisioners run during the build
	hooks := map[string][]packer.Hook{}
	hooks[packer.HookProvision] = []packer.Hook{
		&packer.ProvisionHook{
			Provisioners: []*packer.HookedProvisioner{
                                 // weave in commit provisioning here. 
			},
		},
	}
	hook := &packer.DispatchHook{Mapping: hooks}

I might be more amenable to something like that.

I'm going to close this since this isn't something we plan on working on, but if you wanted to submit a proof of concept PR, we can talk more about it there

@mwhooker mwhooker closed this as completed Mar 5, 2018
@mwhooker mwhooker added enhancement builder/docker core Core components of Packer labels Mar 5, 2018
@maxking
Copy link
Author

maxking commented Mar 6, 2018

Thanks @mwhooker for getting back to me so soon!

I am willing to submit a PoC PR, but I need some help to do that. I am having a bit of a trouble understanding some of the details of how provisioners are actually run today. I went through the documentation, but it doesn't say anything in detail.

This is mostly in respect to docker builder. So we define a bunch of multistep.Step instances, one of which is StepProvision and is supposed to run all the provisioners that are listed in the template file. StepProvision runs packer.HookProvision hook, which is supposed to point to an implementation of packer.Hook. However, I don't understand where is this mapping actually defined (or instantiated), the builder.Run seems to get this as a parameter from something that actually invokes builder.Run, which I can't seem to find, probably somewhere in core?

Is packer.ProvisionHook supposed to be what packer.HookProvision is mapped to and I should create something that looks like packer.ProvisionHook but commits after each of the provisioners have run?

packer.ProvisionHook seems to get "name" as a parameter, which I am not sure why? It doesn't seem to be used anywhere. It also doesn't have access to Statebag from multistep (to get the docker driver to do the actual commiting), but I think I can pass statebag as a parameter when I call hook.Run() in StepProvision, is that correct?

And third and final question, should I be using StepCommit or just directly call docker_driver.Commit() with information extracted from Statebag? I think calling Commit Directly makes more sense, simply because I think Steps are something that are meant to be called from multisteprunner instead of being invoked directly.

I am sorry for a lot of questions, I am quite new to Golang and so struggling a little with common design patterns and navigating through the codebase. And thanks a lot again for your help!

@ghost
Copy link

ghost commented Apr 2, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@ghost ghost locked and limited conversation to collaborators Apr 2, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
builder/docker core Core components of Packer enhancement
Projects
None yet
Development

No branches or pull requests

2 participants