From 9f3d1ce3ffa88fcb6f2b10cfac673a2a0cda7a4d Mon Sep 17 00:00:00 2001 From: Madhu Venugopal Date: Thu, 11 Jun 2015 06:52:46 -0700 Subject: [PATCH] Moved the TOML based Configuration to dnet The configuration format for docker runtime is based on daemon flags and hence adjusting the libnetwork configuration to accomodate it by moving the TOML based configuration to the dnet tool. Also changed the controller configuration via options Signed-off-by: Madhu Venugopal --- libnetwork/README.md | 2 +- libnetwork/api/api_test.go | 20 +++++----- libnetwork/client/service.go | 8 ++-- libnetwork/cmd/dnet/dnet.go | 42 +++++++++++++++++++- libnetwork/cmd/dnet/flags.go | 1 + libnetwork/cmd/readme_test/readme.go | 2 +- libnetwork/cmd/test/main.go | 4 +- libnetwork/config/config.go | 51 +++++++++++++++++++++++- libnetwork/controller.go | 55 +++++++++++--------------- libnetwork/libnetwork_internal_test.go | 2 +- libnetwork/libnetwork_test.go | 4 +- libnetwork/store.go | 9 ++++- 12 files changed, 142 insertions(+), 58 deletions(-) diff --git a/libnetwork/README.md b/libnetwork/README.md index 702bd8a926..3e6a11bb76 100644 --- a/libnetwork/README.md +++ b/libnetwork/README.md @@ -18,7 +18,7 @@ There are many networking solutions available to suit a broad range of use-cases ```go // Create a new controller instance - controller := libnetwork.New("/etc/default/libnetwork.toml") + controller := libnetwork.New() // Select and configure the network driver networkType := "bridge" diff --git a/libnetwork/api/api_test.go b/libnetwork/api/api_test.go index 8cbb9d8aa6..69b93cb639 100644 --- a/libnetwork/api/api_test.go +++ b/libnetwork/api/api_test.go @@ -79,7 +79,7 @@ func i2cL(i interface{}) []*containerResource { } func createTestNetwork(t *testing.T, network string) (libnetwork.NetworkController, libnetwork.Network) { - c, err := libnetwork.New("") + c, err := libnetwork.New() if err != nil { t.Fatal(err) } @@ -174,7 +174,7 @@ func TestJson(t *testing.T) { func TestCreateDeleteNetwork(t *testing.T) { defer netutils.SetupTestNetNS(t)() - c, err := libnetwork.New("") + c, err := libnetwork.New() if err != nil { t.Fatal(err) } @@ -252,7 +252,7 @@ func TestCreateDeleteNetwork(t *testing.T) { func TestGetNetworksAndEndpoints(t *testing.T) { defer netutils.SetupTestNetNS(t)() - c, err := libnetwork.New("") + c, err := libnetwork.New() if err != nil { t.Fatal(err) } @@ -525,7 +525,7 @@ func TestGetNetworksAndEndpoints(t *testing.T) { func TestProcGetServices(t *testing.T) { defer netutils.SetupTestNetNS(t)() - c, err := libnetwork.New("") + c, err := libnetwork.New() if err != nil { t.Fatal(err) } @@ -1001,7 +1001,7 @@ func TestAttachDetachBackend(t *testing.T) { } func TestDetectGetNetworksInvalidQueryComposition(t *testing.T) { - c, err := libnetwork.New("") + c, err := libnetwork.New() if err != nil { t.Fatal(err) } @@ -1108,7 +1108,7 @@ func TestFindNetworkUtil(t *testing.T) { func TestCreateDeleteEndpoints(t *testing.T) { defer netutils.SetupTestNetNS(t)() - c, err := libnetwork.New("") + c, err := libnetwork.New() if err != nil { t.Fatal(err) } @@ -1234,7 +1234,7 @@ func TestCreateDeleteEndpoints(t *testing.T) { func TestJoinLeave(t *testing.T) { defer netutils.SetupTestNetNS(t)() - c, err := libnetwork.New("") + c, err := libnetwork.New() if err != nil { t.Fatal(err) } @@ -1674,7 +1674,7 @@ func TestwriteJSON(t *testing.T) { func TestHttpHandlerUninit(t *testing.T) { defer netutils.SetupTestNetNS(t)() - c, err := libnetwork.New("") + c, err := libnetwork.New() if err != nil { t.Fatal(err) } @@ -1740,7 +1740,7 @@ func TestHttpHandlerBadBody(t *testing.T) { rsp := newWriter() - c, err := libnetwork.New("") + c, err := libnetwork.New() if err != nil { t.Fatal(err) } @@ -1772,7 +1772,7 @@ func TestEndToEnd(t *testing.T) { rsp := newWriter() - c, err := libnetwork.New("") + c, err := libnetwork.New() if err != nil { t.Fatal(err) } diff --git a/libnetwork/client/service.go b/libnetwork/client/service.go index 1e6eee18d9..3822874106 100644 --- a/libnetwork/client/service.go +++ b/libnetwork/client/service.go @@ -15,8 +15,8 @@ var ( serviceCommands = []command{ {"publish", "Publish a service"}, {"unpublish", "Remove a service"}, - {"attach", "Attach a provider (container) to the service"}, - {"detach", "Detach the provider from the service"}, + {"attach", "Attach a backend (container) to the service"}, + {"detach", "Detach the backend from the service"}, {"ls", "Lists all services"}, {"info", "Display information about a service"}, } @@ -189,7 +189,7 @@ func (cli *NetworkCli) CmdServiceLs(chain string, args ...string) error { wr := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) // unless quiet (-q) is specified, print field titles if !*quiet { - fmt.Fprintln(wr, "SERVICE ID\tNAME\tNETWORK\tPROVIDER") + fmt.Fprintln(wr, "SERVICE ID\tNAME\tNETWORK\tCONTAINER") } for _, sr := range serviceResources { @@ -228,7 +228,7 @@ func getBackendID(cli *NetworkCli, servID string) (string, error) { } } else { // Only print a message, don't make the caller cli fail for this - fmt.Fprintf(cli.out, "Failed to retrieve provider list for service %s (%v)", servID, err) + fmt.Fprintf(cli.out, "Failed to retrieve backend list for service %s (%v)", servID, err) } } diff --git a/libnetwork/cmd/dnet/dnet.go b/libnetwork/cmd/dnet/dnet.go index c798d065b1..32920c8b85 100644 --- a/libnetwork/cmd/dnet/dnet.go +++ b/libnetwork/cmd/dnet/dnet.go @@ -19,16 +19,19 @@ import ( "github.com/docker/libnetwork" "github.com/docker/libnetwork/api" "github.com/docker/libnetwork/client" + "github.com/docker/libnetwork/config" "github.com/gorilla/mux" ) -var ( +const ( // DefaultHTTPHost is used if only port is provided to -H flag e.g. docker -d -H tcp://:8080 DefaultHTTPHost = "127.0.0.1" // DefaultHTTPPort is the default http port used by dnet DefaultHTTPPort = 2385 // DefaultUnixSocket exported DefaultUnixSocket = "/var/run/dnet.sock" + cfgFileEnv = "LIBNETWORK_CFG" + defaultCfgFile = "/etc/default/libnetwork.toml" ) func main() { @@ -45,6 +48,36 @@ func main() { } } +func parseConfig(cfgFile string) (*config.Config, error) { + if strings.Trim(cfgFile, " ") == "" { + cfgFile = os.Getenv(cfgFileEnv) + if strings.Trim(cfgFile, " ") == "" { + cfgFile = defaultCfgFile + } + } + return config.ParseConfig(cfgFile) +} + +func processConfig(cfg *config.Config) []config.Option { + options := []config.Option{} + if cfg == nil { + return options + } + if strings.TrimSpace(cfg.Daemon.DefaultNetwork) != "" { + options = append(options, config.OptionDefaultNetwork(cfg.Daemon.DefaultNetwork)) + } + if strings.TrimSpace(cfg.Daemon.DefaultDriver) != "" { + options = append(options, config.OptionDefaultDriver(cfg.Daemon.DefaultDriver)) + } + if strings.TrimSpace(cfg.Datastore.Client.Provider) != "" { + options = append(options, config.OptionKVProvider(cfg.Datastore.Client.Provider)) + } + if strings.TrimSpace(cfg.Datastore.Client.Address) != "" { + options = append(options, config.OptionKVProviderURL(cfg.Datastore.Client.Address)) + } + return options +} + func dnetCommand(stdout, stderr io.Writer) error { flag.Parse() @@ -111,7 +144,12 @@ type dnetConnection struct { } func (d *dnetConnection) dnetDaemon() error { - controller, err := libnetwork.New("") + cfg, err := parseConfig(*flCfgFile) + var cOptions []config.Option + if err == nil { + cOptions = processConfig(cfg) + } + controller, err := libnetwork.New(cOptions...) if err != nil { fmt.Println("Error starting dnetDaemon :", err) return err diff --git a/libnetwork/cmd/dnet/flags.go b/libnetwork/cmd/dnet/flags.go index 595971bbfe..27dfbd19ed 100644 --- a/libnetwork/cmd/dnet/flags.go +++ b/libnetwork/cmd/dnet/flags.go @@ -19,6 +19,7 @@ var ( flHost = flag.String([]string{"H", "-host"}, "", "Daemon socket to connect to") flLogLevel = flag.String([]string{"l", "-log-level"}, "info", "Set the logging level") flDebug = flag.Bool([]string{"D", "-debug"}, false, "Enable debug mode") + flCfgFile = flag.String([]string{"c", "-cfg-file"}, "/etc/default/libnetwork.toml", "Configuration file") flHelp = flag.Bool([]string{"h", "-help"}, false, "Print usage") dnetCommands = []command{ diff --git a/libnetwork/cmd/readme_test/readme.go b/libnetwork/cmd/readme_test/readme.go index 58c722cd0c..33f07fd516 100644 --- a/libnetwork/cmd/readme_test/readme.go +++ b/libnetwork/cmd/readme_test/readme.go @@ -11,7 +11,7 @@ import ( func main() { // Create a new controller instance - controller, err := libnetwork.New("/etc/default/libnetwork.toml") + controller, err := libnetwork.New() if err != nil { return } diff --git a/libnetwork/cmd/test/main.go b/libnetwork/cmd/test/main.go index 951b756639..957a0cdab5 100644 --- a/libnetwork/cmd/test/main.go +++ b/libnetwork/cmd/test/main.go @@ -3,7 +3,6 @@ package main import ( "fmt" "net" - "os" "time" log "github.com/Sirupsen/logrus" @@ -14,8 +13,7 @@ import ( func main() { log.SetLevel(log.DebugLevel) - os.Setenv("LIBNETWORK_CFG", "libnetwork.toml") - controller, err := libnetwork.New("libnetwork.toml") + controller, err := libnetwork.New() if err != nil { log.Fatal(err) } diff --git a/libnetwork/config/config.go b/libnetwork/config/config.go index 460e60b31b..6a8a354912 100644 --- a/libnetwork/config/config.go +++ b/libnetwork/config/config.go @@ -1,6 +1,10 @@ package config -import "github.com/BurntSushi/toml" +import ( + "strings" + + "github.com/BurntSushi/toml" +) // Config encapsulates configurations of various Libnetwork components type Config struct { @@ -11,7 +15,9 @@ type Config struct { // DaemonCfg represents libnetwork core configuration type DaemonCfg struct { - Debug bool + Debug bool + DefaultNetwork string + DefaultDriver string } // ClusterCfg represents cluster configuration @@ -41,3 +47,44 @@ func ParseConfig(tomlCfgFile string) (*Config, error) { } return &cfg, nil } + +// Option is a option setter function type used to pass varios configurations +// to the controller +type Option func(c *Config) + +// OptionDefaultNetwork function returns an option setter for a default network +func OptionDefaultNetwork(dn string) Option { + return func(c *Config) { + c.Daemon.DefaultNetwork = strings.TrimSpace(dn) + } +} + +// OptionDefaultDriver function returns an option setter for default driver +func OptionDefaultDriver(dd string) Option { + return func(c *Config) { + c.Daemon.DefaultDriver = strings.TrimSpace(dd) + } +} + +// OptionKVProvider function returns an option setter for kvstore provider +func OptionKVProvider(provider string) Option { + return func(c *Config) { + c.Datastore.Client.Provider = strings.TrimSpace(provider) + } +} + +// OptionKVProviderURL function returns an option setter for kvstore url +func OptionKVProviderURL(url string) Option { + return func(c *Config) { + c.Datastore.Client.Address = strings.TrimSpace(url) + } +} + +// ProcessOptions processes options and stores it in config +func (c *Config) ProcessOptions(options ...Option) { + for _, opt := range options { + if opt != nil { + opt(c) + } + } +} diff --git a/libnetwork/controller.go b/libnetwork/controller.go index 35f945ecb6..06db0bf49d 100644 --- a/libnetwork/controller.go +++ b/libnetwork/controller.go @@ -3,7 +3,7 @@ Package libnetwork provides the basic functionality and extension points to create network namespaces and allocate interfaces for containers to use. // Create a new controller instance - controller, _err := libnetwork.New("/etc/default/libnetwork.toml") + controller, _err := libnetwork.New(nil) // Select and configure the network driver networkType := "bridge" @@ -47,8 +47,6 @@ package libnetwork import ( "fmt" "net" - "os" - "strings" "sync" log "github.com/Sirupsen/logrus" @@ -68,6 +66,9 @@ type NetworkController interface { // ConfigureNetworkDriver applies the passed options to the driver instance for the specified network type ConfigureNetworkDriver(networkType string, options map[string]interface{}) error + // Config method returns the bootup configuration for the controller + Config() config.Config + // Create a new network. The options parameter carries network specific options. // Labels support will be added in the near future. NewNetwork(networkType, name string, options ...NetworkOption) (Network, error) @@ -112,8 +113,14 @@ type controller struct { } // New creates a new instance of network controller. -func New(configFile string) (NetworkController, error) { +func New(cfgOptions ...config.Option) (NetworkController, error) { + var cfg *config.Config + if len(cfgOptions) > 0 { + cfg = &config.Config{} + cfg.ProcessOptions(cfgOptions...) + } c := &controller{ + cfg: cfg, networks: networkTable{}, sandboxes: sandboxTable{}, drivers: driverTable{}} @@ -121,47 +128,27 @@ func New(configFile string) (NetworkController, error) { return nil, err } - if err := c.initConfig(configFile); err == nil { + if cfg != nil { if err := c.initDataStore(); err != nil { // Failing to initalize datastore is a bad situation to be in. // But it cannot fail creating the Controller - log.Warnf("Failed to Initialize Datastore due to %v. Operating in non-clustered mode", err) + log.Debugf("Failed to Initialize Datastore due to %v. Operating in non-clustered mode", err) } if err := c.initDiscovery(); err != nil { // Failing to initalize discovery is a bad situation to be in. // But it cannot fail creating the Controller - log.Warnf("Failed to Initialize Discovery : %v", err) + log.Debugf("Failed to Initialize Discovery : %v", err) } - } else { - // Missing Configuration file is not a failure scenario - // But without that, datastore cannot be initialized. - log.Debugf("Unable to Parse LibNetwork Config file : %v", err) } return c, nil } -const ( - cfgFileEnv = "LIBNETWORK_CFG" - defaultCfgFile = "/etc/default/libnetwork.toml" -) - -func (c *controller) initConfig(configFile string) error { - cfgFile := configFile - if strings.Trim(cfgFile, " ") == "" { - cfgFile = os.Getenv(cfgFileEnv) - if strings.Trim(cfgFile, " ") == "" { - cfgFile = defaultCfgFile - } +func (c *controller) validateHostDiscoveryConfig() bool { + if c.cfg == nil || c.cfg.Cluster.Discovery == "" || c.cfg.Cluster.Address == "" { + return false } - cfg, err := config.ParseConfig(cfgFile) - if err != nil { - return ErrInvalidConfigFile(cfgFile) - } - c.Lock() - c.cfg = cfg - c.Unlock() - return nil + return true } func (c *controller) initDiscovery() error { @@ -179,6 +166,12 @@ func (c *controller) hostJoinCallback(hosts []net.IP) { func (c *controller) hostLeaveCallback(hosts []net.IP) { } +func (c *controller) Config() config.Config { + c.Lock() + defer c.Unlock() + return *c.cfg +} + func (c *controller) ConfigureNetworkDriver(networkType string, options map[string]interface{}) error { c.Lock() dd, ok := c.drivers[networkType] diff --git a/libnetwork/libnetwork_internal_test.go b/libnetwork/libnetwork_internal_test.go index 23a0a54fc7..317afbb7f3 100644 --- a/libnetwork/libnetwork_internal_test.go +++ b/libnetwork/libnetwork_internal_test.go @@ -9,7 +9,7 @@ import ( func TestDriverRegistration(t *testing.T) { bridgeNetType := "bridge" - c, err := New("") + c, err := New() if err != nil { t.Fatal(err) } diff --git a/libnetwork/libnetwork_test.go b/libnetwork/libnetwork_test.go index 6c4b25992f..81c8b91c1f 100644 --- a/libnetwork/libnetwork_test.go +++ b/libnetwork/libnetwork_test.go @@ -63,7 +63,7 @@ func TestMain(m *testing.M) { func createController() error { var err error - controller, err = libnetwork.New("") + controller, err = libnetwork.New() if err != nil { return err } @@ -1665,7 +1665,7 @@ func TestInvalidRemoteDriver(t *testing.T) { t.Fatal(err) } - controller, err := libnetwork.New("") + controller, err := libnetwork.New() if err != nil { t.Fatal(err) } diff --git a/libnetwork/store.go b/libnetwork/store.go index c72d739715..b1b1b5416f 100644 --- a/libnetwork/store.go +++ b/libnetwork/store.go @@ -9,11 +9,18 @@ import ( "github.com/docker/libnetwork/types" ) +func (c *controller) validateDatastoreConfig() bool { + if c.cfg == nil || c.cfg.Datastore.Client.Provider == "" || c.cfg.Datastore.Client.Address == "" { + return false + } + return true +} + func (c *controller) initDataStore() error { c.Lock() cfg := c.cfg c.Unlock() - if cfg == nil { + if !c.validateDatastoreConfig() { return fmt.Errorf("datastore initialization requires a valid configuration") }