Example #1
0
func (c *Config) NewClientFromSettingsData() (*Client, error) {

	config := Config{}
	err := json.Unmarshal(c.Settings, &config)

	if err == nil {
		return config.NewClient()
	}

	return nil, err
}
Example #2
0
func readFileVars(path string) (map[string]string, error) {
	bytes, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	vars := make(map[string]string)
	err = jsonutil.Unmarshal(bytes, &vars)
	if err != nil {
		return nil, err
	}

	return vars, nil
}
Example #3
0
// ParseTemplate takes a byte slice and parses a Template from it, returning
// the template and possibly errors while loading the template. The error
// could potentially be a MultiError, representing multiple errors. Knowing
// and checking for this can be useful, if you wish to format it in a certain
// way.
func ParseTemplate(data []byte) (t *Template, err error) {
	var rawTplInterface interface{}
	err = jsonutil.Unmarshal(data, &rawTplInterface)
	if err != nil {
		return
	}

	// Decode the raw template interface into the actual rawTemplate
	// structure, checking for any extranneous keys along the way.
	var md mapstructure.Metadata
	var rawTpl rawTemplate
	decoderConfig := &mapstructure.DecoderConfig{
		Metadata: &md,
		Result:   &rawTpl,
	}

	decoder, err := mapstructure.NewDecoder(decoderConfig)
	if err != nil {
		return
	}

	err = decoder.Decode(rawTplInterface)
	if err != nil {
		return
	}

	errors := make([]error, 0)

	if len(md.Unused) > 0 {
		sort.Strings(md.Unused)
		for _, unused := range md.Unused {
			errors = append(
				errors, fmt.Errorf("Unknown root level key in template: '%s'", unused))
		}
	}

	t = &Template{}
	t.Variables = make(map[string]string)
	t.Builders = make(map[string]RawBuilderConfig)
	t.Hooks = rawTpl.Hooks
	t.PostProcessors = make([][]RawPostProcessorConfig, len(rawTpl.PostProcessors))
	t.Provisioners = make([]RawProvisionerConfig, len(rawTpl.Provisioners))

	// Gather all the variables
	for k, v := range rawTpl.Variables {
		t.Variables[k] = v
	}

	// Gather all the builders
	for i, v := range rawTpl.Builders {
		var raw RawBuilderConfig
		if err := mapstructure.Decode(v, &raw); err != nil {
			if merr, ok := err.(*mapstructure.Error); ok {
				for _, err := range merr.Errors {
					errors = append(errors, fmt.Errorf("builder %d: %s", i+1, err))
				}
			} else {
				errors = append(errors, fmt.Errorf("builder %d: %s", i+1, err))
			}

			continue
		}

		if raw.Type == "" {
			errors = append(errors, fmt.Errorf("builder %d: missing 'type'", i+1))
			continue
		}

		// Attempt to get the name of the builder. If the "name" key
		// missing, use the "type" field, which is guaranteed to exist
		// at this point.
		if raw.Name == "" {
			raw.Name = raw.Type
		}

		// Check if we already have a builder with this name and error if so
		if _, ok := t.Builders[raw.Name]; ok {
			errors = append(errors, fmt.Errorf("builder with name '%s' already exists", raw.Name))
			continue
		}

		// Now that we have the name, remove it from the config - as the builder
		// itself doesn't know about, and it will cause a validation error.
		delete(v, "name")

		raw.RawConfig = v

		t.Builders[raw.Name] = raw
	}

	// Gather all the post-processors. This is a complicated process since there
	// are actually three different formats that the user can use to define
	// a post-processor.
	for i, rawV := range rawTpl.PostProcessors {
		rawPP, err := parsePostProcessor(i, rawV)
		if err != nil {
			errors = append(errors, err...)
			continue
		}

		t.PostProcessors[i] = make([]RawPostProcessorConfig, len(rawPP))
		configs := t.PostProcessors[i]
		for j, pp := range rawPP {
			config := &configs[j]
			if err := mapstructure.Decode(pp, config); err != nil {
				if merr, ok := err.(*mapstructure.Error); ok {
					for _, err := range merr.Errors {
						errors = append(errors, fmt.Errorf("Post-processor #%d.%d: %s", i+1, j+1, err))
					}
				} else {
					errors = append(errors, fmt.Errorf("Post-processor %d.%d: %s", i+1, j+1, err))
				}

				continue
			}

			if config.Type == "" {
				errors = append(errors, fmt.Errorf("Post-processor %d.%d: missing 'type'", i+1, j+1))
				continue
			}

			// Remove the input keep_input_artifact option
			delete(pp, "keep_input_artifact")

			config.RawConfig = pp
		}
	}

	// Gather all the provisioners
	for i, v := range rawTpl.Provisioners {
		raw := &t.Provisioners[i]
		if err := mapstructure.Decode(v, raw); err != nil {
			if merr, ok := err.(*mapstructure.Error); ok {
				for _, err := range merr.Errors {
					errors = append(errors, fmt.Errorf("provisioner %d: %s", i+1, err))
				}
			} else {
				errors = append(errors, fmt.Errorf("provisioner %d: %s", i+1, err))
			}

			continue
		}

		if raw.Type == "" {
			errors = append(errors, fmt.Errorf("provisioner %d: missing 'type'", i+1))
			continue
		}

		// The provisioners not only don't need or want the override settings
		// (as they are processed as part of the preparation below), but will
		// actively reject them as invalid configuration.
		delete(v, "override")

		// Verify that the override keys exist...
		for name, _ := range raw.Override {
			if _, ok := t.Builders[name]; !ok {
				errors = append(
					errors, fmt.Errorf("provisioner %d: build '%s' not found for override", i+1, name))
			}
		}

		raw.RawConfig = v
	}

	if len(t.Builders) == 0 {
		errors = append(errors, fmt.Errorf("No builders are defined in the template."))
	}

	// If there were errors, we put it into a MultiError and return
	if len(errors) > 0 {
		err = &MultiError{errors}
		t = nil
		return
	}

	return
}
Example #4
0
// ParseTemplate takes a byte slice and parses a Template from it, returning
// the template and possibly errors while loading the template. The error
// could potentially be a MultiError, representing multiple errors. Knowing
// and checking for this can be useful, if you wish to format it in a certain
// way.
//
// The second parameter, vars, are the values for a set of user variables.
func ParseTemplate(data []byte, vars map[string]string) (t *Template, err error) {
	var rawTplInterface interface{}
	err = jsonutil.Unmarshal(data, &rawTplInterface)
	if err != nil {
		return
	}

	// Decode the raw template interface into the actual rawTemplate
	// structure, checking for any extranneous keys along the way.
	var md mapstructure.Metadata
	var rawTpl rawTemplate
	decoderConfig := &mapstructure.DecoderConfig{
		Metadata: &md,
		Result:   &rawTpl,
	}

	decoder, err := mapstructure.NewDecoder(decoderConfig)
	if err != nil {
		return
	}

	err = decoder.Decode(rawTplInterface)
	if err != nil {
		return
	}

	if rawTpl.MinimumPackerVersion != "" {
		// TODO: NOPE! Replace this
		Version := "1.0"
		vCur, err := version.NewVersion(Version)
		if err != nil {
			panic(err)
		}
		vReq, err := version.NewVersion(rawTpl.MinimumPackerVersion)
		if err != nil {
			return nil, fmt.Errorf(
				"'minimum_packer_version' error: %s", err)
		}

		if vCur.LessThan(vReq) {
			return nil, fmt.Errorf(
				"Template requires Packer version %s. "+
					"Running version is %s.",
				vReq, vCur)
		}
	}

	errors := make([]error, 0)

	if len(md.Unused) > 0 {
		sort.Strings(md.Unused)
		for _, unused := range md.Unused {
			errors = append(
				errors, fmt.Errorf("Unknown root level key in template: '%s'", unused))
		}
	}

	t = &Template{}
	t.Description = rawTpl.Description
	t.Variables = make(map[string]RawVariable)
	t.Builders = make(map[string]RawBuilderConfig)
	t.Hooks = rawTpl.Hooks
	t.PostProcessors = make([][]RawPostProcessorConfig, len(rawTpl.PostProcessors))
	t.Provisioners = make([]RawProvisionerConfig, len(rawTpl.Provisioners))

	// Gather all the variables
	for k, v := range rawTpl.Variables {
		var variable RawVariable
		variable.Required = v == nil

		// Create a new mapstructure decoder in order to decode the default
		// value since this is the only value in the regular template that
		// can be weakly typed.
		decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
			Result:           &variable.Default,
			WeaklyTypedInput: true,
		})
		if err != nil {
			// This should never happen.
			panic(err)
		}

		err = decoder.Decode(v)
		if err != nil {
			errors = append(errors,
				fmt.Errorf("Error decoding default value for user var '%s': %s", k, err))
			continue
		}

		// Set the value of this variable if we have it
		if val, ok := vars[k]; ok {
			variable.HasValue = true
			variable.Value = val
			delete(vars, k)
		}

		t.Variables[k] = variable
	}

	// Gather all the builders
	for i, v := range rawTpl.Builders {
		var raw RawBuilderConfig
		if err := mapstructure.Decode(v, &raw); err != nil {
			if merr, ok := err.(*mapstructure.Error); ok {
				for _, err := range merr.Errors {
					errors = append(errors, fmt.Errorf("builder %d: %s", i+1, err))
				}
			} else {
				errors = append(errors, fmt.Errorf("builder %d: %s", i+1, err))
			}

			continue
		}

		if raw.Type == "" {
			errors = append(errors, fmt.Errorf("builder %d: missing 'type'", i+1))
			continue
		}

		// Attempt to get the name of the builder. If the "name" key
		// missing, use the "type" field, which is guaranteed to exist
		// at this point.
		if raw.Name == "" {
			raw.Name = raw.Type
		}

		// Check if we already have a builder with this name and error if so
		if _, ok := t.Builders[raw.Name]; ok {
			errors = append(errors, fmt.Errorf("builder with name '%s' already exists", raw.Name))
			continue
		}

		// Now that we have the name, remove it from the config - as the builder
		// itself doesn't know about, and it will cause a validation error.
		delete(v, "name")

		raw.RawConfig = v

		t.Builders[raw.Name] = raw
	}

	// Gather all the post-processors. This is a complicated process since there
	// are actually three different formats that the user can use to define
	// a post-processor.
	for i, rawV := range rawTpl.PostProcessors {
		rawPP, err := parsePostProcessor(i, rawV)
		if err != nil {
			errors = append(errors, err...)
			continue
		}

		configs := make([]RawPostProcessorConfig, 0, len(rawPP))
		for j, pp := range rawPP {
			var config RawPostProcessorConfig
			if err := mapstructure.Decode(pp, &config); err != nil {
				if merr, ok := err.(*mapstructure.Error); ok {
					for _, err := range merr.Errors {
						errors = append(errors,
							fmt.Errorf("Post-processor #%d.%d: %s", i+1, j+1, err))
					}
				} else {
					errors = append(errors,
						fmt.Errorf("Post-processor %d.%d: %s", i+1, j+1, err))
				}

				continue
			}

			if config.Type == "" {
				errors = append(errors,
					fmt.Errorf("Post-processor %d.%d: missing 'type'", i+1, j+1))
				continue
			}

			// Remove the input keep_input_artifact option
			config.TemplateOnlyExcept.Prune(pp)
			delete(pp, "keep_input_artifact")

			// Verify that the only settings are good
			if errs := config.TemplateOnlyExcept.Validate(t.Builders); len(errs) > 0 {
				for _, err := range errs {
					errors = append(errors,
						fmt.Errorf("Post-processor %d.%d: %s", i+1, j+1, err))
				}

				continue
			}

			config.RawConfig = pp

			// Add it to the list of configs
			configs = append(configs, config)
		}

		t.PostProcessors[i] = configs
	}

	// Gather all the provisioners
	for i, v := range rawTpl.Provisioners {
		raw := &t.Provisioners[i]
		if err := mapstructure.Decode(v, raw); err != nil {
			if merr, ok := err.(*mapstructure.Error); ok {
				for _, err := range merr.Errors {
					errors = append(errors, fmt.Errorf("provisioner %d: %s", i+1, err))
				}
			} else {
				errors = append(errors, fmt.Errorf("provisioner %d: %s", i+1, err))
			}

			continue
		}

		if raw.Type == "" {
			errors = append(errors, fmt.Errorf("provisioner %d: missing 'type'", i+1))
			continue
		}

		// Delete the keys that we used
		raw.TemplateOnlyExcept.Prune(v)
		delete(v, "override")

		// Verify that the override keys exist...
		for name, _ := range raw.Override {
			if _, ok := t.Builders[name]; !ok {
				errors = append(
					errors, fmt.Errorf("provisioner %d: build '%s' not found for override", i+1, name))
			}
		}

		// Verify that the only settings are good
		if errs := raw.TemplateOnlyExcept.Validate(t.Builders); len(errs) > 0 {
			for _, err := range errs {
				errors = append(errors,
					fmt.Errorf("provisioner %d: %s", i+1, err))
			}
		}

		// Setup the pause settings
		if raw.RawPauseBefore != "" {
			duration, err := time.ParseDuration(raw.RawPauseBefore)
			if err != nil {
				errors = append(
					errors, fmt.Errorf(
						"provisioner %d: pause_before invalid: %s",
						i+1, err))
			}

			raw.pauseBefore = duration
		}

		// Remove the pause_before setting if it is there so that we don't
		// get template validation errors later.
		delete(v, "pause_before")

		raw.RawConfig = v
	}

	if len(t.Builders) == 0 {
		errors = append(errors, fmt.Errorf("No builders are defined in the template."))
	}

	// Verify that all the variable sets were for real variables.
	for k, _ := range vars {
		errors = append(errors, fmt.Errorf("Unknown user variables: %s", k))
	}

	// If there were errors, we put it into a MultiError and return
	if len(errors) > 0 {
		err = &MultiError{errors}
		t = nil
		return
	}

	return
}