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") }