瀏覽代碼

Cleaner Config interface

Andrea Barberio 7 年之前
父節點
當前提交
6c9cb6d64b
共有 3 個文件被更改,包括 75 次插入64 次删除
  1. 1 1
      cmds/coredhcp/main.go
  2. 70 59
      config/config.go
  3. 4 4
      coredhcp.go

+ 1 - 1
cmds/coredhcp/main.go

@@ -18,7 +18,7 @@ var (
 
 func main() {
 	logger := logger.GetLogger()
-	config, err := config.Parse()
+	config, err := config.Load()
 	if err != nil {
 		logger.Fatal(err)
 	}

+ 70 - 59
config/config.go

@@ -20,6 +20,11 @@ type Config struct {
 	Server4 *ServerConfig
 }
 
+// New returns a new initialized instance of a Config object
+func New() *Config {
+	return &Config{v: viper.New()}
+}
+
 // ServerConfig holds a server configuration that is specific to either the
 // DHCPv6 server or the DHCPv4 server.
 type ServerConfig struct {
@@ -27,64 +32,85 @@ type ServerConfig struct {
 	Plugins  []*PluginConfig
 }
 
-// PluginConfig holds the configuration of a single plugin
+// PluginConfig holds the configuration of a plugin
 type PluginConfig struct {
 	Name string
 	Args []string
 }
 
-// Parse returns a Config object after reading a configuration file.
-// It returns an error if the file is invalid or not found.
-func Parse() (*Config, error) {
+// Load reads a configuration file and returns a Config object, or an error if
+// any.
+func Load() (*Config, error) {
 	log.Print("Loading configuration")
-	v := viper.New()
-	v.SetConfigType("yml")
-	v.SetConfigName("config")
-	v.AddConfigPath(".")
-	v.AddConfigPath("$HOME/.coredhcp/")
-	v.AddConfigPath("/etc/coredhcp/")
-	if err := v.ReadInConfig(); err != nil {
+	c := New()
+	c.v.SetConfigType("yml")
+	c.v.SetConfigName("config")
+	c.v.AddConfigPath(".")
+	c.v.AddConfigPath("$HOME/.coredhcp/")
+	c.v.AddConfigPath("/etc/coredhcp/")
+	if err := c.v.ReadInConfig(); err != nil {
 		return nil, err
 	}
-	v6, err := parseV6Config(v)
-	if err != nil {
+	if err := c.parseV6Config(); err != nil {
 		return nil, err
 	}
-	v4, err := parseV4Config(v)
-	if err != nil {
+	if err := c.parseV4Config(); err != nil {
 		return nil, err
 	}
-	if v6 == nil && v4 == nil {
+	if c.Server6 == nil && c.Server4 == nil {
 		return nil, ConfigErrorFromString("need at least one valid config for DHCPv6 or DHCPv4")
 	}
-	return &Config{
-		v:       v,
-		Server6: v6,
-		Server4: v4,
-	}, nil
+	return c, nil
+}
+
+func parsePlugins(pluginList []interface{}) ([]*PluginConfig, error) {
+	plugins := make([]*PluginConfig, 0)
+	for idx, val := range pluginList {
+		conf := cast.ToStringMap(val)
+		if conf == nil {
+			return nil, ConfigErrorFromString("dhcpv6: plugin #%d is not a string map", idx)
+		}
+		// make sure that only one item is specified, since it's a
+		// map name -> args
+		if len(conf) != 1 {
+			return nil, ConfigErrorFromString("dhcpv6: exactly one plugin per item can be specified")
+		}
+		var (
+			name string
+			args []string
+		)
+		// only one item, as enforced above, so read just that
+		for k, v := range conf {
+			name = k
+			args = strings.Fields(cast.ToString(v))
+			break
+		}
+		plugins = append(plugins, &PluginConfig{Name: name, Args: args})
+	}
+	return plugins, nil
 }
 
-func parseV6Config(v *viper.Viper) (*ServerConfig, error) {
-	if exists := v.Get("server6"); exists == nil {
+func (c *Config) parseV6Config() error {
+	if exists := c.v.Get("server6"); exists == nil {
 		// it is valid to have no DHCPv6 configuration defined, so no
 		// server and no error are returned
-		return nil, nil
+		return nil
 	}
-	addr := v.GetString("server6.listen")
+	addr := c.v.GetString("server6.listen")
 	if addr == "" {
-		return nil, ConfigErrorFromString("dhcpv6: missing `server6.listen` directive")
+		return ConfigErrorFromString("dhcpv6: missing `server6.listen` directive")
 	}
 	ipStr, portStr, err := net.SplitHostPort(addr)
 	if err != nil {
-		return nil, ConfigErrorFromString("dhcpv6: %v", err)
+		return ConfigErrorFromString("dhcpv6: %v", err)
 	}
 	ip := net.ParseIP(ipStr)
 	if ip.To4() != nil {
-		return nil, ConfigErrorFromString("dhcpv6: missing or invalid `listen` address")
+		return ConfigErrorFromString("dhcpv6: missing or invalid `listen` address")
 	}
 	port, err := strconv.Atoi(portStr)
 	if err != nil {
-		return nil, ConfigErrorFromString("dhcpv6: invalid `listen` port")
+		return ConfigErrorFromString("dhcpv6: invalid `listen` port")
 	}
 	listener := net.UDPAddr{
 		IP:   ip,
@@ -95,40 +121,25 @@ func parseV6Config(v *viper.Viper) (*ServerConfig, error) {
 		Plugins:  nil,
 	}
 	// load plugins
-	pluginList := cast.ToSlice(v.Get("server6.plugins"))
+	pluginList := cast.ToSlice(c.v.Get("server6.plugins"))
 	if pluginList == nil {
-		return nil, ConfigErrorFromString("dhcpv6: invalid plugins section, not a list")
+		return ConfigErrorFromString("dhcpv6: invalid plugins section, not a list")
 	}
-	for idx, v := range pluginList {
-		conf := cast.ToStringMap(v)
-		if conf == nil {
-			return nil, ConfigErrorFromString("dhcpv6: plugin #%d is not a string map", idx)
-		}
-		// make sure that only one item is specified, since it's a
-		// map name -> args
-		if len(conf) != 1 {
-			return nil, ConfigErrorFromString("dhcpv6: exactly one plugin per item can be specified")
-		}
-		var (
-			name string
-			args []string
-		)
-		// only one item, as enforced above, so read just that
-		for k, v := range conf {
-			name = k
-			args = strings.Fields(cast.ToString(v))
-			break
-		}
-		log.Printf("Found plugin: `%s` with %d args, `%v`", name, len(args), args)
-		sc.Plugins = append(sc.Plugins, &PluginConfig{Name: name, Args: args})
-
+	plugins, err := parsePlugins(pluginList)
+	if err != nil {
+		return err
+	}
+	for _, p := range plugins {
+		log.Printf("DHCPv6: found plugin `%s` with %d args: %v", p.Name, len(p.Args), p.Args)
 	}
-	return &sc, nil
+	sc.Plugins = plugins
+	c.Server6 = &sc
+	return nil
 }
 
-func parseV4Config(v *viper.Viper) (*ServerConfig, error) {
-	if exists := v.Get("server4"); exists != nil {
-		return nil, errors.New("DHCPv4 config parser not implemented yet")
+func (c *Config) parseV4Config() error {
+	if exists := c.v.Get("server4"); exists != nil {
+		return errors.New("DHCPv4 config parser not implemented yet")
 	}
-	return nil, nil
+	return nil
 }

+ 4 - 4
coredhcp.go

@@ -25,10 +25,10 @@ type Server struct {
 	errors    chan error
 }
 
-// LoadPlugins reads a Viper configuration and loads the plugins
-// as specified in the `plugins` section, in order. For a plugin to
-// be available, it must have been previously registered with
-// plugins.RegisterPlugin. This is normally done at plugin import.
+// LoadPlugins reads a Config object and loads the plugins as specified in the
+// `plugins` section, in order. For a plugin to be available, it must have been
+// previously registered with plugins.RegisterPlugin. This is normally done at
+// plugin import time.
 func (s *Server) LoadPlugins(conf *config.Config) ([]*plugins.Plugin, error) {
 	log.Print("Loading plugins...")
 	loadedPlugins := make([]*plugins.Plugin, 0)