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  }