Browse code

Refactor code in cmd/dockerd/daemon.go

Signed-off-by: Karthik Karanth <karanth.karthik@gmail.com>

Karthik Karanth authored on 2018/04/13 03:44:20
Showing 2 changed files
... ...
@@ -123,74 +123,15 @@ func (cli *DaemonCli) start(opts *daemonOptions) (err error) {
123 123
 		}()
124 124
 	}
125 125
 
126
-	// TODO: extract to newApiServerConfig()
127
-	serverConfig := &apiserver.Config{
128
-		Logging:     true,
129
-		SocketGroup: cli.Config.SocketGroup,
130
-		Version:     dockerversion.Version,
131
-		CorsHeaders: cli.Config.CorsHeaders,
132
-	}
133
-
134
-	if cli.Config.TLS {
135
-		tlsOptions := tlsconfig.Options{
136
-			CAFile:             cli.Config.CommonTLSOptions.CAFile,
137
-			CertFile:           cli.Config.CommonTLSOptions.CertFile,
138
-			KeyFile:            cli.Config.CommonTLSOptions.KeyFile,
139
-			ExclusiveRootPools: true,
140
-		}
141
-
142
-		if cli.Config.TLSVerify {
143
-			// server requires and verifies client's certificate
144
-			tlsOptions.ClientAuth = tls.RequireAndVerifyClientCert
145
-		}
146
-		tlsConfig, err := tlsconfig.Server(tlsOptions)
147
-		if err != nil {
148
-			return err
149
-		}
150
-		serverConfig.TLSConfig = tlsConfig
151
-	}
152
-
153
-	if len(cli.Config.Hosts) == 0 {
154
-		cli.Config.Hosts = make([]string, 1)
126
+	serverConfig, err := newAPIServerConfig(cli)
127
+	if err != nil {
128
+		return fmt.Errorf("Failed to create API server: %v", err)
155 129
 	}
156
-
157 130
 	cli.api = apiserver.New(serverConfig)
158 131
 
159
-	var hosts []string
160
-
161
-	for i := 0; i < len(cli.Config.Hosts); i++ {
162
-		var err error
163
-		if cli.Config.Hosts[i], err = dopts.ParseHost(cli.Config.TLS, cli.Config.Hosts[i]); err != nil {
164
-			return fmt.Errorf("error parsing -H %s : %v", cli.Config.Hosts[i], err)
165
-		}
166
-
167
-		protoAddr := cli.Config.Hosts[i]
168
-		protoAddrParts := strings.SplitN(protoAddr, "://", 2)
169
-		if len(protoAddrParts) != 2 {
170
-			return fmt.Errorf("bad format %s, expected PROTO://ADDR", protoAddr)
171
-		}
172
-
173
-		proto := protoAddrParts[0]
174
-		addr := protoAddrParts[1]
175
-
176
-		// It's a bad idea to bind to TCP without tlsverify.
177
-		if proto == "tcp" && (serverConfig.TLSConfig == nil || serverConfig.TLSConfig.ClientAuth != tls.RequireAndVerifyClientCert) {
178
-			logrus.Warn("[!] DON'T BIND ON ANY IP ADDRESS WITHOUT setting --tlsverify IF YOU DON'T KNOW WHAT YOU'RE DOING [!]")
179
-		}
180
-		ls, err := listeners.Init(proto, addr, serverConfig.SocketGroup, serverConfig.TLSConfig)
181
-		if err != nil {
182
-			return err
183
-		}
184
-		ls = wrapListeners(proto, ls)
185
-		// If we're binding to a TCP port, make sure that a container doesn't try to use it.
186
-		if proto == "tcp" {
187
-			if err := allocateDaemonPort(addr); err != nil {
188
-				return err
189
-			}
190
-		}
191
-		logrus.Debugf("Listener created for HTTP on %s (%s)", proto, addr)
192
-		hosts = append(hosts, protoAddrParts[1])
193
-		cli.api.Accept(addr, ls...)
132
+	hosts, err := loadListeners(cli, serverConfig)
133
+	if err != nil {
134
+		return fmt.Errorf("Failed to load listeners: %v", err)
194 135
 	}
195 136
 
196 137
 	registryService, err := registry.NewService(cli.Config.ServiceOptions)
... ...
@@ -200,7 +141,7 @@ func (cli *DaemonCli) start(opts *daemonOptions) (err error) {
200 200
 
201 201
 	rOpts, err := cli.getRemoteOptions()
202 202
 	if err != nil {
203
-		return fmt.Errorf("Failed to generate containerd options: %s", err)
203
+		return fmt.Errorf("Failed to generate containerd options: %v", err)
204 204
 	}
205 205
 	containerdRemote, err := libcontainerd.New(filepath.Join(cli.Config.Root, "containerd"), filepath.Join(cli.Config.ExecRoot, "containerd"), rOpts...)
206 206
 	if err != nil {
... ...
@@ -242,31 +183,7 @@ func (cli *DaemonCli) start(opts *daemonOptions) (err error) {
242 242
 		}
243 243
 	}
244 244
 
245
-	// TODO: createAndStartCluster()
246
-	name, _ := os.Hostname()
247
-
248
-	// Use a buffered channel to pass changes from store watch API to daemon
249
-	// A buffer allows store watch API and daemon processing to not wait for each other
250
-	watchStream := make(chan *swarmapi.WatchMessage, 32)
251
-
252
-	c, err := cluster.New(cluster.Config{
253
-		Root:                   cli.Config.Root,
254
-		Name:                   name,
255
-		Backend:                d,
256
-		ImageBackend:           d.ImageService(),
257
-		PluginBackend:          d.PluginManager(),
258
-		NetworkSubnetsProvider: d,
259
-		DefaultAdvertiseAddr:   cli.Config.SwarmDefaultAdvertiseAddr,
260
-		RaftHeartbeatTick:      cli.Config.SwarmRaftHeartbeatTick,
261
-		RaftElectionTick:       cli.Config.SwarmRaftElectionTick,
262
-		RuntimeRoot:            cli.getSwarmRunRoot(),
263
-		WatchStream:            watchStream,
264
-	})
265
-	if err != nil {
266
-		logrus.Fatalf("Error creating cluster component: %v", err)
267
-	}
268
-	d.SetCluster(c)
269
-	err = c.Start()
245
+	c, err := createAndStartCluster(cli, d)
270 246
 	if err != nil {
271 247
 		logrus.Fatalf("Error starting cluster component: %v", err)
272 248
 	}
... ...
@@ -292,7 +209,7 @@ func (cli *DaemonCli) start(opts *daemonOptions) (err error) {
292 292
 	// process cluster change notifications
293 293
 	watchCtx, cancel := context.WithCancel(context.Background())
294 294
 	defer cancel()
295
-	go d.ProcessClusterNotifications(watchCtx, watchStream)
295
+	go d.ProcessClusterNotifications(watchCtx, c.GetWatchStream())
296 296
 
297 297
 	cli.setupConfigReloadTrap()
298 298
 
... ...
@@ -569,6 +486,109 @@ func (cli *DaemonCli) getRemoteOptions() ([]libcontainerd.RemoteOption, error) {
569 569
 	return opts, nil
570 570
 }
571 571
 
572
+func newAPIServerConfig(cli *DaemonCli) (*apiserver.Config, error) {
573
+	serverConfig := &apiserver.Config{
574
+		Logging:     true,
575
+		SocketGroup: cli.Config.SocketGroup,
576
+		Version:     dockerversion.Version,
577
+		CorsHeaders: cli.Config.CorsHeaders,
578
+	}
579
+
580
+	if cli.Config.TLS {
581
+		tlsOptions := tlsconfig.Options{
582
+			CAFile:             cli.Config.CommonTLSOptions.CAFile,
583
+			CertFile:           cli.Config.CommonTLSOptions.CertFile,
584
+			KeyFile:            cli.Config.CommonTLSOptions.KeyFile,
585
+			ExclusiveRootPools: true,
586
+		}
587
+
588
+		if cli.Config.TLSVerify {
589
+			// server requires and verifies client's certificate
590
+			tlsOptions.ClientAuth = tls.RequireAndVerifyClientCert
591
+		}
592
+		tlsConfig, err := tlsconfig.Server(tlsOptions)
593
+		if err != nil {
594
+			return nil, err
595
+		}
596
+		serverConfig.TLSConfig = tlsConfig
597
+	}
598
+
599
+	if len(cli.Config.Hosts) == 0 {
600
+		cli.Config.Hosts = make([]string, 1)
601
+	}
602
+
603
+	return serverConfig, nil
604
+}
605
+
606
+func loadListeners(cli *DaemonCli, serverConfig *apiserver.Config) ([]string, error) {
607
+	var hosts []string
608
+	for i := 0; i < len(cli.Config.Hosts); i++ {
609
+		var err error
610
+		if cli.Config.Hosts[i], err = dopts.ParseHost(cli.Config.TLS, cli.Config.Hosts[i]); err != nil {
611
+			return nil, fmt.Errorf("error parsing -H %s : %v", cli.Config.Hosts[i], err)
612
+		}
613
+
614
+		protoAddr := cli.Config.Hosts[i]
615
+		protoAddrParts := strings.SplitN(protoAddr, "://", 2)
616
+		if len(protoAddrParts) != 2 {
617
+			return nil, fmt.Errorf("bad format %s, expected PROTO://ADDR", protoAddr)
618
+		}
619
+
620
+		proto := protoAddrParts[0]
621
+		addr := protoAddrParts[1]
622
+
623
+		// It's a bad idea to bind to TCP without tlsverify.
624
+		if proto == "tcp" && (serverConfig.TLSConfig == nil || serverConfig.TLSConfig.ClientAuth != tls.RequireAndVerifyClientCert) {
625
+			logrus.Warn("[!] DON'T BIND ON ANY IP ADDRESS WITHOUT setting --tlsverify IF YOU DON'T KNOW WHAT YOU'RE DOING [!]")
626
+		}
627
+		ls, err := listeners.Init(proto, addr, serverConfig.SocketGroup, serverConfig.TLSConfig)
628
+		if err != nil {
629
+			return nil, err
630
+		}
631
+		ls = wrapListeners(proto, ls)
632
+		// If we're binding to a TCP port, make sure that a container doesn't try to use it.
633
+		if proto == "tcp" {
634
+			if err := allocateDaemonPort(addr); err != nil {
635
+				return nil, err
636
+			}
637
+		}
638
+		logrus.Debugf("Listener created for HTTP on %s (%s)", proto, addr)
639
+		hosts = append(hosts, protoAddrParts[1])
640
+		cli.api.Accept(addr, ls...)
641
+	}
642
+
643
+	return hosts, nil
644
+}
645
+
646
+func createAndStartCluster(cli *DaemonCli, d *daemon.Daemon) (*cluster.Cluster, error) {
647
+	name, _ := os.Hostname()
648
+
649
+	// Use a buffered channel to pass changes from store watch API to daemon
650
+	// A buffer allows store watch API and daemon processing to not wait for each other
651
+	watchStream := make(chan *swarmapi.WatchMessage, 32)
652
+
653
+	c, err := cluster.New(cluster.Config{
654
+		Root:                   cli.Config.Root,
655
+		Name:                   name,
656
+		Backend:                d,
657
+		ImageBackend:           d.ImageService(),
658
+		PluginBackend:          d.PluginManager(),
659
+		NetworkSubnetsProvider: d,
660
+		DefaultAdvertiseAddr:   cli.Config.SwarmDefaultAdvertiseAddr,
661
+		RaftHeartbeatTick:      cli.Config.SwarmRaftHeartbeatTick,
662
+		RaftElectionTick:       cli.Config.SwarmRaftElectionTick,
663
+		RuntimeRoot:            cli.getSwarmRunRoot(),
664
+		WatchStream:            watchStream,
665
+	})
666
+	if err != nil {
667
+		return nil, err
668
+	}
669
+	d.SetCluster(c)
670
+	err = c.Start()
671
+
672
+	return c, err
673
+}
674
+
572 675
 // validates that the plugins requested with the --authorization-plugin flag are valid AuthzDriver
573 676
 // plugins present on the host and available to the daemon
574 677
 func validateAuthzPlugins(requestedPlugins []string, pg plugingetter.PluginGetter) error {
... ...
@@ -305,6 +305,13 @@ func (c *Cluster) GetRemoteAddressList() []string {
305 305
 	return c.getRemoteAddressList()
306 306
 }
307 307
 
308
+// GetWatchStream returns the channel to pass changes from store watch API
309
+func (c *Cluster) GetWatchStream() chan *swarmapi.WatchMessage {
310
+	c.mu.RLock()
311
+	defer c.mu.RUnlock()
312
+	return c.watchStream
313
+}
314
+
308 315
 func (c *Cluster) getRemoteAddressList() []string {
309 316
 	state := c.currentNodeState()
310 317
 	if state.swarmNode == nil {