From eb89ea7b213e26524c1fe884c4313d5a8c5f5316 Mon Sep 17 00:00:00 2001 From: Yue Ko Date: Thu, 12 Jan 2017 03:38:53 +0000 Subject: [PATCH] Use config file in addition to command line args Allow specification of -conf-file command line argument to specify a configuration file that set same set of parameters as command line args. If the same paremeter is set in both places, the command line value takes precedence. --- README.md | 39 ++++++++++- config.example | 21 ++++++ config.go | 174 ++++++++++++++++++++++++++++++++-------------- create_ea_defs.go | 9 ++- ipam-driver.go | 9 ++- 5 files changed, 194 insertions(+), 58 deletions(-) create mode 100644 config.example diff --git a/README.md b/README.md index 76637f7..00afbaf 100644 --- a/README.md +++ b/README.md @@ -40,8 +40,10 @@ ipam-driver accepts a number of arguments which can be listed by specifying -h: ``` ubuntu$ ./ipam-driver --help Usage of ./ipam-driver: + -conf-file + File path of configuration file (see below) -driver-name string - Name of Infoblox IPAM driver (default "mddi") + Name of Infoblox IPAM driver (default "infoblox") -global-network-container string Subnets will be allocated from this container when --subnet is not specified during network creation (default "172.18.0.0/16") -global-prefix-length uint @@ -68,6 +70,10 @@ Usage of ./ipam-driver: Infoblox WAPI Username -wapi-version string Infoblox WAPI Version. (default "2.0") + -http-request_timeout + Infoblox WAPI request timeout in seconds. (default 60) + -http-pool-connections + Infoblox WAPI request connection pool size. (default 10) ``` For example, @@ -75,8 +81,39 @@ For example, ``` ./ipam-driver --grid-host=192.168.124.200 --wapi-username=cloudadmin --wapi-password=cloudadmin --local-view=local_view --local-network-container="192.168.0.0/20,192.169.0.0/22" --local-prefix-length=25 --global-view=global_view --global-network-container="172.18.0.0/16" --global-prefix-length=24 ``` + The command need to be executed with root permission. +If the ```conf-file``` option is specified in the command line argument, it specifies a configuration +file that accept the same set of parameters (except ```conf_file```) in the following format: + +``` +[plugin_config] +driver_name="infoblox" +plugin_dir="/run/docker/plugins" + +[grid_config] +grid_host="192.168.124.200" +wapi_port="443" +wapi_username="admin" +wapi_password="infoblox" +wapi_version="2.0" +ssl_verify="false" +http_request_timeout=60 +http_pool_connections=10 + +[ipam_config] +global_view="default" +global_container="172.18.0.0/16" +global_prefix=16 +local_view="default" +local_container="192.168.0.0/16" +local_prefix=24 +``` + +If the same parameter is specified in both the configuration file and command line argument, the +value specified in the command line argument takes precedence. + By default, ipam-driver uses Docker API Version 1.22 to access Docker Remote API. The default can be overridden using the DOCKER_API_VERSION environment variable prior to running the driver. For example, diff --git a/config.example b/config.example new file mode 100644 index 0000000..f3cf669 --- /dev/null +++ b/config.example @@ -0,0 +1,21 @@ +[plugin_config] +driver_name="infoblox" +plugin_dir="/run/docker/plugins" + +[grid_config] +grid_host="192.168.124.200" +wapi_port="443" +wapi_username="admin" +wapi_password="infoblox" +wapi_version="2.0" +ssl_verify="false" +http_request_timeout=60 +http_pool_connections=10 + +[ipam_config] +global_view="default" +global_container="172.18.0.0/16" +global_prefix=16 +local_view="default" +local_container="192.168.0.0/16" +local_prefix=24 diff --git a/config.go b/config.go index 16ae362..1982ebe 100644 --- a/config.go +++ b/config.go @@ -2,62 +2,134 @@ package main import ( "flag" + "github.com/BurntSushi/toml" + "os" ) -const ( - HTTP_REQUEST_TIMEOUT = 60 - HTTP_POOL_CONNECTIONS = 10 -) +type PluginConfig struct { + PluginDir string `toml:"plugin_dir"` + DriverName string `toml:"driver_name"` +} type GridConfig struct { - GridHost string - WapiVer string - WapiPort string - WapiUsername string - WapiPassword string - SslVerify string - HttpRequestTimeout int - HttpPoolConnections int -} - -type DriverConfig struct { - PluginDir string - DriverName string - GlobalNetview string - GlobalNetworkContainer string - GlobalPrefixLength uint - LocalNetview string - LocalNetworkContainer string - LocalPrefixLength uint + GridHost string `toml:"grid_host"` + WapiVer string `toml:"wapi_version"` + WapiPort string `toml:"wapi_port"` + WapiUsername string `toml:"wapi_username"` + WapiPassword string `toml:"wapi_password"` + SslVerify string `toml:"ssl_verify"` + HttpRequestTimeout uint `toml:"http_request_timeout"` + HttpPoolConnections uint `toml:"http_pool_connections"` +} + +type IpamConfig struct { + GlobalNetview string `toml:"global_view"` + GlobalNetworkContainer string `toml:"global_container"` + GlobalPrefixLength uint `toml:"global_prefix"` + LocalNetview string `toml:"local_view"` + LocalNetworkContainer string `toml:"local_container"` + LocalPrefixLength uint `toml:"local_prefix"` } type Config struct { - GridConfig - DriverConfig -} - -func LoadConfig() (config *Config) { - config = new(Config) - - flag.StringVar(&config.GridHost, "grid-host", "192.168.124.200", "IP of Infoblox Grid Host") - flag.StringVar(&config.WapiVer, "wapi-version", "2.0", "Infoblox WAPI Version.") - flag.StringVar(&config.WapiPort, "wapi-port", "443", "Infoblox WAPI Port.") - flag.StringVar(&config.WapiUsername, "wapi-username", "", "Infoblox WAPI Username") - flag.StringVar(&config.WapiPassword, "wapi-password", "", "Infoblox WAPI Password") - flag.StringVar(&config.SslVerify, "ssl-verify", "false", "Specifies whether (true/false) to verify server certificate. If a file path is specified, it is assumed to be a certificate file and will be used to verify server certificate.") - config.HttpRequestTimeout = HTTP_REQUEST_TIMEOUT - config.HttpPoolConnections = HTTP_POOL_CONNECTIONS - - flag.StringVar(&config.PluginDir, "plugin-dir", "/run/docker/plugins", "Docker plugin directory where driver socket is created") - flag.StringVar(&config.DriverName, "driver-name", "infoblox", "Name of Infoblox IPAM driver") - flag.StringVar(&config.GlobalNetview, "global-view", "default", "Infoblox Network View for Global Address Space") - flag.StringVar(&config.GlobalNetworkContainer, "global-network-container", "172.18.0.0/16", "Subnets will be allocated from this container when --subnet is not specified during network creation") - flag.UintVar(&config.GlobalPrefixLength, "global-prefix-length", 24, "The default CIDR prefix length when allocating a global subnet.") - flag.StringVar(&config.LocalNetview, "local-view", "default", "Infoblox Network View for Local Address Space") - flag.StringVar(&config.LocalNetworkContainer, "local-network-container", "192.168.0.0/16", "Subnets will be allocated from this container when --subnet is not specified during network creation") - flag.UintVar(&config.LocalPrefixLength, "local-prefix-length", 24, "The default CIDR prefix length when allocating a local subnet.") - - flag.Parse() - - return config + ConfigFile string `toml:` + PluginConfig `toml:"plugin_config"` + GridConfig `toml:"grid_config"` + IpamConfig `toml:"ipam_config"` +} + +func NewConfig() *Config { + return &Config{ + ConfigFile: "", + + PluginConfig: PluginConfig{ + PluginDir: "/run/docker/plugins", + DriverName: "infoblox", + }, + + GridConfig: GridConfig{ + GridHost: "192.168.124.200", + WapiVer: "2.0", + WapiPort: "443", + WapiUsername: "", + WapiPassword: "", + SslVerify: "false", + HttpRequestTimeout: 60, + HttpPoolConnections: 10, + }, + + IpamConfig: IpamConfig{ + GlobalNetview: "default", + GlobalNetworkContainer: "global-network-container", + GlobalPrefixLength: 24, + LocalNetview: "default", + LocalNetworkContainer: "192.168.0.0/16", + LocalPrefixLength: 24, + }, + } +} + +func LoadFromCommandLine(config *Config) (*Config, error) { + if config == nil { + config = NewConfig() + } + + flagSet := flag.NewFlagSet(os.Args[0], flag.ExitOnError) + + flagSet.StringVar(&config.ConfigFile, "conf-file", "", "File path of configuration file") + + flagSet.StringVar(&config.PluginDir, "plugin-dir", config.PluginDir, "Docker plugin directory where driver socket is created") + flagSet.StringVar(&config.DriverName, "driver-name", config.DriverName, "Name of Infoblox IPAM driver") + + flagSet.StringVar(&config.GridHost, "grid-host", config.GridHost, "IP of Infoblox Grid Host") + flagSet.StringVar(&config.WapiVer, "wapi-version", config.WapiVer, "Infoblox WAPI Version.") + flagSet.StringVar(&config.WapiPort, "wapi-port", config.WapiPort, "Infoblox WAPI Port.") + flagSet.StringVar(&config.WapiUsername, "wapi-username", config.WapiUsername, "Infoblox WAPI Username") + flagSet.StringVar(&config.WapiPassword, "wapi-password", config.WapiPassword, "Infoblox WAPI Password") + flagSet.StringVar(&config.SslVerify, "ssl-verify", config.SslVerify, "Specifies whether (true/false) to verify server certificate. If a file path is specified, it is assumed to be a certificate file and will be used to verify server certificate.") + flagSet.UintVar(&config.HttpRequestTimeout, "http-request-timeout", config.HttpRequestTimeout, "Infoblox WAPI request timeout in seconds.") + flagSet.UintVar(&config.HttpPoolConnections, "http-pool-connections", config.HttpPoolConnections, "Infoblox WAPI connection pool size.") + + flagSet.StringVar(&config.GlobalNetview, "global-view", config.GlobalNetview, "Infoblox Network View for Global Address Space") + flagSet.StringVar(&config.GlobalNetworkContainer, "global-network-container", config.GlobalNetworkContainer, "Subnets will be allocated from this container when --subnet is not specified during network creation") + flagSet.UintVar(&config.GlobalPrefixLength, "global-prefix-length", config.GlobalPrefixLength, "The default CIDR prefix length when allocating a global subnet.") + flagSet.StringVar(&config.LocalNetview, "local-view", config.LocalNetview, "Infoblox Network View for Local Address Space") + flagSet.StringVar(&config.LocalNetworkContainer, "local-network-container", config.LocalNetworkContainer, "Subnets will be allocated from this container when --subnet is not specified during network creation") + flagSet.UintVar(&config.LocalPrefixLength, "local-prefix-length", config.LocalPrefixLength, "The default CIDR prefix length when allocating a local subnet.") + + flagSet.Parse(os.Args[1:]) + + return config, nil +} + +func LoadFromConfFile(config *Config) (*Config, error) { + // Just look for --conf-file flag + tmpConfig, err := LoadFromCommandLine(NewConfig()) + if tmpConfig == nil || err != nil { + return tmpConfig, err + } + + // Now load config file + if tmpConfig.ConfigFile != "" { + if _, err = toml.DecodeFile(tmpConfig.ConfigFile, config); err != nil { + return nil, err + } + } + + return config, err + +} + +func LoadConfig() (config *Config, err error) { + config = NewConfig() + + if config, err = LoadFromConfFile(config); config == nil || err != nil { + return + } + + if config, err = LoadFromCommandLine(config); config == nil || err != nil { + return + } + + return } diff --git a/create_ea_defs.go b/create_ea_defs.go index dc198dc..1b902a2 100644 --- a/create_ea_defs.go +++ b/create_ea_defs.go @@ -6,7 +6,10 @@ import ( ) func main() { - config := LoadConfig() + config, err := LoadConfig() + if config == nil || err != nil { + log.Fatal(err) + } hostConfig := ibclient.HostConfig{ Host: config.GridHost, @@ -18,8 +21,8 @@ func main() { transportConfig := ibclient.NewTransportConfig( config.SslVerify, - config.HttpRequestTimeout, - config.HttpPoolConnections, + int(config.HttpRequestTimeout), + int(config.HttpPoolConnections), ) requestBuilder := &ibclient.WapiRequestBuilder{} diff --git a/ipam-driver.go b/ipam-driver.go index 837d9fc..24d9695 100644 --- a/ipam-driver.go +++ b/ipam-driver.go @@ -114,7 +114,10 @@ type ipamCall struct { } func main() { - config := LoadConfig() + config, err := LoadConfig() + if config == nil || err != nil { + log.Fatal(err) + } socketFile := setupSocket(config.PluginDir, config.DriverName) log.Printf("Driver Name: '%s'", config.DriverName) @@ -130,8 +133,8 @@ func main() { transportConfig := ibclient.NewTransportConfig( config.SslVerify, - config.HttpRequestTimeout, - config.HttpPoolConnections, + int(config.HttpRequestTimeout), + int(config.HttpPoolConnections), ) requestBuilder := &ibclient.WapiRequestBuilder{}