package latticestore import ( "github.com/golang/glog" "encoding/json" "net" "net/http" "strings" "time" "github.com/aws/aws-application-networking-k8s/pkg/utils/retry" ) const ( // defaultIntrospectionAddress is listening on localhost 61679 for ipamd introspection defaultIntrospectionBindAddress = "0.0.0.0:61680" ) type rootResponse struct { AvailableCommands []string } // LoggingHandler is a object for handling http request type LoggingHandler struct { h http.Handler } func (lh LoggingHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { glog.V(6).Infof("Handling http request: %s, from: %s, URI: %s\n", r.Method, r.RemoteAddr, r.RequestURI) lh.h.ServeHTTP(w, r) } func (c *LatticeDataStore) ServeIntrospection() { glog.V(6).Infof("Starting LatticeDataStore serve Introspection\n") server := c.setupIntrospectionServer() for { _ = retry.WithBackoff(retry.NewSimpleBackoff(time.Second, time.Minute, 0.2, 2), func() error { var ln net.Listener var err error if strings.HasPrefix(server.Addr, "unix:") { socket := strings.TrimPrefix(server.Addr, "unix:") ln, err = net.Listen("unix", socket) } else { ln, err = net.Listen("tcp", server.Addr) } if err == nil { err = server.Serve(ln) } return err }) } } func (c *LatticeDataStore) setupIntrospectionServer() *http.Server { serverFunctions := map[string]func(w http.ResponseWriter, r *http.Request){ "/v1/latticecache": latticecacheHandler(c), } paths := make([]string, 0, len(serverFunctions)) for path := range serverFunctions { paths = append(paths, path) } availableCommands := &rootResponse{paths} // Autogenerated list of the above serverFunctions paths availableCommandResponse, err := json.Marshal(&availableCommands) if err != nil { glog.V(6).Infof("Failed to marshal: %v\n", err) } defaultHandler := func(w http.ResponseWriter, r *http.Request) { glog.V(6).Info(w.Write(availableCommandResponse)) } serveMux := http.NewServeMux() serveMux.HandleFunc("/", defaultHandler) for key, fn := range serverFunctions { serveMux.HandleFunc(key, fn) } // Log all requests and then pass through to serveMux loggingServeMux := http.NewServeMux() loggingServeMux.Handle("/", LoggingHandler{serveMux}) addr := defaultIntrospectionBindAddress glog.V(2).Infof("Serving introspection endpoints on %s\n", addr) server := &http.Server{ Addr: addr, Handler: loggingServeMux, ReadTimeout: 5 * time.Second, WriteTimeout: 5 * time.Second, } return server } func latticecacheHandler(c *LatticeDataStore) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { store := dumpCurrentLatticeDataStore(c) //TODO responseJSON, err := json.Marshal(store) if err != nil { glog.V(6).Infof("Failed to marshal mecurycache %v\n", err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } glog.V(6).Infof("store :%v \n", store) glog.V(6).Info(w.Write(responseJSON)) } }