github.com/wilsonge/packer@v1.3.2/command/fix.go (about)

     1  package command
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"log"
     8  	"os"
     9  	"strings"
    10  
    11  	"github.com/hashicorp/packer/fix"
    12  	"github.com/hashicorp/packer/template"
    13  
    14  	"github.com/posener/complete"
    15  )
    16  
    17  type FixCommand struct {
    18  	Meta
    19  }
    20  
    21  func (c *FixCommand) Run(args []string) int {
    22  	var flagValidate bool
    23  	flags := c.Meta.FlagSet("fix", FlagSetNone)
    24  	flags.BoolVar(&flagValidate, "validate", true, "")
    25  	flags.Usage = func() { c.Ui.Say(c.Help()) }
    26  	if err := flags.Parse(args); err != nil {
    27  		return 1
    28  	}
    29  
    30  	args = flags.Args()
    31  	if len(args) != 1 {
    32  		flags.Usage()
    33  		return 1
    34  	}
    35  
    36  	// Read the file for decoding
    37  	tplF, err := os.Open(args[0])
    38  	if err != nil {
    39  		c.Ui.Error(fmt.Sprintf("Error opening template: %s", err))
    40  		return 1
    41  	}
    42  	defer tplF.Close()
    43  
    44  	// Decode the JSON into a generic map structure
    45  	var templateData map[string]interface{}
    46  	decoder := json.NewDecoder(tplF)
    47  	if err := decoder.Decode(&templateData); err != nil {
    48  		c.Ui.Error(fmt.Sprintf("Error parsing template: %s", err))
    49  		return 1
    50  	}
    51  
    52  	// Close the file since we're done with that
    53  	tplF.Close()
    54  
    55  	input := templateData
    56  	for _, name := range fix.FixerOrder {
    57  		var err error
    58  		fixer, ok := fix.Fixers[name]
    59  		if !ok {
    60  			panic("fixer not found: " + name)
    61  		}
    62  
    63  		log.Printf("Running fixer: %s", name)
    64  		input, err = fixer.Fix(input)
    65  		if err != nil {
    66  			c.Ui.Error(fmt.Sprintf("Error fixing: %s", err))
    67  			return 1
    68  		}
    69  	}
    70  
    71  	var output bytes.Buffer
    72  	encoder := json.NewEncoder(&output)
    73  	if err := encoder.Encode(input); err != nil {
    74  		c.Ui.Error(fmt.Sprintf("Error encoding: %s", err))
    75  		return 1
    76  	}
    77  
    78  	var indented bytes.Buffer
    79  	if err := json.Indent(&indented, output.Bytes(), "", "  "); err != nil {
    80  		c.Ui.Error(fmt.Sprintf("Error encoding: %s", err))
    81  		return 1
    82  	}
    83  
    84  	result := indented.String()
    85  	result = strings.Replace(result, `\u003c`, "<", -1)
    86  	result = strings.Replace(result, `\u003e`, ">", -1)
    87  	c.Ui.Say(result)
    88  
    89  	if flagValidate {
    90  		// Attempt to parse and validate the template
    91  		tpl, err := template.Parse(strings.NewReader(result))
    92  		if err != nil {
    93  			c.Ui.Error(fmt.Sprintf(
    94  				"Error! Fixed template fails to parse: %s\n\n"+
    95  					"This is usually caused by an error in the input template.\n"+
    96  					"Please fix the error and try again.",
    97  				err))
    98  			return 1
    99  		}
   100  		if err := tpl.Validate(); err != nil {
   101  			c.Ui.Error(fmt.Sprintf(
   102  				"Error! Fixed template failed to validate: %s\n\n"+
   103  					"This is usually caused by an error in the input template.\n"+
   104  					"Please fix the error and try again.",
   105  				err))
   106  			return 1
   107  		}
   108  	}
   109  
   110  	return 0
   111  }
   112  
   113  func (*FixCommand) Help() string {
   114  	helpText := `
   115  Usage: packer fix [options] TEMPLATE
   116  
   117    Reads the JSON template and attempts to fix known backwards
   118    incompatibilities. The fixed template will be outputted to standard out.
   119  
   120    If the template cannot be fixed due to an error, the command will exit
   121    with a non-zero exit status. Error messages will appear on standard error.
   122  
   123  Fixes that are run:
   124  
   125    iso-md5                    Replaces "iso_md5" in builders with newer
   126                               "iso_checksum"
   127    createtime                 Replaces ".CreateTime" in builder configs with
   128                               "{{timestamp}}"
   129    virtualbox-gaattach        Updates VirtualBox builders using
   130                               "guest_additions_attach" to use
   131                               "guest_additions_mode"
   132    pp-vagrant-override        Replaces old-style provider overrides for the
   133                               Vagrant post-processor to new-style as of Packer
   134                               0.5.0.
   135    virtualbox-rename          Updates "virtualbox" builders to "virtualbox-iso"
   136    vmware-rename              Updates "vmware" builders to "vmware-iso"
   137    parallels-headless         Removes unused "headless" setting from Parallels
   138                               builders
   139    parallels-deprecations     Removes deprecated "parallels_tools_host_path" from
   140                               Parallels builders
   141    sshkeypath                 Updates builders using "ssh_key_path" to use
   142                               "ssh_private_key_file"
   143    sshdisableagent            Updates builders using "ssh_disable_agent" to use
   144                               "ssh_disable_agent_forwarding"
   145    manifest-filename          Updates "manifest" post-processor so any "filename"
   146                               field is renamed to "output"
   147    amazon-shutdown_behavior   Changes "shutdown_behaviour" to "shutdown_behavior"
   148                               in Amazon builders
   149    amazon-enhanced-networking Replaces "enhanced_networking" in builders with
   150                               "ena_support"
   151    amazon-private-ip          Replaces "ssh_private_ip": true in amazon builders
   152                               with "ssh_interface": "private_ip"
   153    docker-email               Removes "login_email" from the Docker builder
   154    powershell-escapes         Removes PowerShell escapes from user env vars and
   155                               elevated username and password strings
   156    hyperv-deprecations        Removes the deprecated "vhd_temp_path" setting from
   157                               Hyper-V ISO builder templates
   158    hyperv-vmxc-typo           Corrects a typo in the "clone_from_vmxc_path"
   159                               setting. Replaces with "clone_from_vmcx_path".
   160    vmware-compaction          Adds "skip_compaction = true" to "vmware-iso"
   161                               builders with incompatible disk_type_id
   162  
   163  Options:
   164  
   165    -validate=true      If true (default), validates the fixed template.
   166  `
   167  
   168  	return strings.TrimSpace(helpText)
   169  }
   170  
   171  func (c *FixCommand) Synopsis() string {
   172  	return "fixes templates from old versions of packer"
   173  }
   174  
   175  func (c *FixCommand) AutocompleteArgs() complete.Predictor {
   176  	return complete.PredictNothing
   177  }
   178  
   179  func (c *FixCommand) AutocompleteFlags() complete.Flags {
   180  	return complete.Flags{
   181  		"-validate": complete.PredictNothing,
   182  	}
   183  }