github.com/timsutton/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 }