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