func (s *httpServer) deleteChannelHandler(w http.ResponseWriter, req *http.Request) { if req.Method != "POST" { s.ctx.nsqadmin.logf("ERROR: invalid %s to POST only method", req.Method) http.Error(w, "INVALID_REQUEST", 500) return } reqParams := &http_api.PostParams{req} topicName, channelName, err := http_api.GetTopicChannelArgs(reqParams) if err != nil { http.Error(w, err.Error(), 500) return } rd, _ := reqParams.Get("rd") if !strings.HasPrefix(rd, "/") { rd = fmt.Sprintf("/topic/%s", url.QueryEscape(topicName)) } for _, addr := range s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses { nsqlookupdVersion, err := lookupd.GetVersion(addr) if err != nil { s.ctx.nsqadmin.logf("ERROR: failed to get nsqlookupd %s version - %s", addr, err) } uri := "delete_channel" if !nsqlookupdVersion.LT(v1EndpointVersion) { uri = "channel/delete" } endpoint := fmt.Sprintf("http://%s/%s?topic=%s&channel=%s", addr, uri, url.QueryEscape(topicName), url.QueryEscape(channelName)) s.ctx.nsqadmin.logf("LOOKUPD: querying %s", endpoint) _, err = http_api.NegotiateV1("POST", endpoint, nil) if err != nil { s.ctx.nsqadmin.logf("ERROR: lookupd %s - %s", endpoint, err) continue } } producerAddrs := s.getProducers(topicName) s.performVersionNegotiatedRequestsToNSQD( s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses, producerAddrs, "delete_channel", "channel/delete", fmt.Sprintf("topic=%s&channel=%s", url.QueryEscape(topicName), url.QueryEscape(channelName))) s.notifyAdminAction("delete_channel", topicName, channelName, "", req) http.Redirect(w, req, rd, 302) }
func (s *httpServer) deleteTopicHandler(w http.ResponseWriter, req *http.Request) { if req.Method != "POST" { s.ctx.nsqadmin.logf("ERROR: invalid %s to POST only method", req.Method) http.Error(w, "INVALID_REQUEST", 500) return } reqParams := &http_api.PostParams{req} topicName, err := reqParams.Get("topic") if err != nil { http.Error(w, "MISSING_ARG_TOPIC", 500) return } rd, _ := reqParams.Get("rd") if !strings.HasPrefix(rd, "/") { rd = "/" } // for topic removal, you need to get all the producers *first* producerAddrs := s.getProducers(topicName) // remove the topic from all the lookupds for _, addr := range s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses { nsqlookupdVersion, err := lookupd.GetVersion(addr) if err != nil { s.ctx.nsqadmin.logf("ERROR: failed to get nsqlookupd %s version - %s", addr, err) } uri := "delete_topic" if !nsqlookupdVersion.LT(v1EndpointVersion) { uri = "topic/delete" } endpoint := fmt.Sprintf("http://%s/%s?topic=%s", addr, uri, url.QueryEscape(topicName)) s.ctx.nsqadmin.logf("LOOKUPD: querying %s", endpoint) _, err = http_api.NegotiateV1("POST", endpoint, nil) if err != nil { s.ctx.nsqadmin.logf("ERROR: lookupd %s - %s", endpoint, err) continue } } s.performVersionNegotiatedRequestsToNSQD( s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses, producerAddrs, "delete_topic", "topic/delete", fmt.Sprintf("topic=%s", url.QueryEscape(topicName))) s.notifyAdminAction("delete_topic", topicName, "", "", req) http.Redirect(w, req, rd, 302) }
func (s *httpServer) performVersionNegotiatedRequestsToNSQD( nsqlookupdAddrs []string, nsqdAddrs []string, deprecatedURI string, v1URI string, queryString string) { var err error // get producer structs in one set of up-front requests // so we can negotiate versions // // (this returns an empty list if there are no nsqlookupd configured) producers, _ := lookupd.GetLookupdProducers(nsqlookupdAddrs) for _, addr := range nsqdAddrs { var nodeVer semver.Version uri := deprecatedURI producer := producerSearch(producers, addr) if producer != nil { nodeVer = producer.VersionObj } else { // we couldn't find the node in our list // so ask it for a version directly nodeVer, err = lookupd.GetVersion(addr) if err != nil { s.ctx.nsqadmin.logf("ERROR: failed to get nsqd %s version - %s", addr, err) } } if nodeVer.NE(semver.Version{}) && nodeVer.GTE(v1EndpointVersion) { uri = v1URI } endpoint := fmt.Sprintf("http://%s/%s?%s", addr, uri, queryString) s.ctx.nsqadmin.logf("NSQD: querying %s", endpoint) _, err := http_api.NegotiateV1("POST", endpoint, nil) if err != nil { s.ctx.nsqadmin.logf("ERROR: nsqd %s - %s", endpoint, err) continue } } }
func (s *httpServer) tombstoneTopicProducerHandler(w http.ResponseWriter, req *http.Request) { if req.Method != "POST" { s.ctx.nsqadmin.logf("ERROR: invalid %s to POST only method", req.Method) http.Error(w, "INVALID_REQUEST", 500) return } reqParams := &http_api.PostParams{req} topicName, err := reqParams.Get("topic") if err != nil { http.Error(w, "MISSING_ARG_TOPIC", 500) return } node, err := reqParams.Get("node") if err != nil { http.Error(w, "MISSING_ARG_NODE", 500) return } rd, _ := reqParams.Get("rd") if !strings.HasPrefix(rd, "/") { rd = "/" } // tombstone the topic on all the lookupds for _, addr := range s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses { nsqlookupdVersion, err := lookupd.GetVersion(addr) if err != nil { s.ctx.nsqadmin.logf("ERROR: failed to get nsqlookupd %s version - %s", addr, err) } uri := "tombstone_topic_producer" if !nsqlookupdVersion.LT(v1EndpointVersion) { uri = "topic/tombstone" } endpoint := fmt.Sprintf("http://%s/%s?topic=%s&node=%s", addr, uri, url.QueryEscape(topicName), url.QueryEscape(node)) s.ctx.nsqadmin.logf("LOOKUPD: querying %s", endpoint) _, err = http_api.NegotiateV1("POST", endpoint, nil) if err != nil { s.ctx.nsqadmin.logf("ERROR: lookupd %s - %s", endpoint, err) } } nsqdVersion, err := lookupd.GetVersion(node) if err != nil { s.ctx.nsqadmin.logf("ERROR: failed to get nsqd %s version - %s", node, err) } uri := "delete_topic" if !nsqdVersion.LT(v1EndpointVersion) { uri = "topic/delete" } // delete the topic on the producer endpoint := fmt.Sprintf("http://%s/%s?topic=%s", node, uri, url.QueryEscape(topicName)) s.ctx.nsqadmin.logf("NSQD: querying %s", endpoint) _, err = http_api.NegotiateV1("POST", endpoint, nil) if err != nil { s.ctx.nsqadmin.logf("ERROR: nsqd %s - %s", endpoint, err) } s.notifyAdminAction("tombstone_topic_producer", topicName, "", node, req) http.Redirect(w, req, rd, 302) }
func (s *httpServer) createTopicChannelHandler(w http.ResponseWriter, req *http.Request) { if req.Method != "POST" { s.ctx.nsqadmin.logf("ERROR: invalid %s to POST only method", req.Method) http.Error(w, "INVALID_REQUEST", 500) return } reqParams := &http_api.PostParams{req} topicName, err := reqParams.Get("topic") if err != nil || !protocol.IsValidTopicName(topicName) { http.Error(w, "INVALID_TOPIC", 500) return } channelName, err := reqParams.Get("channel") if err != nil || (len(channelName) > 0 && !protocol.IsValidChannelName(channelName)) { http.Error(w, "INVALID_CHANNEL", 500) return } for _, addr := range s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses { nsqlookupdVersion, err := lookupd.GetVersion(addr) if err != nil { s.ctx.nsqadmin.logf("ERROR: failed to get nsqlookupd %s version - %s", addr, err) } uri := "create_topic" if !nsqlookupdVersion.LT(v1EndpointVersion) { uri = "topic/create" } endpoint := fmt.Sprintf("http://%s/%s?topic=%s", addr, uri, url.QueryEscape(topicName)) s.ctx.nsqadmin.logf("LOOKUPD: querying %s", endpoint) _, err = http_api.NegotiateV1("POST", endpoint, nil) if err != nil { s.ctx.nsqadmin.logf("ERROR: lookupd %s - %s", endpoint, err) continue } if len(channelName) > 0 { uri := "create_channel" if !nsqlookupdVersion.LT(v1EndpointVersion) { uri = "channel/create" } endpoint := fmt.Sprintf("http://%s/%s?topic=%s&channel=%s", addr, uri, url.QueryEscape(topicName), url.QueryEscape(channelName)) s.ctx.nsqadmin.logf("LOOKUPD: querying %s", endpoint) _, err := http_api.NegotiateV1("POST", endpoint, nil) if err != nil { s.ctx.nsqadmin.logf("ERROR: lookupd %s - %s", endpoint, err) continue } } } s.notifyAdminAction("create_topic", topicName, "", "", req) if len(channelName) > 0 { // TODO: we can remove this when we push new channel information from nsqlookupd -> nsqd producerAddrs, _ := lookupd.GetLookupdTopicProducers(topicName, s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses) s.performVersionNegotiatedRequestsToNSQD( s.ctx.nsqadmin.opts.NSQLookupdHTTPAddresses, producerAddrs, "create_channel", "channel/create", fmt.Sprintf("topic=%s&channel=%s", url.QueryEscape(topicName), url.QueryEscape(channelName))) s.notifyAdminAction("create_channel", topicName, channelName, "", req) } http.Redirect(w, req, "/lookup", 302) }