github.com/kaixiang/packer@v0.5.2-0.20140114230416-1f5786b0d7f1/command/validate/command.go (about) 1 package validate 2 3 import ( 4 "flag" 5 "fmt" 6 cmdcommon "github.com/mitchellh/packer/common/command" 7 "github.com/mitchellh/packer/packer" 8 "log" 9 "strings" 10 ) 11 12 type Command byte 13 14 func (Command) Help() string { 15 return strings.TrimSpace(helpString) 16 } 17 18 func (c Command) Run(env packer.Environment, args []string) int { 19 var cfgSyntaxOnly bool 20 buildOptions := new(cmdcommon.BuildOptions) 21 22 cmdFlags := flag.NewFlagSet("validate", flag.ContinueOnError) 23 cmdFlags.Usage = func() { env.Ui().Say(c.Help()) } 24 cmdFlags.BoolVar(&cfgSyntaxOnly, "syntax-only", false, "check syntax only") 25 cmdcommon.BuildOptionFlags(cmdFlags, buildOptions) 26 if err := cmdFlags.Parse(args); err != nil { 27 return 1 28 } 29 30 args = cmdFlags.Args() 31 if len(args) != 1 { 32 cmdFlags.Usage() 33 return 1 34 } 35 36 if err := buildOptions.Validate(); err != nil { 37 env.Ui().Error(err.Error()) 38 env.Ui().Error("") 39 env.Ui().Error(c.Help()) 40 return 1 41 } 42 43 userVars, err := buildOptions.AllUserVars() 44 if err != nil { 45 env.Ui().Error(fmt.Sprintf("Error compiling user variables: %s", err)) 46 env.Ui().Error("") 47 env.Ui().Error(c.Help()) 48 return 1 49 } 50 51 // Parse the template into a machine-usable format 52 log.Printf("Reading template: %s", args[0]) 53 tpl, err := packer.ParseTemplateFile(args[0], userVars) 54 if err != nil { 55 env.Ui().Error(fmt.Sprintf("Failed to parse template: %s", err)) 56 return 1 57 } 58 59 if cfgSyntaxOnly { 60 env.Ui().Say("Syntax-only check passed. Everything looks okay.") 61 return 0 62 } 63 64 errs := make([]error, 0) 65 warnings := make(map[string][]string) 66 67 // The component finder for our builds 68 components := &packer.ComponentFinder{ 69 Builder: env.Builder, 70 Hook: env.Hook, 71 PostProcessor: env.PostProcessor, 72 Provisioner: env.Provisioner, 73 } 74 75 // Otherwise, get all the builds 76 builds, err := buildOptions.Builds(tpl, components) 77 if err != nil { 78 env.Ui().Error(err.Error()) 79 return 1 80 } 81 82 // Check the configuration of all builds 83 for _, b := range builds { 84 log.Printf("Preparing build: %s", b.Name()) 85 warns, err := b.Prepare() 86 if len(warns) > 0 { 87 warnings[b.Name()] = warns 88 } 89 if err != nil { 90 errs = append(errs, fmt.Errorf("Errors validating build '%s'. %s", b.Name(), err)) 91 } 92 } 93 94 if len(errs) > 0 { 95 env.Ui().Error("Template validation failed. Errors are shown below.\n") 96 for i, err := range errs { 97 env.Ui().Error(err.Error()) 98 99 if (i + 1) < len(errs) { 100 env.Ui().Error("") 101 } 102 } 103 104 return 1 105 } 106 107 if len(warnings) > 0 { 108 env.Ui().Say("Template validation succeeded, but there were some warnings.") 109 env.Ui().Say("These are ONLY WARNINGS, and Packer will attempt to build the") 110 env.Ui().Say("template despite them, but they should be paid attention to.\n") 111 112 for build, warns := range warnings { 113 env.Ui().Say(fmt.Sprintf("Warnings for build '%s':\n", build)) 114 for _, warning := range warns { 115 env.Ui().Say(fmt.Sprintf("* %s", warning)) 116 } 117 } 118 119 return 0 120 } 121 122 env.Ui().Say("Template validated successfully.") 123 return 0 124 } 125 126 func (Command) Synopsis() string { 127 return "check that a template is valid" 128 }