// NewClient is used to create a new client from the given configuration func NewClient(cfg *config.Config, consulSyncer *consul.Syncer, logger *log.Logger) (*Client, error) { // Create the client c := &Client{ config: cfg, consulSyncer: consulSyncer, start: time.Now(), connPool: nomad.NewPool(cfg.LogOutput, clientRPCCache, clientMaxStreams, nil), logger: logger, hostStatsCollector: stats.NewHostStatsCollector(), allocs: make(map[string]*AllocRunner), allocUpdates: make(chan *structs.Allocation, 64), shutdownCh: make(chan struct{}), } // Initialize the client if err := c.init(); err != nil { return nil, fmt.Errorf("failed to initialize client: %v", err) } // Setup the node if err := c.setupNode(); err != nil { return nil, fmt.Errorf("node setup failed: %v", err) } // Fingerprint the node if err := c.fingerprint(); err != nil { return nil, fmt.Errorf("fingerprinting failed: %v", err) } // Scan for drivers if err := c.setupDrivers(); err != nil { return nil, fmt.Errorf("driver setup failed: %v", err) } // Setup the reserved resources c.reservePorts() // Store the config copy before restoring state but after it has been // initialized. c.configLock.Lock() c.configCopy = c.config.Copy() c.configLock.Unlock() // Create the RPC Proxy and bootstrap with the preconfigured list of // static servers c.configLock.RLock() c.rpcProxy = rpcproxy.NewRPCProxy(c.logger, c.shutdownCh, c, c.connPool) for _, serverAddr := range c.configCopy.Servers { c.rpcProxy.AddPrimaryServer(serverAddr) } c.configLock.RUnlock() // Restore the state if err := c.restoreState(); err != nil { return nil, fmt.Errorf("failed to restore state: %v", err) } // Setup the Consul syncer if err := c.setupConsulSyncer(); err != nil { return nil, fmt.Errorf("failed to create client Consul syncer: %v") } // Register and then start heartbeating to the servers. go c.registerAndHeartbeat() // Begin periodic snapshotting of state. go c.periodicSnapshot() // Begin syncing allocations to the server go c.allocSync() // Start the client! go c.run() // Start collecting stats go c.collectHostStats() // Start the RPCProxy maintenance task. This task periodically // shuffles the list of Nomad Server Endpoints this Client will use // when communicating with Nomad Servers via RPC. This is done in // order to prevent server fixation in stable Nomad clusters. This // task actively populates the active list of Nomad Server Endpoints // from information from the Nomad Client heartbeats. If a heartbeat // times out and there are no Nomad servers available, this data is // populated by periodically polling Consul, if available. go c.rpcProxy.Run() return c, nil }
// NewClient is used to create a new client from the given configuration func NewClient(cfg *config.Config) (*Client, error) { // Create a logger logger := log.New(cfg.LogOutput, "", log.LstdFlags) resourceUsage, err := stats.NewRingBuff(cfg.StatsDataPoints) if err != nil { return nil, err } // Create the client c := &Client{ config: cfg, start: time.Now(), connPool: nomad.NewPool(cfg.LogOutput, clientRPCCache, clientMaxStreams, nil), logger: logger, hostStatsCollector: stats.NewHostStatsCollector(), resourceUsage: resourceUsage, allocs: make(map[string]*AllocRunner), allocUpdates: make(chan *structs.Allocation, 64), shutdownCh: make(chan struct{}), } // Initialize the client if err := c.init(); err != nil { return nil, fmt.Errorf("failed to initialize client: %v", err) } // Setup the node if err := c.setupNode(); err != nil { return nil, fmt.Errorf("node setup failed: %v", err) } // Fingerprint the node if err := c.fingerprint(); err != nil { return nil, fmt.Errorf("fingerprinting failed: %v", err) } // Scan for drivers if err := c.setupDrivers(); err != nil { return nil, fmt.Errorf("driver setup failed: %v", err) } // Setup the reserved resources c.reservePorts() // Set up the known servers list c.SetServers(c.config.Servers) // Store the config copy before restoring state but after it has been // initialized. c.configCopy = c.config.Copy() // Restore the state if err := c.restoreState(); err != nil { return nil, fmt.Errorf("failed to restore state: %v", err) } // Setup the consul client if err := c.setupConsulClient(); err != nil { return nil, fmt.Errorf("failed to create consul client: %v") } // Register and then start heartbeating to the servers. go c.registerAndHeartbeat() // Begin periodic snapshotting of state. go c.periodicSnapshot() // Begin syncing allocations to the server go c.allocSync() // Start the client! go c.run() // Start collecting stats go c.collectHostStats() // Start the consul sync go c.syncConsul() return c, nil }