github.com/mmcquillan/packer@v1.1.1-0.20171009221028-c85cf0483a5d/command/inspect.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"strings"
     7  
     8  	"github.com/hashicorp/packer/template"
     9  )
    10  
    11  type InspectCommand struct {
    12  	Meta
    13  }
    14  
    15  func (c *InspectCommand) Run(args []string) int {
    16  	flags := c.Meta.FlagSet("inspect", FlagSetNone)
    17  	flags.Usage = func() { c.Ui.Say(c.Help()) }
    18  	if err := flags.Parse(args); err != nil {
    19  		return 1
    20  	}
    21  
    22  	args = flags.Args()
    23  	if len(args) != 1 {
    24  		flags.Usage()
    25  		return 1
    26  	}
    27  
    28  	// Parse the template
    29  	tpl, err := template.ParseFile(args[0])
    30  	if err != nil {
    31  		c.Ui.Error(fmt.Sprintf("Failed to parse template: %s", err))
    32  		return 1
    33  	}
    34  
    35  	// Convenience...
    36  	ui := c.Ui
    37  
    38  	// Description
    39  	if tpl.Description != "" {
    40  		ui.Say("Description:\n")
    41  		ui.Say(tpl.Description + "\n")
    42  	}
    43  
    44  	// Variables
    45  	if len(tpl.Variables) == 0 {
    46  		ui.Say("Variables:\n")
    47  		ui.Say("  <No variables>")
    48  	} else {
    49  		requiredHeader := false
    50  		for k, v := range tpl.Variables {
    51  			if v.Required {
    52  				if !requiredHeader {
    53  					requiredHeader = true
    54  					ui.Say("Required variables:\n")
    55  				}
    56  
    57  				ui.Machine("template-variable", k, v.Default, "1")
    58  				ui.Say("  " + k)
    59  			}
    60  		}
    61  
    62  		if requiredHeader {
    63  			ui.Say("")
    64  		}
    65  
    66  		ui.Say("Optional variables and their defaults:\n")
    67  		keys := make([]string, 0, len(tpl.Variables))
    68  		max := 0
    69  		for k := range tpl.Variables {
    70  			keys = append(keys, k)
    71  			if len(k) > max {
    72  				max = len(k)
    73  			}
    74  		}
    75  
    76  		sort.Strings(keys)
    77  
    78  		for _, k := range keys {
    79  			v := tpl.Variables[k]
    80  			if v.Required {
    81  				continue
    82  			}
    83  
    84  			padding := strings.Repeat(" ", max-len(k))
    85  			output := fmt.Sprintf("  %s%s = %s", k, padding, v.Default)
    86  
    87  			ui.Machine("template-variable", k, v.Default, "0")
    88  			ui.Say(output)
    89  		}
    90  	}
    91  
    92  	ui.Say("")
    93  
    94  	// Builders
    95  	ui.Say("Builders:\n")
    96  	if len(tpl.Builders) == 0 {
    97  		ui.Say("  <No builders>")
    98  	} else {
    99  		keys := make([]string, 0, len(tpl.Builders))
   100  		max := 0
   101  		for k := range tpl.Builders {
   102  			keys = append(keys, k)
   103  			if len(k) > max {
   104  				max = len(k)
   105  			}
   106  		}
   107  
   108  		sort.Strings(keys)
   109  
   110  		for _, k := range keys {
   111  			v := tpl.Builders[k]
   112  			padding := strings.Repeat(" ", max-len(k))
   113  			output := fmt.Sprintf("  %s%s", k, padding)
   114  			if v.Name != v.Type {
   115  				output = fmt.Sprintf("%s (%s)", output, v.Type)
   116  			}
   117  
   118  			ui.Machine("template-builder", k, v.Type)
   119  			ui.Say(output)
   120  
   121  		}
   122  	}
   123  
   124  	ui.Say("")
   125  
   126  	// Provisioners
   127  	ui.Say("Provisioners:\n")
   128  	if len(tpl.Provisioners) == 0 {
   129  		ui.Say("  <No provisioners>")
   130  	} else {
   131  		for _, v := range tpl.Provisioners {
   132  			ui.Machine("template-provisioner", v.Type)
   133  			ui.Say(fmt.Sprintf("  %s", v.Type))
   134  		}
   135  	}
   136  
   137  	ui.Say("\nNote: If your build names contain user variables or template\n" +
   138  		"functions such as 'timestamp', these are processed at build time,\n" +
   139  		"and therefore only show in their raw form here.")
   140  
   141  	return 0
   142  }
   143  
   144  func (*InspectCommand) Help() string {
   145  	helpText := `
   146  Usage: packer inspect TEMPLATE
   147  
   148    Inspects a template, parsing and outputting the components a template
   149    defines. This does not validate the contents of a template (other than
   150    basic syntax by necessity).
   151  
   152  Options:
   153  
   154    -machine-readable  Machine-readable output
   155  `
   156  
   157  	return strings.TrimSpace(helpText)
   158  }
   159  
   160  func (c *InspectCommand) Synopsis() string {
   161  	return "see components of a template"
   162  }