Beispiel #1
0
func InitConfig(c interface{}, initFuncs ...InitFunc) (err error) {
	cval := reflect.ValueOf(c)
	for cval.Kind() == reflect.Ptr {
		cval = cval.Elem()
	}
	cf := cval.FieldByName("Config").Interface().(Config)

	if cf.Initialized {
		err = fmt.Errorf("Config %v is already Initialized.", cf)
		return
	}

	names, types, tags := StructFields(c)
	namesSet := set.NewStringSet()
	assertions := make(map[string]map[string][]Assertion)
	for _, key := range names {
		if !namesSet.HasMember(key) {
			namesSet.Add(key)
			assertions[key] = make(map[string][]Assertion)
		} else {
			err = fmt.Errorf("Coniguration keys must be unique - got '%s' a second time.", key)
			fmt.Println(err)
			return
		}
	}

	// init sets
	for key, type_ := range types {
		switch type_ {
		case "*set.StringSet":
			cval.FieldByName(key).Set(reflect.ValueOf(set.NewStringSet()))
		case "*set.IntSet":
			cval.FieldByName(key).Set(reflect.ValueOf(set.NewIntSet()))
		case "*set.Int64Set":
			cval.FieldByName(key).Set(reflect.ValueOf(set.NewInt64Set()))
		}
	}

	initC := Config{
		MainConfig:   cval,
		ConfigValues: make(map[string]interface{}),
		Initialized:  false,
		ConfigKeys:   namesSet,
		KeyAliases:   set.NewStringSet(),
		AliasKeyMap:  make(map[string]string),
		ConfigTypes:  types,
		ConfigTags:   tags,
		Assertions:   assertions,
		LogSet:       cf.LogSet,
	}

	initC.initFuncs = append(
		[]InitFunc{
			InitFunc{
				F:           initC.setDefaults,
				ExitOnError: true,
			},
			InitFunc{
				F:           initC.readFromEnv,
				ExitOnError: true,
			},
		},
		append(
			initFuncs,
			InitFunc{
				F:           initC.Validate,
				ExitOnError: true,
			},
		)...,
	)

	// get aliases
	err = initC.extractAliases()
	if err == nil {
		// set Assertions
		err = initC.extractAssertions()
		if err == nil {
			log.Println("initC.extractAssertions() OK")
		} else {
			return
		}
	} else {
		return
	}

	// init functions might reference a global config - we now need to operate
	// on the actualy object..
	cval.FieldByName("Config").Set(reflect.ValueOf(initC))
	cfg := cval.FieldByName("Config").Interface().(Config)
	// run all init functions
	err = cfg.ReInit()
	if err == nil {
		log.Println("initC.ReInit() OK")
		cval.FieldByName("Initialized").SetBool(true)
	}

	return
}
Beispiel #2
0
func TestDefaultValues(t *testing.T) {
	cfg := struct {
		Config

		BoolSetting   bool    `default:"true"`
		StringSetting string  `default:"foo"`
		IntSetting    int     `default:"23"`
		FloatSetting  float64 `default:"1.681"`

		SingleValueConfig struct {
			StringSetting string  `default:"bar"`
			IntSetting    int     `default:"42"`
			FloatSetting  float64 `default:"23.12"`
		}

		SliceConfig struct {
			StringSliceSetting []string  `default:"foo,bar"`
			IntSliceSetting    []int     `default:"23,42"`
			FloatSliceSetting  []float64 `default:"1.394,1.112"`
		}

		NestedValueConfig struct {
			StringSetting          string `default:"NestedOuterFoo"`
			InnerNestedValueConfig struct {
				StringSetting string `default:"NestedInnerFoo"`
			}
		}

		StringSet *set.StringSet
		IntSet    *set.IntSet
	}{}

	initFunc := InitFunc{
		F: func() (err error) {
			cfg.StringSet = set.NewStringSet([]string{"foo", "bar"}...)
			cfg.IntSet = set.NewIntSet([]int{1, 2}...)
			return
		},
		ExitOnError: false,
	}

	err := InitConfig(&cfg, initFunc)
	cv.Convey(`Initializing the config should pass.`, t, func() {
		cv.So(err, cv.ShouldBeNil)

		cv.So(cfg.BoolSetting, cv.ShouldBeTrue)
		cv.So(cfg.StringSetting, cv.ShouldEqual, "foo")
		cv.So(cfg.IntSetting, cv.ShouldEqual, 23)
		cv.So(cfg.FloatSetting, cv.ShouldEqual, 1.681)

		cv.So(cfg.SingleValueConfig.StringSetting, cv.ShouldEqual, "bar")
		cv.So(cfg.SingleValueConfig.IntSetting, cv.ShouldEqual, 42)
		cv.So(cfg.SingleValueConfig.FloatSetting, cv.ShouldEqual, 23.12)

		cv.So(cfg.SliceConfig.StringSliceSetting, cv.ShouldContain, "foo")
		cv.So(cfg.SliceConfig.StringSliceSetting, cv.ShouldContain, "bar")
		cv.So(cfg.SliceConfig.IntSliceSetting, cv.ShouldContain, 23)
		cv.So(cfg.SliceConfig.IntSliceSetting, cv.ShouldContain, 42)
		cv.So(cfg.SliceConfig.FloatSliceSetting, cv.ShouldContain, 1.394)
		cv.So(cfg.SliceConfig.FloatSliceSetting, cv.ShouldContain, 1.112)

		cv.So(cfg.NestedValueConfig.StringSetting, cv.ShouldEqual, "NestedOuterFoo")
		cv.So(cfg.NestedValueConfig.InnerNestedValueConfig.StringSetting, cv.ShouldEqual, "NestedInnerFoo")

		cv.So(cfg.StringSet.HasMembers("foo", "bar"), cv.ShouldBeTrue)
		cv.So(cfg.IntSet.HasMembers(1, 2), cv.ShouldBeTrue)
	})

}
Beispiel #3
0
func (c *Config) setValue(key string, value interface{}) (err error) {
	var field reflect.Value
	// fmt.Println("%", key, value)
	field, err = c.FieldForKey(key)
	if err != nil {
		return
	}

	ifaces, ok := value.([]interface{})
	if ok {
		fmt.Println("[]interface{}...")
		var val interface{}
		for _, iface := range ifaces {
			// fmt.Println("> got", reflect.TypeOf(iface))
			switch c.ConfigTypes[key] {
			case "bool":
				val = iface.(bool)
			case "[]bool":
				if reflect.TypeOf(val) == nil {
					val = []bool{}
				}
				val = append(val.([]bool), iface.(bool))
			case "string":
				val = iface.(string)
			case "[]string":
				if reflect.TypeOf(val) == nil {
					val = []string{}
				}
				val = reflect.Append(
					reflect.ValueOf(val),
					reflect.ValueOf(iface),
				).Interface()

			case "int":
				val = iface.(int)
			case "[]int":
				if reflect.TypeOf(val) == nil {
					val = []int{}
				}
				val = append(val.([]int), iface.(int))
			case "float64":
				val = iface.(float64)
			case "[]float64":
				if reflect.TypeOf(val) == nil {
					val = []float64{}
				}
				val = append(val.([]float64), iface.(float64))
			default:
				err = fmt.Errorf("Cannot set config from %v", value)
				fmt.Println("nope", err)
				return
			}

			err = c.setValue(key, val)
			if err != nil {
				break
			}
		}
		return
	}

	// fmt.Printf("set %s to a %v with value %v\n", key, c.ConfigTypes[key], value)
	// fmt.Println("-- Got", reflect.TypeOf(value))

	var is interface{}
	switch c.ConfigTypes[key] {
	case "bool":
		var v bool
		v, ok := value.(bool)
		if !ok {
			v, err = boolFromInterface(value)
			if err != nil {
				return
			}
		}
		field.SetBool(v)
	case "string":
		var v string
		v, ok := value.(string)
		if !ok {
			vs, ok := value.([]string)
			if ok {
				v = vs[0]
			}
		}
		field.SetString(v)
	case "int":
		var v int64
		v, ok := value.(int64)
		if !ok {
			v, err = intFromInterface(value)
			if err != nil {
				return
			}
		}
		field.SetInt(v)
	case "float64":
		var v float64
		v, ok := value.(float64)
		if !ok {
			v, err = floatFromInterface(value)
			if err != nil {
				return
			}
		}
		field.SetFloat(v)
	case "[]string", "*set.StringSet":
		// log.Println("[]string", "*set.StringSet")
		var v []string
		v, ok := value.([]string)
		if !ok {
			var type_ string
			is, err = sliceFromStrings(value, type_)
			if err != nil {
				return
			}
			v = is.([]string)
		}
		if c.ConfigTypes[key] == "*set.StringSet" {
			field.Set(reflect.ValueOf(set.NewStringSet(v...)))
		} else {
			field.Set(reflect.ValueOf(v))
		}

	case "[]int", "*set.IntSet":
		var v []int
		v, ok := value.([]int)
		if !ok {
			var type_ int
			is, err = sliceFromStrings(value, type_)
			if err != nil {
				return
			}
			v = is.([]int)
		}

		if c.ConfigTypes[key] == "*set.IntSet" {
			field.Set(reflect.ValueOf(set.NewIntSet(v...)))
		} else {
			field.Set(reflect.ValueOf(v))
		}
	case "[]float64":
		var v []float64
		v, ok := value.([]float64)
		if !ok {
			var type_ float64
			is, err = sliceFromStrings(value, type_)
			if err != nil {
				return
			}
			v = is.([]float64)
		}
		field.Set(reflect.ValueOf(v))
	case "interface{}":
		err = fmt.Errorf("Set interface{} - not implemented")

	case "[]interface{}":
		err = fmt.Errorf("Set []interface{} - not implemented")
	default:
		err = fmt.Errorf("Cannot deal with %v.", c.ConfigTypes[key])
	}

	if c.LogSet && err == nil {
		fld, _ := c.FieldForKey(key)
		log.Printf("Set %s to %v.\n", key, fld.Interface())
	}

	return
}