github.com/KyaXTeam/consul@v1.4.5/agent/retry_join.go (about) 1 package agent 2 3 import ( 4 "fmt" 5 "log" 6 "strings" 7 "time" 8 9 "github.com/hashicorp/consul/lib" 10 discover "github.com/hashicorp/go-discover" 11 discoverk8s "github.com/hashicorp/go-discover/provider/k8s" 12 ) 13 14 func (a *Agent) retryJoinLAN() { 15 r := &retryJoiner{ 16 cluster: "LAN", 17 addrs: a.config.RetryJoinLAN, 18 maxAttempts: a.config.RetryJoinMaxAttemptsLAN, 19 interval: a.config.RetryJoinIntervalLAN, 20 join: a.JoinLAN, 21 logger: a.logger, 22 } 23 if err := r.retryJoin(); err != nil { 24 a.retryJoinCh <- err 25 } 26 } 27 28 func (a *Agent) retryJoinWAN() { 29 r := &retryJoiner{ 30 cluster: "WAN", 31 addrs: a.config.RetryJoinWAN, 32 maxAttempts: a.config.RetryJoinMaxAttemptsWAN, 33 interval: a.config.RetryJoinIntervalWAN, 34 join: a.JoinWAN, 35 logger: a.logger, 36 } 37 if err := r.retryJoin(); err != nil { 38 a.retryJoinCh <- err 39 } 40 } 41 42 // retryJoiner is used to handle retrying a join until it succeeds or all 43 // retries are exhausted. 44 type retryJoiner struct { 45 // cluster is the name of the serf cluster, e.g. "LAN" or "WAN". 46 cluster string 47 48 // addrs is the list of servers or go-discover configurations 49 // to join with. 50 addrs []string 51 52 // maxAttempts is the number of join attempts before giving up. 53 maxAttempts int 54 55 // interval is the time between two join attempts. 56 interval time.Duration 57 58 // join adds the discovered or configured servers to the given 59 // serf cluster. 60 join func([]string) (int, error) 61 62 // logger is the agent logger. Log messages should contain the 63 // "agent: " prefix. 64 logger *log.Logger 65 } 66 67 func (r *retryJoiner) retryJoin() error { 68 if len(r.addrs) == 0 { 69 return nil 70 } 71 72 // Copy the default providers, and then add the non-default 73 providers := make(map[string]discover.Provider) 74 for k, v := range discover.Providers { 75 providers[k] = v 76 } 77 providers["k8s"] = &discoverk8s.Provider{} 78 79 disco, err := discover.New( 80 discover.WithUserAgent(lib.UserAgent()), 81 discover.WithProviders(providers), 82 ) 83 if err != nil { 84 return err 85 } 86 87 r.logger.Printf("[INFO] agent: Retry join %s is supported for: %s", r.cluster, strings.Join(disco.Names(), " ")) 88 r.logger.Printf("[INFO] agent: Joining %s cluster...", r.cluster) 89 attempt := 0 90 for { 91 var addrs []string 92 var err error 93 94 for _, addr := range r.addrs { 95 switch { 96 case strings.Contains(addr, "provider="): 97 servers, err := disco.Addrs(addr, r.logger) 98 if err != nil { 99 r.logger.Printf("[ERR] agent: Join %s: %s", r.cluster, err) 100 } else { 101 addrs = append(addrs, servers...) 102 r.logger.Printf("[INFO] agent: Discovered %s servers: %s", r.cluster, strings.Join(servers, " ")) 103 } 104 105 default: 106 addrs = append(addrs, addr) 107 } 108 } 109 110 if len(addrs) > 0 { 111 n, err := r.join(addrs) 112 if err == nil { 113 r.logger.Printf("[INFO] agent: Join %s completed. Synced with %d initial agents", r.cluster, n) 114 return nil 115 } 116 } 117 118 if len(addrs) == 0 { 119 err = fmt.Errorf("No servers to join") 120 } 121 122 attempt++ 123 if r.maxAttempts > 0 && attempt > r.maxAttempts { 124 return fmt.Errorf("agent: max join %s retry exhausted, exiting", r.cluster) 125 } 126 127 r.logger.Printf("[WARN] agent: Join %s failed: %v, retrying in %v", r.cluster, err, r.interval) 128 time.Sleep(r.interval) 129 } 130 }