| 
									
										
										
										
											2019-03-07 20:35:16 +00:00
										 |  |  | // Package ready is used to signal readiness of the CoreDNS process. Once all
 | 
					
						
							|  |  |  | // plugins have called in the plugin will signal readiness by returning a 200
 | 
					
						
							|  |  |  | // OK on the HTTP handler (on port 8181). If not ready yet, the handler will
 | 
					
						
							|  |  |  | // return a 503.
 | 
					
						
							|  |  |  | package ready
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import (
 | 
					
						
							|  |  |  | 	"io"
 | 
					
						
							|  |  |  | 	"net"
 | 
					
						
							|  |  |  | 	"net/http"
 | 
					
						
							|  |  |  | 	"sync"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	clog "github.com/coredns/coredns/plugin/pkg/log"
 | 
					
						
							| 
									
										
										
										
											2019-11-20 20:14:37 +08:00
										 |  |  | 	"github.com/coredns/coredns/plugin/pkg/reuseport"
 | 
					
						
							| 
									
										
										
										
											2020-01-17 16:47:45 +01:00
										 |  |  | 	"github.com/coredns/coredns/plugin/pkg/uniq"
 | 
					
						
							| 
									
										
										
										
											2019-03-07 20:35:16 +00:00
										 |  |  | )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var (
 | 
					
						
							|  |  |  | 	log      = clog.NewWithPlugin("ready")
 | 
					
						
							|  |  |  | 	plugins  = &list{}
 | 
					
						
							|  |  |  | 	uniqAddr = uniq.New()
 | 
					
						
							|  |  |  | )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type ready struct {
 | 
					
						
							|  |  |  | 	Addr string
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sync.RWMutex
 | 
					
						
							|  |  |  | 	ln   net.Listener
 | 
					
						
							|  |  |  | 	done bool
 | 
					
						
							|  |  |  | 	mux  *http.ServeMux
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (rd *ready) onStartup() error {
 | 
					
						
							| 
									
										
										
										
											2019-11-20 20:14:37 +08:00
										 |  |  | 	ln, err := reuseport.Listen("tcp", rd.Addr)
 | 
					
						
							| 
									
										
										
										
											2019-03-07 20:35:16 +00:00
										 |  |  | 	if err != nil {
 | 
					
						
							|  |  |  | 		return err
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rd.Lock()
 | 
					
						
							|  |  |  | 	rd.ln = ln
 | 
					
						
							|  |  |  | 	rd.mux = http.NewServeMux()
 | 
					
						
							|  |  |  | 	rd.done = true
 | 
					
						
							|  |  |  | 	rd.Unlock()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rd.mux.HandleFunc("/ready", func(w http.ResponseWriter, _ *http.Request) {
 | 
					
						
							| 
									
										
										
										
											2020-10-01 10:13:23 -04:00
										 |  |  | 		rd.Lock()
 | 
					
						
							|  |  |  | 		defer rd.Unlock()
 | 
					
						
							|  |  |  | 		if !rd.done {
 | 
					
						
							|  |  |  | 			w.WriteHeader(http.StatusServiceUnavailable)
 | 
					
						
							|  |  |  | 			io.WriteString(w, "Shutting down")
 | 
					
						
							|  |  |  | 			return
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							| 
									
										
										
										
											2025-04-08 16:46:30 +03:00
										 |  |  | 		ready, notReadyPlugins := plugins.Ready()
 | 
					
						
							|  |  |  | 		if ready {
 | 
					
						
							| 
									
										
										
										
											2019-03-07 20:35:16 +00:00
										 |  |  | 			w.WriteHeader(http.StatusOK)
 | 
					
						
							| 
									
										
										
										
											2019-09-19 11:38:15 -04:00
										 |  |  | 			io.WriteString(w, http.StatusText(http.StatusOK))
 | 
					
						
							| 
									
										
										
										
											2019-03-07 20:35:16 +00:00
										 |  |  | 			return
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							| 
									
										
										
										
											2025-04-08 16:46:30 +03:00
										 |  |  | 		log.Infof("Plugins not ready: %q", notReadyPlugins)
 | 
					
						
							| 
									
										
										
										
											2019-03-07 20:35:16 +00:00
										 |  |  | 		w.WriteHeader(http.StatusServiceUnavailable)
 | 
					
						
							| 
									
										
										
										
											2025-04-08 16:46:30 +03:00
										 |  |  | 		io.WriteString(w, notReadyPlugins)
 | 
					
						
							| 
									
										
										
										
											2019-03-07 20:35:16 +00:00
										 |  |  | 	})
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	go func() { http.Serve(rd.ln, rd.mux) }()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (rd *ready) onFinalShutdown() error {
 | 
					
						
							|  |  |  | 	rd.Lock()
 | 
					
						
							|  |  |  | 	defer rd.Unlock()
 | 
					
						
							|  |  |  | 	if !rd.done {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	uniqAddr.Unset(rd.Addr)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rd.ln.Close()
 | 
					
						
							|  |  |  | 	rd.done = false
 | 
					
						
							|  |  |  | 	return nil
 | 
					
						
							|  |  |  | }
 |