github.com/hashicorp/packer@v1.14.3/website/content/docs/plugins/creation/custom-provisioners.mdx (about) 1 --- 2 description: > 3 Provisioners install and configure software prior to turning a machine into an image. Learn how to create custom provisioners that extend Packer functionality. 4 5 page_title: Create custom provisioners 6 --- 7 8 # Create Custom Provisioners 9 10 Packer provisioners install and configure software into a running machine prior to turning that machine into an image. For example, the [shell provisioner](/packer/docs/provisioners/shell) runs shell scripts within machines. 11 12 Provisioner plugins implement the [`packer.Provisioner`](https://pkg.go.dev/github.com/hashicorp/packer-plugin-sdk/packer#Provisioner) interface and are served 13 using the `plugin.ServeProvisioner` function. 14 15 ~> **Warning:** This is an advanced topic that requires strong knowledge of Packer and Packer plugins. 16 17 ## Before You Begin 18 19 We recommend reviewing the following resources before you begin development: 20 - [Developing Plugins - Overview](/packer/docs/plugins/creation) 21 - The [Go](https://go.dev/) language. You must write custom plugins in Go, so this guide assumes you are familiar with the language. 22 23 ## The Interface 24 25 The interface that must be implemented for a provisioner is the 26 [`packer.Provisioner`](https://pkg.go.dev/github.com/hashicorp/packer-plugin-sdk/packer#Provisioner) interface. It is reproduced below for reference. The 27 actual interface in the source code contains some basic documentation as well 28 explaining what each method should do. 29 30 ```go 31 type Provisioner interface { 32 ConfigSpec() hcldec.ObjectSpec 33 Prepare(...interface{}) error 34 Provision(context.Context, Ui, Communicator, map[string]interface{}) error 35 } 36 ``` 37 38 ### The `Prepare` Method 39 40 The `Prepare` method for each provisioner is called prior to any runs with the 41 configuration that was given in the template. This is passed in as an array of 42 `interface{}` types, but is generally `map[string]interface{}`. The prepare 43 method is responsible for translating this configuration into an internal 44 structure, validating it, and returning any errors. 45 46 For multiple parameters, they should be merged together into the final 47 configuration, with later parameters overwriting any previous configuration. 48 The exact semantics of the merge are left to the builder author. 49 50 For decoding the `interface{}` into a meaningful structure, the 51 [mapstructure](https://github.com/mitchellh/mapstructure) library is 52 recommended. Mapstructure will take an `interface{}` and decode it into an 53 arbitrarily complex struct. If there are any errors, it generates very human 54 friendly errors that can be returned directly from the prepare method. 55 56 While it is not actively enforced, **no side effects** should occur from 57 running the `Prepare` method. Specifically, don't create files, don't launch 58 virtual machines, etc. Prepare's purpose is solely to configure the builder and 59 validate the configuration. 60 61 The `Prepare` method is called very early in the build process so that errors 62 may be displayed to the user before anything actually happens. 63 64 ### The `ConfigSpec` Method 65 66 This method returns a `hcldec.ObjectSpec`, which is a spec necessary for using 67 HCL2 templates with Packer. For information on how to use and implement this 68 function, check our 69 [object spec docs](/packer/guides/hcl/component-object-spec) 70 71 ### The `Provision` Method 72 73 The `Provision` method is called when a machine is running and ready to be 74 provisioned. The provisioner should do its real work here. 75 76 The method takes two parameters: a `packer.Ui` and a `packer.Communicator`. The 77 UI can be used to communicate with the user what is going on. The communicator 78 is used to communicate with the running machine, and is guaranteed to be 79 connected at this point. 80 81 The provision method should not return until provisioning is complete. 82 83 The map[string]interface{} provides users with build-specific information, 84 like host and IP, provided by the `build` template engine. Provisioners may use 85 this information however they please, or not use it. 86 87 ## Using the Communicator 88 89 The `packer.Communicator` parameter and interface is used to communicate with 90 running machine. The machine may be local (in a virtual machine or container of 91 some sort) or it may be remote (in a cloud). The communicator interface 92 abstracts this away so that communication is the same overall. 93 94 The documentation around the [code 95 itself](https://godoc.org/github.com/hashicorp/packer-plugin-sdk/packer#Communicator) 96 is really great as an overview of how to use the interface. You should begin by 97 reading this. Once you have read it, you can see some example usage below: 98 99 ```go 100 // Build the remote command. 101 var cmd packer.RemoteCmd 102 cmd.Command = "echo foo" 103 104 // We care about stdout, so lets collect that into a buffer. Since 105 // we don't set stderr, that will just be discarded. 106 var stdout bytes.Buffer 107 cmd.Stdout = &stdout 108 109 // Start the command 110 if err := comm.Start(&cmd); err != nil { 111 panic(err) 112 } 113 114 // Wait for it to complete 115 cmd.Wait() 116 117 // Read the stdout! 118 fmt.Printf("Command output: %s", stdout.String()) 119 ```