Пример #1
0
func parseRestartPolicy(result *structs.RestartPolicy, obj *hclobj.Object) error {
	var restartHclObj *hclobj.Object
	var m map[string]interface{}
	if restartHclObj = obj.Get("restart", false); restartHclObj == nil {
		return nil
	}
	if err := hcl.DecodeObject(&m, restartHclObj); err != nil {
		return err
	}

	if delay, ok := m["delay"]; ok {
		d, err := toDuration(delay)
		if err != nil {
			return fmt.Errorf("Invalid Delay time in restart policy: %v", err)
		}
		result.Delay = d
	}

	if interval, ok := m["interval"]; ok {
		i, err := toDuration(interval)
		if err != nil {
			return fmt.Errorf("Invalid Interval time in restart policy: %v", err)
		}
		result.Interval = i
	}

	if attempts, ok := m["attempts"]; ok {
		a, err := toInteger(attempts)
		if err != nil {
			return fmt.Errorf("Invalid value in attempts: %v", err)
		}
		result.Attempts = a
	}
	return nil
}
Пример #2
0
func parseRawObject(key string, hcltree *hclObj.Object, errors *multierror.Error) (apisOut []*hclObj.Object) {
	if apis := hcltree.Get(key, false); apis != nil {
		for _, api := range apis.Elem(true) {
			apisOut = append(apisOut, api)
		}
	} else {
		errors = multierror.Append(errors, fmt.Errorf("No job_store was specified in the configuration"))
	}
	return apisOut
}
Пример #3
0
func parseRawBool(key string, hcltree *hclObj.Object, errors *multierror.Error) bool {
	if rawValue := hcltree.Get(key, false); rawValue != nil {
		if rawValue.Type != hclObj.ValueTypeBool {
			errors = multierror.Append(errors, fmt.Errorf("Invalid type assigned to property: %s. Expected string type, Found %s", key, rawValue.Type))
		} else {
			return rawValue.Value.(bool)
		}
	} else {
		errors = multierror.Append(errors, fmt.Errorf("Property: %s not specified in the configuration", key))
	}
	return false
}
Пример #4
0
func parseRawArray(key string, object *hclObj.Object, errors *multierror.Error) []string {
	output := []string{}
	if rawValue := object.Get(key, false); rawValue != nil {
		switch rawValue.Type {
		case hclObj.ValueTypeString:
			output = append(output, rawValue.Value.(string))
		case hclObj.ValueTypeList:
			for _, m := range rawValue.Elem(true) {
				output = append(output, m.Value.(string))
			}
		}
	}
	return output
}
Пример #5
0
func parseJobTrigger(jobNode *hclObj.Object, errors *multierror.Error) TriggerConfig {
	var triggerConfig TriggerConfig
	if t := jobNode.Get("trigger", false); t != nil {
		err := hcl.DecodeObject(&triggerConfig, t)
		if err != nil {
			errors = multierror.Append(errors, err)
		}
	}
	return triggerConfig
	// cron := parseCron(jobNode.Get("trigger", false), errors)
	// maxExecs := parseMaxExecutions(jobNode.Get("trigger", false), errors)
	// return TriggerConfig{
	// 	Cron:          cron,
	// 	MaxExecutions: maxExecs,
	// }
}
Пример #6
0
func parseMaxExecutions(jobNode *hclObj.Object, errors *multierror.Error) string {
	if rawCron := jobNode.Get("max_executions", false); rawCron != nil {
		if rawCron.Len() > 1 {
			errors = multierror.Append(errors, fmt.Errorf("max_executions was specified more than once"))
		} else {
			if rawCron.Type != hclObj.ValueTypeString {
				errors = multierror.Append(errors, fmt.Errorf("max_executions was specified as an invalid type - expected string, found %s", rawCron.Type))
			} else {
				return rawCron.Value.(string)
			}
		}
	} else {
		errors = multierror.Append(errors, fmt.Errorf("No max_executions was specified in the configuration"))
	}
	return ""
}
Пример #7
0
func parseVersion(hcltree *hclObj.Object, errors *multierror.Error) string {
	if rawVersion := hcltree.Get("version", false); rawVersion != nil {
		if rawVersion.Len() > 1 {
			errors = multierror.Append(errors, fmt.Errorf("Version was specified more than once"))
		} else {
			if rawVersion.Type != hclObj.ValueTypeString {
				errors = multierror.Append(errors, fmt.Errorf("Version was specified as an invalid type - expected string, found %s", rawVersion.Type))
			} else {
				return rawVersion.Value.(string)
			}
		}
	} else {
		errors = multierror.Append(errors, fmt.Errorf("No version was specified in the configuration"))
	}
	return "*** Error"
}
Пример #8
0
func parseRawChain(hclObj *hclObj.Object, errors *multierror.Error) chain.ChainSpec {
	if rawChain := hclObj.Get("chain", false); rawChain != nil {
		// iterate over all modules for a given chain
		for _, mod := range rawChain.Elem(true) {
			modules := parseRawModules(mod, errors)
			return chain.NewWithModules(modules)
		}
	}
	return chain.New()
}
Пример #9
0
func parseJobs(hcltree *hclObj.Object, errors *multierror.Error) []JobConfig {
	outputConfig := make([]JobConfig, 0)
	if rawJobs := hcltree.Get("job", false); rawJobs != nil {
		if rawJobs.Type != hclObj.ValueTypeObject {
			errors = multierror.Append(errors, fmt.Errorf("job was specified as an invalid type - expected list, found %s", rawJobs.Type))
		} else {
			arrayJobs := rawJobs.Elem(true)
			for _, job := range arrayJobs {
				outputConfig = append(outputConfig, parseJob(job, errors))
			}
		}

	} else {
		if len(outputConfig) == 0 {
			errors = multierror.Append(errors, fmt.Errorf("No job_store was specified in the configuration"))
		}
	}
	return outputConfig

}
Пример #10
0
func parseJobStore(hcltree *hclObj.Object, errors *multierror.Error) []string {
	hosts := make([]string, 0)
	if jobStore := hcltree.Get("job_store", false); jobStore != nil {
		if jobStore.Len() > 1 {
			errors = multierror.Append(errors, fmt.Errorf("job_store was specified more than once"))
		} else {
			if jobStore.Type != hclObj.ValueTypeList {
				errors = multierror.Append(errors, fmt.Errorf("job_store was specified as an invalid type - expected string, found %s", jobStore.Type))
			} else {
				for _, host := range jobStore.Elem(true) {
					hosts = append(hosts, host.Value.(string))
				}
				return hosts
			}
		}
	} else {
		errors = multierror.Append(errors, fmt.Errorf("No job_store was specified in the configuration"))
	}
	return []string{}
}
Пример #11
0
func parseJob(result *structs.Job, obj *hclobj.Object) error {
	if obj.Len() > 1 {
		return fmt.Errorf("only one 'job' block allowed")
	}

	// Get our job object
	obj = obj.Elem(true)[0]

	// Decode the full thing into a map[string]interface for ease
	var m map[string]interface{}
	if err := hcl.DecodeObject(&m, obj); err != nil {
		return err
	}
	delete(m, "constraint")
	delete(m, "meta")
	delete(m, "update")

	// Set the ID and name to the object key
	result.ID = obj.Key
	result.Name = obj.Key

	// Defaults
	result.Priority = 50
	result.Region = "global"
	result.Type = "service"

	// Decode the rest
	if err := mapstructure.WeakDecode(m, result); err != nil {
		return err
	}

	// Parse constraints
	if o := obj.Get("constraint", false); o != nil {
		if err := parseConstraints(&result.Constraints, o); err != nil {
			return err
		}
	}

	// If we have an update strategy, then parse that
	if o := obj.Get("update", false); o != nil {
		if err := parseUpdate(&result.Update, o); err != nil {
			return err
		}
	}

	// Parse out meta fields. These are in HCL as a list so we need
	// to iterate over them and merge them.
	if metaO := obj.Get("meta", false); metaO != nil {
		for _, o := range metaO.Elem(false) {
			var m map[string]interface{}
			if err := hcl.DecodeObject(&m, o); err != nil {
				return err
			}
			if err := mapstructure.WeakDecode(m, &result.Meta); err != nil {
				return err
			}
		}
	}

	// If we have tasks outside, do those
	if o := obj.Get("task", false); o != nil {
		var tasks []*structs.Task
		if err := parseTasks(&tasks, o); err != nil {
			return err
		}

		result.TaskGroups = make([]*structs.TaskGroup, len(tasks), len(tasks)*2)
		for i, t := range tasks {
			result.TaskGroups[i] = &structs.TaskGroup{
				Name:  t.Name,
				Count: 1,
				Tasks: []*structs.Task{t},
			}
		}
	}

	// Parse the task groups
	if o := obj.Get("group", false); o != nil {
		if err := parseGroups(result, o); err != nil {
			return fmt.Errorf("error parsing 'group': %s", err)
		}
	}

	return nil
}
Пример #12
0
func (d *decoder) decodeStruct(name string, o *hcl.Object, result reflect.Value) error {
	if o.Type != hcl.ValueTypeObject {
		return fmt.Errorf(
			"%s: not an object type for struct (%s)", name, o.Type)
	}

	// This slice will keep track of all the structs we'll be decoding.
	// There can be more than one struct if there are embedded structs
	// that are squashed.
	structs := make([]reflect.Value, 1, 5)
	structs[0] = result

	// Compile the list of all the fields that we're going to be decoding
	// from all the structs.
	fields := make(map[*reflect.StructField]reflect.Value)
	for len(structs) > 0 {
		structVal := structs[0]
		structs = structs[1:]

		structType := structVal.Type()
		for i := 0; i < structType.NumField(); i++ {
			fieldType := structType.Field(i)

			if fieldType.Anonymous {
				fieldKind := fieldType.Type.Kind()
				if fieldKind != reflect.Struct {
					return fmt.Errorf(
						"%s: unsupported type to struct: %s",
						fieldType.Name, fieldKind)
				}

				// We have an embedded field. We "squash" the fields down
				// if specified in the tag.
				squash := false
				tagParts := strings.Split(fieldType.Tag.Get(tagName), ",")
				for _, tag := range tagParts[1:] {
					if tag == "squash" {
						squash = true
						break
					}
				}

				if squash {
					structs = append(
						structs, result.FieldByName(fieldType.Name))
					continue
				}
			}

			// Normal struct field, store it away
			fields[&fieldType] = structVal.Field(i)
		}
	}

	usedKeys := make(map[string]struct{})
	decodedFields := make([]string, 0, len(fields))
	decodedFieldsVal := make([]reflect.Value, 0)
	unusedKeysVal := make([]reflect.Value, 0)
	for fieldType, field := range fields {
		if !field.IsValid() {
			// This should never happen
			panic("field is not valid")
		}

		// If we can't set the field, then it is unexported or something,
		// and we just continue onwards.
		if !field.CanSet() {
			continue
		}

		fieldName := fieldType.Name

		// This is whether or not we expand the object into its children
		// later.
		expand := false

		tagValue := fieldType.Tag.Get(tagName)
		tagParts := strings.SplitN(tagValue, ",", 2)
		if len(tagParts) >= 2 {
			switch tagParts[1] {
			case "expand":
				expand = true
			case "decodedFields":
				decodedFieldsVal = append(decodedFieldsVal, field)
				continue
			case "key":
				field.SetString(o.Key)
				continue
			case "unusedKeys":
				unusedKeysVal = append(unusedKeysVal, field)
				continue
			}
		}

		if tagParts[0] != "" {
			fieldName = tagParts[0]
		}

		// Find the element matching this name
		obj := o.Get(fieldName, true)
		if obj == nil {
			continue
		}

		// Track the used key
		usedKeys[fieldName] = struct{}{}

		// Create the field name and decode. We range over the elements
		// because we actually want the value.
		fieldName = fmt.Sprintf("%s.%s", name, fieldName)
		for _, obj := range obj.Elem(expand) {
			if err := d.decode(fieldName, obj, field); err != nil {
				return err
			}
		}

		decodedFields = append(decodedFields, fieldType.Name)
	}

	if len(decodedFieldsVal) > 0 {
		// Sort it so that it is deterministic
		sort.Strings(decodedFields)

		for _, v := range decodedFieldsVal {
			v.Set(reflect.ValueOf(decodedFields))
		}
	}

	// If we want to know what keys are unused, compile that
	if len(unusedKeysVal) > 0 {
		/*
			unusedKeys := make([]string, 0, int(obj.Len())-len(usedKeys))

			for _, elem := range obj.Elem {
				k := elem.Key()
				if _, ok := usedKeys[k]; !ok {
					unusedKeys = append(unusedKeys, k)
				}
			}

			if len(unusedKeys) == 0 {
				unusedKeys = nil
			}

			for _, v := range unusedKeysVal {
				v.Set(reflect.ValueOf(unusedKeys))
			}
		*/
	}

	return nil
}