github.com/jerryclinesmith/packer@v0.3.7/common/command/template.go (about)

     1  package command
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	jsonutil "github.com/mitchellh/packer/common/json"
     7  	"github.com/mitchellh/packer/packer"
     8  	"io/ioutil"
     9  	"log"
    10  	"os"
    11  )
    12  
    13  // BuildOptions is a set of options related to builds that can be set
    14  // from the command line.
    15  type BuildOptions struct {
    16  	UserVarFiles []string
    17  	UserVars     map[string]string
    18  	Except       []string
    19  	Only         []string
    20  }
    21  
    22  // Validate validates the options
    23  func (f *BuildOptions) Validate() error {
    24  	if len(f.Except) > 0 && len(f.Only) > 0 {
    25  		return errors.New("Only one of '-except' or '-only' may be specified.")
    26  	}
    27  
    28  	if len(f.UserVarFiles) > 0 {
    29  		for _, path := range f.UserVarFiles {
    30  			if _, err := os.Stat(path); err != nil {
    31  				return fmt.Errorf("Cannot access: %s", path)
    32  			}
    33  		}
    34  	}
    35  
    36  	return nil
    37  }
    38  
    39  // AllUserVars returns the user variables, compiled from both the
    40  // file paths and the vars on the command line.
    41  func (f *BuildOptions) AllUserVars() (map[string]string, error) {
    42  	all := make(map[string]string)
    43  
    44  	// Copy in the variables from the files
    45  	for _, path := range f.UserVarFiles {
    46  		fileVars, err := readFileVars(path)
    47  		if err != nil {
    48  			return nil, err
    49  		}
    50  
    51  		for k, v := range fileVars {
    52  			all[k] = v
    53  		}
    54  	}
    55  
    56  	// Copy in the command-line vars
    57  	for k, v := range f.UserVars {
    58  		all[k] = v
    59  	}
    60  
    61  	return all, nil
    62  }
    63  
    64  // Builds returns the builds out of the given template that pass the
    65  // configured options.
    66  func (f *BuildOptions) Builds(t *packer.Template, cf *packer.ComponentFinder) ([]packer.Build, error) {
    67  	buildNames := t.BuildNames()
    68  
    69  	checks := make(map[string][]string)
    70  	checks["except"] = f.Except
    71  	checks["only"] = f.Only
    72  	for t, ns := range checks {
    73  		for _, n := range ns {
    74  			found := false
    75  			for _, actual := range buildNames {
    76  				if actual == n {
    77  					found = true
    78  					break
    79  				}
    80  			}
    81  
    82  			if !found {
    83  				return nil, fmt.Errorf(
    84  					"Unknown build in '%s' flag: %s", t, n)
    85  			}
    86  		}
    87  	}
    88  
    89  	builds := make([]packer.Build, 0, len(buildNames))
    90  	for _, buildName := range buildNames {
    91  		if len(f.Except) > 0 {
    92  			found := false
    93  			for _, except := range f.Except {
    94  				if buildName == except {
    95  					found = true
    96  					break
    97  				}
    98  			}
    99  
   100  			if found {
   101  				log.Printf("Skipping build '%s' because specified by -except.", buildName)
   102  				continue
   103  			}
   104  		}
   105  
   106  		if len(f.Only) > 0 {
   107  			found := false
   108  			for _, only := range f.Only {
   109  				if buildName == only {
   110  					found = true
   111  					break
   112  				}
   113  			}
   114  
   115  			if !found {
   116  				log.Printf("Skipping build '%s' because not specified by -only.", buildName)
   117  				continue
   118  			}
   119  		}
   120  
   121  		log.Printf("Creating build: %s", buildName)
   122  		build, err := t.Build(buildName, cf)
   123  		if err != nil {
   124  			return nil, fmt.Errorf("Failed to create build '%s': \n\n%s", buildName, err)
   125  		}
   126  
   127  		builds = append(builds, build)
   128  	}
   129  
   130  	return builds, nil
   131  }
   132  
   133  func readFileVars(path string) (map[string]string, error) {
   134  	bytes, err := ioutil.ReadFile(path)
   135  	if err != nil {
   136  		return nil, err
   137  	}
   138  
   139  	vars := make(map[string]string)
   140  	err = jsonutil.Unmarshal(bytes, &vars)
   141  	if err != nil {
   142  		return nil, err
   143  	}
   144  
   145  	return vars, nil
   146  }