github.com/hashicorp/packer@v1.14.3/config.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package main 5 6 import ( 7 "encoding/json" 8 "fmt" 9 "io" 10 "log" 11 "os" 12 "strings" 13 14 packersdk "github.com/hashicorp/packer-plugin-sdk/packer" 15 "github.com/hashicorp/packer/command" 16 "github.com/hashicorp/packer/packer" 17 ) 18 19 type config struct { 20 DisableCheckpoint bool `json:"disable_checkpoint"` 21 DisableCheckpointSignature bool `json:"disable_checkpoint_signature"` 22 RawBuilders map[string]string `json:"builders"` 23 RawProvisioners map[string]string `json:"provisioners"` 24 RawPostProcessors map[string]string `json:"post-processors"` 25 26 Plugins *packer.PluginConfig 27 } 28 29 // decodeConfig decodes configuration in JSON format from the given io.Reader into 30 // the config object pointed to. 31 func decodeConfig(r io.Reader, c *config) error { 32 decoder := json.NewDecoder(r) 33 return decoder.Decode(c) 34 } 35 36 // LoadExternalComponentsFromConfig loads plugins defined in RawBuilders, RawProvisioners, and RawPostProcessors. 37 func (c *config) LoadExternalComponentsFromConfig() error { 38 // helper to build up list of plugin paths 39 extractPaths := func(m map[string]string) []string { 40 paths := make([]string, 0, len(m)) 41 for _, v := range m { 42 paths = append(paths, v) 43 } 44 45 return paths 46 } 47 48 var pluginPaths []string 49 pluginPaths = append(pluginPaths, extractPaths(c.RawProvisioners)...) 50 pluginPaths = append(pluginPaths, extractPaths(c.RawBuilders)...) 51 pluginPaths = append(pluginPaths, extractPaths(c.RawPostProcessors)...) 52 53 if len(pluginPaths) == 0 { 54 return nil 55 } 56 57 componentList := &strings.Builder{} 58 for _, path := range pluginPaths { 59 fmt.Fprintf(componentList, "- %s\n", path) 60 } 61 62 return fmt.Errorf("Your configuration file describes some legacy components: \n%s"+ 63 "Packer does not support these mono-component plugins anymore.\n"+ 64 "Please refer to our Installing Plugins docs for an overview of how to manage installation of local plugins:\n"+ 65 "https://developer.hashicorp.com/packer/docs/plugins/install-plugins", 66 componentList.String()) 67 } 68 69 // This is a proper packer.BuilderFunc that can be used to load packersdk.Builder 70 // implementations from the defined plugins. 71 func (c *config) StartBuilder(name string) (packersdk.Builder, error) { 72 log.Printf("Loading builder: %s\n", name) 73 return c.Plugins.Builders.Start(name) 74 } 75 76 // This is a proper implementation of packer.HookFunc that can be used 77 // to load packersdk.Hook implementations from the defined plugins. 78 func (c *config) StarHook(name string) (packersdk.Hook, error) { 79 log.Printf("Loading hook: %s\n", name) 80 return c.Plugins.Client(name).Hook() 81 } 82 83 // This is a proper packersdk.PostProcessorFunc that can be used to load 84 // packersdk.PostProcessor implementations from defined plugins. 85 func (c *config) StartPostProcessor(name string) (packersdk.PostProcessor, error) { 86 log.Printf("Loading post-processor: %s", name) 87 return c.Plugins.PostProcessors.Start(name) 88 } 89 90 // This is a proper packer.ProvisionerFunc that can be used to load 91 // packer.Provisioner implementations from defined plugins. 92 func (c *config) StartProvisioner(name string) (packersdk.Provisioner, error) { 93 log.Printf("Loading provisioner: %s\n", name) 94 return c.Plugins.Provisioners.Start(name) 95 } 96 97 func (c *config) discoverInternalComponents() error { 98 // Get the packer binary path 99 packerPath, err := os.Executable() 100 if err != nil { 101 log.Printf("[ERR] Error loading exe directory: %s", err) 102 return err 103 } 104 105 for builder := range command.Builders { 106 builder := builder 107 if !c.Plugins.Builders.Has(builder) { 108 c.Plugins.Builders.Set(builder, func() (packersdk.Builder, error) { 109 args := []string{"execute"} 110 111 if packer.PackerUseProto { 112 args = append(args, "--protobuf") 113 } 114 115 args = append(args, fmt.Sprintf("packer-builder-%s", builder)) 116 117 return c.Plugins.Client(packerPath, args...).Builder() 118 }) 119 } 120 } 121 122 for provisioner := range command.Provisioners { 123 provisioner := provisioner 124 if !c.Plugins.Provisioners.Has(provisioner) { 125 c.Plugins.Provisioners.Set(provisioner, func() (packersdk.Provisioner, error) { 126 args := []string{"execute"} 127 128 if packer.PackerUseProto { 129 args = append(args, "--protobuf") 130 } 131 132 args = append(args, fmt.Sprintf("packer-provisioner-%s", provisioner)) 133 134 return c.Plugins.Client(packerPath, args...).Provisioner() 135 }) 136 } 137 } 138 139 for postProcessor := range command.PostProcessors { 140 postProcessor := postProcessor 141 if !c.Plugins.PostProcessors.Has(postProcessor) { 142 c.Plugins.PostProcessors.Set(postProcessor, func() (packersdk.PostProcessor, error) { 143 args := []string{"execute"} 144 145 if packer.PackerUseProto { 146 args = append(args, "--protobuf") 147 } 148 149 args = append(args, fmt.Sprintf("packer-post-processor-%s", postProcessor)) 150 151 return c.Plugins.Client(packerPath, args...).PostProcessor() 152 }) 153 } 154 } 155 156 for dataSource := range command.Datasources { 157 dataSource := dataSource 158 if !c.Plugins.DataSources.Has(dataSource) { 159 c.Plugins.DataSources.Set(dataSource, func() (packersdk.Datasource, error) { 160 args := []string{"execute"} 161 162 if packer.PackerUseProto { 163 args = append(args, "--protobuf") 164 } 165 166 args = append(args, fmt.Sprintf("packer-datasource-%s", dataSource)) 167 168 return c.Plugins.Client(packerPath, args...).Datasource() 169 }) 170 } 171 } 172 173 return nil 174 }