mirror of https://github.com/status-im/consul.git
agent: consolidate handling of 405 Method Not Allowed (#3405)
* agent: consolidate http method not allowed checks This patch uses the error handling of the http handlers to handle HTTP method not allowed errors across all available endpoints. It also adds a test for testing whether the endpoints respond with the correct status code. * agent: do not panic on metrics tests * agent: drop other tests for MethodNotAllowed * agent: align /agent/join with reality /agent/join uses PUT instead of GET as documented. * agent: align /agent/check/{fail,warn,pass} with reality /agent/check/{fail,warn,pass} uses PUT instead of GET as documented. * fix some tests * Drop more tests for method not allowed * Align TestAgent_RegisterService_InvalidAddress with reality * Changes API client join to use PUT instead of GET. * Fixes agent endpoint verbs and removes obsolete tests. * Updates the change log.
This commit is contained in:
parent
5143218ae1
commit
1e461110e6
43
CHANGELOG.md
43
CHANGELOG.md
|
@ -2,7 +2,48 @@
|
||||||
|
|
||||||
BREAKING CHANGES:
|
BREAKING CHANGES:
|
||||||
|
|
||||||
* **Raft Protocol Defaults to 3:** The [`-raft-protocol`](https://www.consul.io/docs/agent/options.html#_raft_protocol) default has been changed from 2 to 3, enabling all Autopilot features by default. Version 3 requires Consul running 0.8.0 or newer on all servers in order to work, so if you are upgrading with older servers in a cluster then you will need to set this back to 2 in order to upgrade. See [Raft Protocol Version Compatibility](https://www.consul.io/docs/upgrade-specific.html#raft-protocol-version-compatibility) for more details. Also the format of `peers.json` used for outage recovery is different when running with the lastest Raft protocol. See [Manual Recovery Using peers.json](https://www.consul.io/docs/guides/outage.html#manual-recovery-using-peers-json) for a description of the required format.
|
* **Raft Protocol Defaults to 3:** The [`-raft-protocol`](https://www.consul.io/docs/agent/options.html#_raft_protocol) default has been changed from 2 to 3, enabling all Autopilot features by default. Version 3 requires Consul running 0.8.0 or newer on all servers in order to work, so if you are upgrading with older servers in a cluster then you will need to set this back to 2 in order to upgrade. See [Raft Protocol Version Compatibility](https://www.consul.io/docs/upgrade-specific.html#raft-protocol-version-compatibility) for more details. Also the format of `peers.json` used for outage recovery is different when running with the lastest Raft protocol. See [Manual Recovery Using peers.json](https://www.consul.io/docs/guides/outage.html#manual-recovery-using-peers-json) for a description of the required format. [GH-3477]
|
||||||
|
* **HTTP Verb Enforcement:** Many endpoints in the HTTP API that previously took any HTTP verb now check for specific HTTP verbs and enforce them. This may break clients relying on the old behavior. The table below has the endpoints that were updated. [GH-3405]
|
||||||
|
| Endpoint | Required Verbs |
|
||||||
|
| -------- | -------------- |
|
||||||
|
| /v1/acl/info | GET |
|
||||||
|
| /v1/acl/list | GET |
|
||||||
|
| /v1/acl/replication | GET |
|
||||||
|
| /v1/agent/check/deregister | PUT |
|
||||||
|
| /v1/agent/check/fail | PUT |
|
||||||
|
| /v1/agent/check/pass | PUT |
|
||||||
|
| /v1/agent/check/register | PUT |
|
||||||
|
| /v1/agent/check/warn | PUT |
|
||||||
|
| /v1/agent/checks | GET |
|
||||||
|
| /v1/agent/force-leave | PUT |
|
||||||
|
| /v1/agent/join | PUT |
|
||||||
|
| /v1/agent/members | GET |
|
||||||
|
| /v1/agent/metrics | GET |
|
||||||
|
| /v1/agent/self | GET |
|
||||||
|
| /v1/agent/service/register | PUT |
|
||||||
|
| /v1/agent/service/deregister | PUT |
|
||||||
|
| /v1/agent/services | GET |
|
||||||
|
| /v1/catalog/datacenters | GET |
|
||||||
|
| /v1/catalog/deregister | PUT |
|
||||||
|
| /v1/catalog/node | GET |
|
||||||
|
| /v1/catalog/nodes | GET |
|
||||||
|
| /v1/catalog/register | PUT |
|
||||||
|
| /v1/catalog/service | GET |
|
||||||
|
| /v1/catalog/services | GET |
|
||||||
|
| /v1/coordinate/datacenters | GET |
|
||||||
|
| /v1/coordinate/nodes | GET |
|
||||||
|
| /v1/health/checks | GET |
|
||||||
|
| /v1/health/node | GET |
|
||||||
|
| /v1/health/service | GET |
|
||||||
|
| /v1/health/state | GET |
|
||||||
|
| /v1/internal/ui/node | GET |
|
||||||
|
| /v1/internal/ui/nodes | GET |
|
||||||
|
| /v1/internal/ui/services | GET |
|
||||||
|
| /v1/session/info | GET |
|
||||||
|
| /v1/session/list | GET |
|
||||||
|
| /v1/session/node | GET |
|
||||||
|
| /v1/status/leader | GET |
|
||||||
|
| /v1/status/peers | GET |
|
||||||
|
|
||||||
FEATURES:
|
FEATURES:
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,7 @@ func ACLDisabled(resp http.ResponseWriter, req *http.Request) (interface{}, erro
|
||||||
// a cluster to get the first management token.
|
// a cluster to get the first management token.
|
||||||
func (s *HTTPServer) ACLBootstrap(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) ACLBootstrap(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
if req.Method != "PUT" {
|
if req.Method != "PUT" {
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
args := structs.DCSpecificRequest{
|
args := structs.DCSpecificRequest{
|
||||||
|
@ -49,10 +48,8 @@ func (s *HTTPServer) ACLBootstrap(resp http.ResponseWriter, req *http.Request) (
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) ACLDestroy(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) ACLDestroy(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
// Mandate a PUT request
|
|
||||||
if req.Method != "PUT" {
|
if req.Method != "PUT" {
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
args := structs.ACLRequest{
|
args := structs.ACLRequest{
|
||||||
|
@ -77,18 +74,22 @@ func (s *HTTPServer) ACLDestroy(resp http.ResponseWriter, req *http.Request) (in
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) ACLCreate(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) ACLCreate(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "PUT" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
|
}
|
||||||
return s.aclSet(resp, req, false)
|
return s.aclSet(resp, req, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) ACLUpdate(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) ACLUpdate(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "PUT" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
|
}
|
||||||
return s.aclSet(resp, req, true)
|
return s.aclSet(resp, req, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) aclSet(resp http.ResponseWriter, req *http.Request, update bool) (interface{}, error) {
|
func (s *HTTPServer) aclSet(resp http.ResponseWriter, req *http.Request, update bool) (interface{}, error) {
|
||||||
// Mandate a PUT request
|
|
||||||
if req.Method != "PUT" {
|
if req.Method != "PUT" {
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
args := structs.ACLRequest{
|
args := structs.ACLRequest{
|
||||||
|
@ -128,10 +129,8 @@ func (s *HTTPServer) aclSet(resp http.ResponseWriter, req *http.Request, update
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) ACLClone(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) ACLClone(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
// Mandate a PUT request
|
|
||||||
if req.Method != "PUT" {
|
if req.Method != "PUT" {
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
args := structs.ACLSpecificRequest{
|
args := structs.ACLSpecificRequest{
|
||||||
|
@ -182,6 +181,10 @@ func (s *HTTPServer) ACLClone(resp http.ResponseWriter, req *http.Request) (inte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) ACLGet(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) ACLGet(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
args := structs.ACLSpecificRequest{
|
args := structs.ACLSpecificRequest{
|
||||||
Datacenter: s.agent.config.ACLDatacenter,
|
Datacenter: s.agent.config.ACLDatacenter,
|
||||||
}
|
}
|
||||||
|
@ -212,6 +215,10 @@ func (s *HTTPServer) ACLGet(resp http.ResponseWriter, req *http.Request) (interf
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) ACLList(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) ACLList(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
args := structs.DCSpecificRequest{
|
args := structs.DCSpecificRequest{
|
||||||
Datacenter: s.agent.config.ACLDatacenter,
|
Datacenter: s.agent.config.ACLDatacenter,
|
||||||
}
|
}
|
||||||
|
@ -234,6 +241,10 @@ func (s *HTTPServer) ACLList(resp http.ResponseWriter, req *http.Request) (inter
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) ACLReplicationStatus(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) ACLReplicationStatus(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
// Note that we do not forward to the ACL DC here. This is a query for
|
// Note that we do not forward to the ACL DC here. This is a query for
|
||||||
// any DC that's doing replication.
|
// any DC that's doing replication.
|
||||||
args := structs.DCSpecificRequest{}
|
args := structs.DCSpecificRequest{}
|
||||||
|
|
|
@ -44,7 +44,6 @@ func TestACL_Bootstrap(t *testing.T) {
|
||||||
code int
|
code int
|
||||||
token bool
|
token bool
|
||||||
}{
|
}{
|
||||||
{"bad method", "GET", http.StatusMethodNotAllowed, false},
|
|
||||||
{"bootstrap", "PUT", http.StatusOK, true},
|
{"bootstrap", "PUT", http.StatusOK, true},
|
||||||
{"not again", "PUT", http.StatusForbidden, false},
|
{"not again", "PUT", http.StatusForbidden, false},
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,10 @@ type Self struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) AgentSelf(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) AgentSelf(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
var cs lib.CoordinateSet
|
var cs lib.CoordinateSet
|
||||||
if !s.agent.config.DisableCoordinates {
|
if !s.agent.config.DisableCoordinates {
|
||||||
var err error
|
var err error
|
||||||
|
@ -58,6 +62,10 @@ func (s *HTTPServer) AgentSelf(resp http.ResponseWriter, req *http.Request) (int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) AgentMetrics(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) AgentMetrics(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch the ACL token, if any, and enforce agent policy.
|
// Fetch the ACL token, if any, and enforce agent policy.
|
||||||
var token string
|
var token string
|
||||||
s.parseToken(req, &token)
|
s.parseToken(req, &token)
|
||||||
|
@ -74,8 +82,7 @@ func (s *HTTPServer) AgentMetrics(resp http.ResponseWriter, req *http.Request) (
|
||||||
|
|
||||||
func (s *HTTPServer) AgentReload(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) AgentReload(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
if req.Method != "PUT" {
|
if req.Method != "PUT" {
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the ACL token, if any, and enforce agent policy.
|
// Fetch the ACL token, if any, and enforce agent policy.
|
||||||
|
@ -107,6 +114,10 @@ func (s *HTTPServer) AgentReload(resp http.ResponseWriter, req *http.Request) (i
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) AgentServices(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) AgentServices(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch the ACL token, if any.
|
// Fetch the ACL token, if any.
|
||||||
var token string
|
var token string
|
||||||
s.parseToken(req, &token)
|
s.parseToken(req, &token)
|
||||||
|
@ -127,6 +138,10 @@ func (s *HTTPServer) AgentServices(resp http.ResponseWriter, req *http.Request)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) AgentChecks(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) AgentChecks(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch the ACL token, if any.
|
// Fetch the ACL token, if any.
|
||||||
var token string
|
var token string
|
||||||
s.parseToken(req, &token)
|
s.parseToken(req, &token)
|
||||||
|
@ -147,6 +162,10 @@ func (s *HTTPServer) AgentChecks(resp http.ResponseWriter, req *http.Request) (i
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) AgentMembers(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) AgentMembers(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch the ACL token, if any.
|
// Fetch the ACL token, if any.
|
||||||
var token string
|
var token string
|
||||||
s.parseToken(req, &token)
|
s.parseToken(req, &token)
|
||||||
|
@ -192,6 +211,10 @@ func (s *HTTPServer) AgentMembers(resp http.ResponseWriter, req *http.Request) (
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) AgentJoin(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) AgentJoin(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "PUT" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch the ACL token, if any, and enforce agent policy.
|
// Fetch the ACL token, if any, and enforce agent policy.
|
||||||
var token string
|
var token string
|
||||||
s.parseToken(req, &token)
|
s.parseToken(req, &token)
|
||||||
|
@ -221,8 +244,7 @@ func (s *HTTPServer) AgentJoin(resp http.ResponseWriter, req *http.Request) (int
|
||||||
|
|
||||||
func (s *HTTPServer) AgentLeave(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) AgentLeave(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
if req.Method != "PUT" {
|
if req.Method != "PUT" {
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the ACL token, if any, and enforce agent policy.
|
// Fetch the ACL token, if any, and enforce agent policy.
|
||||||
|
@ -243,6 +265,10 @@ func (s *HTTPServer) AgentLeave(resp http.ResponseWriter, req *http.Request) (in
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) AgentForceLeave(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) AgentForceLeave(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "PUT" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch the ACL token, if any, and enforce agent policy.
|
// Fetch the ACL token, if any, and enforce agent policy.
|
||||||
var token string
|
var token string
|
||||||
s.parseToken(req, &token)
|
s.parseToken(req, &token)
|
||||||
|
@ -270,6 +296,10 @@ func (s *HTTPServer) syncChanges() {
|
||||||
const invalidCheckMessage = "Must provide TTL or Script/DockerContainerID/HTTP/TCP and Interval"
|
const invalidCheckMessage = "Must provide TTL or Script/DockerContainerID/HTTP/TCP and Interval"
|
||||||
|
|
||||||
func (s *HTTPServer) AgentRegisterCheck(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) AgentRegisterCheck(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "PUT" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
|
}
|
||||||
|
|
||||||
var args structs.CheckDefinition
|
var args structs.CheckDefinition
|
||||||
// Fixup the type decode of TTL or Interval.
|
// Fixup the type decode of TTL or Interval.
|
||||||
decodeCB := func(raw interface{}) error {
|
decodeCB := func(raw interface{}) error {
|
||||||
|
@ -321,6 +351,10 @@ func (s *HTTPServer) AgentRegisterCheck(resp http.ResponseWriter, req *http.Requ
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) AgentDeregisterCheck(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) AgentDeregisterCheck(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "PUT" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
|
}
|
||||||
|
|
||||||
checkID := types.CheckID(strings.TrimPrefix(req.URL.Path, "/v1/agent/check/deregister/"))
|
checkID := types.CheckID(strings.TrimPrefix(req.URL.Path, "/v1/agent/check/deregister/"))
|
||||||
|
|
||||||
// Get the provided token, if any, and vet against any ACL policies.
|
// Get the provided token, if any, and vet against any ACL policies.
|
||||||
|
@ -338,6 +372,10 @@ func (s *HTTPServer) AgentDeregisterCheck(resp http.ResponseWriter, req *http.Re
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) AgentCheckPass(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) AgentCheckPass(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "PUT" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
|
}
|
||||||
|
|
||||||
checkID := types.CheckID(strings.TrimPrefix(req.URL.Path, "/v1/agent/check/pass/"))
|
checkID := types.CheckID(strings.TrimPrefix(req.URL.Path, "/v1/agent/check/pass/"))
|
||||||
note := req.URL.Query().Get("note")
|
note := req.URL.Query().Get("note")
|
||||||
|
|
||||||
|
@ -356,6 +394,10 @@ func (s *HTTPServer) AgentCheckPass(resp http.ResponseWriter, req *http.Request)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) AgentCheckWarn(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) AgentCheckWarn(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "PUT" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
|
}
|
||||||
|
|
||||||
checkID := types.CheckID(strings.TrimPrefix(req.URL.Path, "/v1/agent/check/warn/"))
|
checkID := types.CheckID(strings.TrimPrefix(req.URL.Path, "/v1/agent/check/warn/"))
|
||||||
note := req.URL.Query().Get("note")
|
note := req.URL.Query().Get("note")
|
||||||
|
|
||||||
|
@ -374,6 +416,10 @@ func (s *HTTPServer) AgentCheckWarn(resp http.ResponseWriter, req *http.Request)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) AgentCheckFail(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) AgentCheckFail(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "PUT" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
|
}
|
||||||
|
|
||||||
checkID := types.CheckID(strings.TrimPrefix(req.URL.Path, "/v1/agent/check/fail/"))
|
checkID := types.CheckID(strings.TrimPrefix(req.URL.Path, "/v1/agent/check/fail/"))
|
||||||
note := req.URL.Query().Get("note")
|
note := req.URL.Query().Get("note")
|
||||||
|
|
||||||
|
@ -408,8 +454,7 @@ type checkUpdate struct {
|
||||||
// APIs.
|
// APIs.
|
||||||
func (s *HTTPServer) AgentCheckUpdate(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) AgentCheckUpdate(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
if req.Method != "PUT" {
|
if req.Method != "PUT" {
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var update checkUpdate
|
var update checkUpdate
|
||||||
|
@ -452,6 +497,10 @@ func (s *HTTPServer) AgentCheckUpdate(resp http.ResponseWriter, req *http.Reques
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) AgentRegisterService(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) AgentRegisterService(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "PUT" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
|
}
|
||||||
|
|
||||||
var args structs.ServiceDefinition
|
var args structs.ServiceDefinition
|
||||||
// Fixup the type decode of TTL or Interval if a check if provided.
|
// Fixup the type decode of TTL or Interval if a check if provided.
|
||||||
decodeCB := func(raw interface{}) error {
|
decodeCB := func(raw interface{}) error {
|
||||||
|
@ -535,6 +584,10 @@ func (s *HTTPServer) AgentRegisterService(resp http.ResponseWriter, req *http.Re
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) AgentDeregisterService(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) AgentDeregisterService(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "PUT" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
|
}
|
||||||
|
|
||||||
serviceID := strings.TrimPrefix(req.URL.Path, "/v1/agent/service/deregister/")
|
serviceID := strings.TrimPrefix(req.URL.Path, "/v1/agent/service/deregister/")
|
||||||
|
|
||||||
// Get the provided token, if any, and vet against any ACL policies.
|
// Get the provided token, if any, and vet against any ACL policies.
|
||||||
|
@ -552,10 +605,8 @@ func (s *HTTPServer) AgentDeregisterService(resp http.ResponseWriter, req *http.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) AgentServiceMaintenance(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) AgentServiceMaintenance(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
// Only PUT supported
|
|
||||||
if req.Method != "PUT" {
|
if req.Method != "PUT" {
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure we have a service ID
|
// Ensure we have a service ID
|
||||||
|
@ -608,10 +659,8 @@ func (s *HTTPServer) AgentServiceMaintenance(resp http.ResponseWriter, req *http
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) AgentNodeMaintenance(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) AgentNodeMaintenance(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
// Only PUT supported
|
|
||||||
if req.Method != "PUT" {
|
if req.Method != "PUT" {
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure we have some action
|
// Ensure we have some action
|
||||||
|
@ -651,10 +700,8 @@ func (s *HTTPServer) AgentNodeMaintenance(resp http.ResponseWriter, req *http.Re
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) AgentMonitor(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) AgentMonitor(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
// Only GET supported.
|
|
||||||
if req.Method != "GET" {
|
if req.Method != "GET" {
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the ACL token, if any, and enforce agent policy.
|
// Fetch the ACL token, if any, and enforce agent policy.
|
||||||
|
@ -741,8 +788,7 @@ func (h *httpLogHandler) HandleLog(log string) {
|
||||||
|
|
||||||
func (s *HTTPServer) AgentToken(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) AgentToken(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
if req.Method != "PUT" {
|
if req.Method != "PUT" {
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the ACL token, if any, and enforce agent policy.
|
// Fetch the ACL token, if any, and enforce agent policy.
|
||||||
|
|
|
@ -421,7 +421,7 @@ func TestAgent_Join(t *testing.T) {
|
||||||
defer a2.Shutdown()
|
defer a2.Shutdown()
|
||||||
|
|
||||||
addr := fmt.Sprintf("127.0.0.1:%d", a2.Config.SerfPortLAN)
|
addr := fmt.Sprintf("127.0.0.1:%d", a2.Config.SerfPortLAN)
|
||||||
req, _ := http.NewRequest("GET", fmt.Sprintf("/v1/agent/join/%s", addr), nil)
|
req, _ := http.NewRequest("PUT", fmt.Sprintf("/v1/agent/join/%s", addr), nil)
|
||||||
obj, err := a1.srv.AgentJoin(nil, req)
|
obj, err := a1.srv.AgentJoin(nil, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Err: %v", err)
|
t.Fatalf("Err: %v", err)
|
||||||
|
@ -449,7 +449,7 @@ func TestAgent_Join_WAN(t *testing.T) {
|
||||||
defer a2.Shutdown()
|
defer a2.Shutdown()
|
||||||
|
|
||||||
addr := fmt.Sprintf("127.0.0.1:%d", a2.Config.SerfPortWAN)
|
addr := fmt.Sprintf("127.0.0.1:%d", a2.Config.SerfPortWAN)
|
||||||
req, _ := http.NewRequest("GET", fmt.Sprintf("/v1/agent/join/%s?wan=true", addr), nil)
|
req, _ := http.NewRequest("PUT", fmt.Sprintf("/v1/agent/join/%s?wan=true", addr), nil)
|
||||||
obj, err := a1.srv.AgentJoin(nil, req)
|
obj, err := a1.srv.AgentJoin(nil, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Err: %v", err)
|
t.Fatalf("Err: %v", err)
|
||||||
|
@ -479,14 +479,14 @@ func TestAgent_Join_ACLDeny(t *testing.T) {
|
||||||
addr := fmt.Sprintf("127.0.0.1:%d", a2.Config.SerfPortLAN)
|
addr := fmt.Sprintf("127.0.0.1:%d", a2.Config.SerfPortLAN)
|
||||||
|
|
||||||
t.Run("no token", func(t *testing.T) {
|
t.Run("no token", func(t *testing.T) {
|
||||||
req, _ := http.NewRequest("GET", fmt.Sprintf("/v1/agent/join/%s", addr), nil)
|
req, _ := http.NewRequest("PUT", fmt.Sprintf("/v1/agent/join/%s", addr), nil)
|
||||||
if _, err := a1.srv.AgentJoin(nil, req); !acl.IsErrPermissionDenied(err) {
|
if _, err := a1.srv.AgentJoin(nil, req); !acl.IsErrPermissionDenied(err) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("agent master token", func(t *testing.T) {
|
t.Run("agent master token", func(t *testing.T) {
|
||||||
req, _ := http.NewRequest("GET", fmt.Sprintf("/v1/agent/join/%s?token=towel", addr), nil)
|
req, _ := http.NewRequest("PUT", fmt.Sprintf("/v1/agent/join/%s?token=towel", addr), nil)
|
||||||
_, err := a1.srv.AgentJoin(nil, req)
|
_, err := a1.srv.AgentJoin(nil, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
|
@ -495,7 +495,7 @@ func TestAgent_Join_ACLDeny(t *testing.T) {
|
||||||
|
|
||||||
t.Run("read-only token", func(t *testing.T) {
|
t.Run("read-only token", func(t *testing.T) {
|
||||||
ro := makeReadOnlyAgentACL(t, a1.srv)
|
ro := makeReadOnlyAgentACL(t, a1.srv)
|
||||||
req, _ := http.NewRequest("GET", fmt.Sprintf("/v1/agent/join/%s?token=%s", addr, ro), nil)
|
req, _ := http.NewRequest("PUT", fmt.Sprintf("/v1/agent/join/%s?token=%s", addr, ro), nil)
|
||||||
if _, err := a1.srv.AgentJoin(nil, req); !acl.IsErrPermissionDenied(err) {
|
if _, err := a1.srv.AgentJoin(nil, req); !acl.IsErrPermissionDenied(err) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -616,7 +616,7 @@ func TestAgent_ForceLeave(t *testing.T) {
|
||||||
a2.Shutdown()
|
a2.Shutdown()
|
||||||
|
|
||||||
// Force leave now
|
// Force leave now
|
||||||
req, _ := http.NewRequest("GET", fmt.Sprintf("/v1/agent/force-leave/%s", a2.Config.NodeName), nil)
|
req, _ := http.NewRequest("PUT", fmt.Sprintf("/v1/agent/force-leave/%s", a2.Config.NodeName), nil)
|
||||||
obj, err := a1.srv.AgentForceLeave(nil, req)
|
obj, err := a1.srv.AgentForceLeave(nil, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Err: %v", err)
|
t.Fatalf("Err: %v", err)
|
||||||
|
@ -639,14 +639,14 @@ func TestAgent_ForceLeave_ACLDeny(t *testing.T) {
|
||||||
defer a.Shutdown()
|
defer a.Shutdown()
|
||||||
|
|
||||||
t.Run("no token", func(t *testing.T) {
|
t.Run("no token", func(t *testing.T) {
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/force-leave/nope", nil)
|
req, _ := http.NewRequest("PUT", "/v1/agent/force-leave/nope", nil)
|
||||||
if _, err := a.srv.AgentForceLeave(nil, req); !acl.IsErrPermissionDenied(err) {
|
if _, err := a.srv.AgentForceLeave(nil, req); !acl.IsErrPermissionDenied(err) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("agent master token", func(t *testing.T) {
|
t.Run("agent master token", func(t *testing.T) {
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/force-leave/nope?token=towel", nil)
|
req, _ := http.NewRequest("PUT", "/v1/agent/force-leave/nope?token=towel", nil)
|
||||||
if _, err := a.srv.AgentForceLeave(nil, req); err != nil {
|
if _, err := a.srv.AgentForceLeave(nil, req); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -654,7 +654,7 @@ func TestAgent_ForceLeave_ACLDeny(t *testing.T) {
|
||||||
|
|
||||||
t.Run("read-only token", func(t *testing.T) {
|
t.Run("read-only token", func(t *testing.T) {
|
||||||
ro := makeReadOnlyAgentACL(t, a.srv)
|
ro := makeReadOnlyAgentACL(t, a.srv)
|
||||||
req, _ := http.NewRequest("GET", fmt.Sprintf("/v1/agent/force-leave/nope?token=%s", ro), nil)
|
req, _ := http.NewRequest("PUT", fmt.Sprintf("/v1/agent/force-leave/nope?token=%s", ro), nil)
|
||||||
if _, err := a.srv.AgentForceLeave(nil, req); !acl.IsErrPermissionDenied(err) {
|
if _, err := a.srv.AgentForceLeave(nil, req); !acl.IsErrPermissionDenied(err) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -671,7 +671,7 @@ func TestAgent_RegisterCheck(t *testing.T) {
|
||||||
Name: "test",
|
Name: "test",
|
||||||
TTL: 15 * time.Second,
|
TTL: 15 * time.Second,
|
||||||
}
|
}
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/check/register?token=abc123", jsonReader(args))
|
req, _ := http.NewRequest("PUT", "/v1/agent/check/register?token=abc123", jsonReader(args))
|
||||||
obj, err := a.srv.AgentRegisterCheck(nil, req)
|
obj, err := a.srv.AgentRegisterCheck(nil, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
|
@ -713,7 +713,7 @@ func TestAgent_RegisterCheck_Passing(t *testing.T) {
|
||||||
TTL: 15 * time.Second,
|
TTL: 15 * time.Second,
|
||||||
Status: api.HealthPassing,
|
Status: api.HealthPassing,
|
||||||
}
|
}
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/check/register", jsonReader(args))
|
req, _ := http.NewRequest("PUT", "/v1/agent/check/register", jsonReader(args))
|
||||||
obj, err := a.srv.AgentRegisterCheck(nil, req)
|
obj, err := a.srv.AgentRegisterCheck(nil, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
|
@ -749,7 +749,7 @@ func TestAgent_RegisterCheck_BadStatus(t *testing.T) {
|
||||||
TTL: 15 * time.Second,
|
TTL: 15 * time.Second,
|
||||||
Status: "fluffy",
|
Status: "fluffy",
|
||||||
}
|
}
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/check/register", jsonReader(args))
|
req, _ := http.NewRequest("PUT", "/v1/agent/check/register", jsonReader(args))
|
||||||
resp := httptest.NewRecorder()
|
resp := httptest.NewRecorder()
|
||||||
if _, err := a.srv.AgentRegisterCheck(resp, req); err != nil {
|
if _, err := a.srv.AgentRegisterCheck(resp, req); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
|
@ -770,14 +770,14 @@ func TestAgent_RegisterCheck_ACLDeny(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("no token", func(t *testing.T) {
|
t.Run("no token", func(t *testing.T) {
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/check/register", jsonReader(args))
|
req, _ := http.NewRequest("PUT", "/v1/agent/check/register", jsonReader(args))
|
||||||
if _, err := a.srv.AgentRegisterCheck(nil, req); !acl.IsErrPermissionDenied(err) {
|
if _, err := a.srv.AgentRegisterCheck(nil, req); !acl.IsErrPermissionDenied(err) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("root token", func(t *testing.T) {
|
t.Run("root token", func(t *testing.T) {
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/check/register?token=root", jsonReader(args))
|
req, _ := http.NewRequest("PUT", "/v1/agent/check/register?token=root", jsonReader(args))
|
||||||
if _, err := a.srv.AgentRegisterCheck(nil, req); err != nil {
|
if _, err := a.srv.AgentRegisterCheck(nil, req); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -795,7 +795,7 @@ func TestAgent_DeregisterCheck(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register node
|
// Register node
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/check/deregister/test", nil)
|
req, _ := http.NewRequest("PUT", "/v1/agent/check/deregister/test", nil)
|
||||||
obj, err := a.srv.AgentDeregisterCheck(nil, req)
|
obj, err := a.srv.AgentDeregisterCheck(nil, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
|
@ -821,14 +821,14 @@ func TestAgent_DeregisterCheckACLDeny(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("no token", func(t *testing.T) {
|
t.Run("no token", func(t *testing.T) {
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/check/deregister/test", nil)
|
req, _ := http.NewRequest("PUT", "/v1/agent/check/deregister/test", nil)
|
||||||
if _, err := a.srv.AgentDeregisterCheck(nil, req); !acl.IsErrPermissionDenied(err) {
|
if _, err := a.srv.AgentDeregisterCheck(nil, req); !acl.IsErrPermissionDenied(err) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("root token", func(t *testing.T) {
|
t.Run("root token", func(t *testing.T) {
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/check/deregister/test?token=root", nil)
|
req, _ := http.NewRequest("PUT", "/v1/agent/check/deregister/test?token=root", nil)
|
||||||
if _, err := a.srv.AgentDeregisterCheck(nil, req); err != nil {
|
if _, err := a.srv.AgentDeregisterCheck(nil, req); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -846,7 +846,7 @@ func TestAgent_PassCheck(t *testing.T) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/check/pass/test", nil)
|
req, _ := http.NewRequest("PUT", "/v1/agent/check/pass/test", nil)
|
||||||
obj, err := a.srv.AgentCheckPass(nil, req)
|
obj, err := a.srv.AgentCheckPass(nil, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
|
@ -874,14 +874,14 @@ func TestAgent_PassCheck_ACLDeny(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("no token", func(t *testing.T) {
|
t.Run("no token", func(t *testing.T) {
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/check/pass/test", nil)
|
req, _ := http.NewRequest("PUT", "/v1/agent/check/pass/test", nil)
|
||||||
if _, err := a.srv.AgentCheckPass(nil, req); !acl.IsErrPermissionDenied(err) {
|
if _, err := a.srv.AgentCheckPass(nil, req); !acl.IsErrPermissionDenied(err) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("root token", func(t *testing.T) {
|
t.Run("root token", func(t *testing.T) {
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/check/pass/test?token=root", nil)
|
req, _ := http.NewRequest("PUT", "/v1/agent/check/pass/test?token=root", nil)
|
||||||
if _, err := a.srv.AgentCheckPass(nil, req); err != nil {
|
if _, err := a.srv.AgentCheckPass(nil, req); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -899,7 +899,7 @@ func TestAgent_WarnCheck(t *testing.T) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/check/warn/test", nil)
|
req, _ := http.NewRequest("PUT", "/v1/agent/check/warn/test", nil)
|
||||||
obj, err := a.srv.AgentCheckWarn(nil, req)
|
obj, err := a.srv.AgentCheckWarn(nil, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
|
@ -927,14 +927,14 @@ func TestAgent_WarnCheck_ACLDeny(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("no token", func(t *testing.T) {
|
t.Run("no token", func(t *testing.T) {
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/check/warn/test", nil)
|
req, _ := http.NewRequest("PUT", "/v1/agent/check/warn/test", nil)
|
||||||
if _, err := a.srv.AgentCheckWarn(nil, req); !acl.IsErrPermissionDenied(err) {
|
if _, err := a.srv.AgentCheckWarn(nil, req); !acl.IsErrPermissionDenied(err) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("root token", func(t *testing.T) {
|
t.Run("root token", func(t *testing.T) {
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/check/warn/test?token=root", nil)
|
req, _ := http.NewRequest("PUT", "/v1/agent/check/warn/test?token=root", nil)
|
||||||
if _, err := a.srv.AgentCheckWarn(nil, req); err != nil {
|
if _, err := a.srv.AgentCheckWarn(nil, req); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -952,7 +952,7 @@ func TestAgent_FailCheck(t *testing.T) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/check/fail/test", nil)
|
req, _ := http.NewRequest("PUT", "/v1/agent/check/fail/test", nil)
|
||||||
obj, err := a.srv.AgentCheckFail(nil, req)
|
obj, err := a.srv.AgentCheckFail(nil, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
|
@ -980,14 +980,14 @@ func TestAgent_FailCheck_ACLDeny(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("no token", func(t *testing.T) {
|
t.Run("no token", func(t *testing.T) {
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/check/fail/test", nil)
|
req, _ := http.NewRequest("PUT", "/v1/agent/check/fail/test", nil)
|
||||||
if _, err := a.srv.AgentCheckFail(nil, req); !acl.IsErrPermissionDenied(err) {
|
if _, err := a.srv.AgentCheckFail(nil, req); !acl.IsErrPermissionDenied(err) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("root token", func(t *testing.T) {
|
t.Run("root token", func(t *testing.T) {
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/check/fail/test?token=root", nil)
|
req, _ := http.NewRequest("PUT", "/v1/agent/check/fail/test?token=root", nil)
|
||||||
if _, err := a.srv.AgentCheckFail(nil, req); err != nil {
|
if _, err := a.srv.AgentCheckFail(nil, req); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -1075,22 +1075,6 @@ func TestAgent_UpdateCheck(t *testing.T) {
|
||||||
t.Fatalf("expected 400, got %d", resp.Code)
|
t.Fatalf("expected 400, got %d", resp.Code)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("bogus verb", func(t *testing.T) {
|
|
||||||
args := checkUpdate{Status: api.HealthPassing}
|
|
||||||
req, _ := http.NewRequest("POST", "/v1/agent/check/update/test", jsonReader(args))
|
|
||||||
resp := httptest.NewRecorder()
|
|
||||||
obj, err := a.srv.AgentCheckUpdate(resp, req)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("err: %v", err)
|
|
||||||
}
|
|
||||||
if obj != nil {
|
|
||||||
t.Fatalf("bad: %v", obj)
|
|
||||||
}
|
|
||||||
if resp.Code != 405 {
|
|
||||||
t.Fatalf("expected 405, got %d", resp.Code)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAgent_UpdateCheck_ACLDeny(t *testing.T) {
|
func TestAgent_UpdateCheck_ACLDeny(t *testing.T) {
|
||||||
|
@ -1142,7 +1126,7 @@ func TestAgent_RegisterService(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/service/register?token=abc123", jsonReader(args))
|
req, _ := http.NewRequest("PUT", "/v1/agent/service/register?token=abc123", jsonReader(args))
|
||||||
|
|
||||||
obj, err := a.srv.AgentRegisterService(nil, req)
|
obj, err := a.srv.AgentRegisterService(nil, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1196,14 +1180,14 @@ func TestAgent_RegisterService_ACLDeny(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("no token", func(t *testing.T) {
|
t.Run("no token", func(t *testing.T) {
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/service/register", jsonReader(args))
|
req, _ := http.NewRequest("PUT", "/v1/agent/service/register", jsonReader(args))
|
||||||
if _, err := a.srv.AgentRegisterService(nil, req); !acl.IsErrPermissionDenied(err) {
|
if _, err := a.srv.AgentRegisterService(nil, req); !acl.IsErrPermissionDenied(err) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("root token", func(t *testing.T) {
|
t.Run("root token", func(t *testing.T) {
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/service/register?token=root", jsonReader(args))
|
req, _ := http.NewRequest("PUT", "/v1/agent/service/register?token=root", jsonReader(args))
|
||||||
if _, err := a.srv.AgentRegisterService(nil, req); err != nil {
|
if _, err := a.srv.AgentRegisterService(nil, req); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -1222,7 +1206,7 @@ func TestAgent_RegisterService_InvalidAddress(t *testing.T) {
|
||||||
Address: addr,
|
Address: addr,
|
||||||
Port: 8000,
|
Port: 8000,
|
||||||
}
|
}
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/service/register?token=abc123", jsonReader(args))
|
req, _ := http.NewRequest("PUT", "/v1/agent/service/register?token=abc123", jsonReader(args))
|
||||||
resp := httptest.NewRecorder()
|
resp := httptest.NewRecorder()
|
||||||
_, err := a.srv.AgentRegisterService(resp, req)
|
_, err := a.srv.AgentRegisterService(resp, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1251,7 +1235,7 @@ func TestAgent_DeregisterService(t *testing.T) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/service/deregister/test", nil)
|
req, _ := http.NewRequest("PUT", "/v1/agent/service/deregister/test", nil)
|
||||||
obj, err := a.srv.AgentDeregisterService(nil, req)
|
obj, err := a.srv.AgentDeregisterService(nil, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
|
@ -1284,14 +1268,14 @@ func TestAgent_DeregisterService_ACLDeny(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("no token", func(t *testing.T) {
|
t.Run("no token", func(t *testing.T) {
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/service/deregister/test", nil)
|
req, _ := http.NewRequest("PUT", "/v1/agent/service/deregister/test", nil)
|
||||||
if _, err := a.srv.AgentDeregisterService(nil, req); !acl.IsErrPermissionDenied(err) {
|
if _, err := a.srv.AgentDeregisterService(nil, req); !acl.IsErrPermissionDenied(err) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("root token", func(t *testing.T) {
|
t.Run("root token", func(t *testing.T) {
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/service/deregister/test?token=root", nil)
|
req, _ := http.NewRequest("PUT", "/v1/agent/service/deregister/test?token=root", nil)
|
||||||
if _, err := a.srv.AgentDeregisterService(nil, req); err != nil {
|
if _, err := a.srv.AgentDeregisterService(nil, req); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -1303,17 +1287,6 @@ func TestAgent_ServiceMaintenance_BadRequest(t *testing.T) {
|
||||||
a := NewTestAgent(t.Name(), "")
|
a := NewTestAgent(t.Name(), "")
|
||||||
defer a.Shutdown()
|
defer a.Shutdown()
|
||||||
|
|
||||||
t.Run("not PUT", func(t *testing.T) {
|
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/service/maintenance/test?enable=true", nil)
|
|
||||||
resp := httptest.NewRecorder()
|
|
||||||
if _, err := a.srv.AgentServiceMaintenance(resp, req); err != nil {
|
|
||||||
t.Fatalf("err: %s", err)
|
|
||||||
}
|
|
||||||
if resp.Code != 405 {
|
|
||||||
t.Fatalf("expected 405, got %d", resp.Code)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("not enabled", func(t *testing.T) {
|
t.Run("not enabled", func(t *testing.T) {
|
||||||
req, _ := http.NewRequest("PUT", "/v1/agent/service/maintenance/test", nil)
|
req, _ := http.NewRequest("PUT", "/v1/agent/service/maintenance/test", nil)
|
||||||
resp := httptest.NewRecorder()
|
resp := httptest.NewRecorder()
|
||||||
|
@ -1460,19 +1433,9 @@ func TestAgent_NodeMaintenance_BadRequest(t *testing.T) {
|
||||||
a := NewTestAgent(t.Name(), "")
|
a := NewTestAgent(t.Name(), "")
|
||||||
defer a.Shutdown()
|
defer a.Shutdown()
|
||||||
|
|
||||||
// Fails on non-PUT
|
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/self/maintenance?enable=true", nil)
|
|
||||||
resp := httptest.NewRecorder()
|
|
||||||
if _, err := a.srv.AgentNodeMaintenance(resp, req); err != nil {
|
|
||||||
t.Fatalf("err: %s", err)
|
|
||||||
}
|
|
||||||
if resp.Code != 405 {
|
|
||||||
t.Fatalf("expected 405, got %d", resp.Code)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fails when no enable flag provided
|
// Fails when no enable flag provided
|
||||||
req, _ = http.NewRequest("PUT", "/v1/agent/self/maintenance", nil)
|
req, _ := http.NewRequest("PUT", "/v1/agent/self/maintenance", nil)
|
||||||
resp = httptest.NewRecorder()
|
resp := httptest.NewRecorder()
|
||||||
if _, err := a.srv.AgentNodeMaintenance(resp, req); err != nil {
|
if _, err := a.srv.AgentNodeMaintenance(resp, req); err != nil {
|
||||||
t.Fatalf("err: %s", err)
|
t.Fatalf("err: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -1571,7 +1534,7 @@ func TestAgent_RegisterCheck_Service(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// First register the service
|
// First register the service
|
||||||
req, _ := http.NewRequest("GET", "/v1/agent/service/register", jsonReader(args))
|
req, _ := http.NewRequest("PUT", "/v1/agent/service/register", jsonReader(args))
|
||||||
if _, err := a.srv.AgentRegisterService(nil, req); err != nil {
|
if _, err := a.srv.AgentRegisterService(nil, req); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -1582,7 +1545,7 @@ func TestAgent_RegisterCheck_Service(t *testing.T) {
|
||||||
ServiceID: "memcache",
|
ServiceID: "memcache",
|
||||||
TTL: 15 * time.Second,
|
TTL: 15 * time.Second,
|
||||||
}
|
}
|
||||||
req, _ = http.NewRequest("GET", "/v1/agent/check/register", jsonReader(checkArgs))
|
req, _ = http.NewRequest("PUT", "/v1/agent/check/register", jsonReader(checkArgs))
|
||||||
if _, err := a.srv.AgentRegisterCheck(nil, req); err != nil {
|
if _, err := a.srv.AgentRegisterCheck(nil, req); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -1721,12 +1684,6 @@ func TestAgent_Token(t *testing.T) {
|
||||||
code int
|
code int
|
||||||
got, want tokens
|
got, want tokens
|
||||||
}{
|
}{
|
||||||
{
|
|
||||||
name: "bad method",
|
|
||||||
method: "GET",
|
|
||||||
url: "acl_token",
|
|
||||||
code: http.StatusMethodNotAllowed,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "bad token name",
|
name: "bad token name",
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
|
|
|
@ -9,6 +9,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *HTTPServer) CatalogRegister(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) CatalogRegister(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "PUT" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
|
}
|
||||||
|
|
||||||
var args structs.RegisterRequest
|
var args structs.RegisterRequest
|
||||||
if err := decodeBody(req, &args, nil); err != nil {
|
if err := decodeBody(req, &args, nil); err != nil {
|
||||||
resp.WriteHeader(http.StatusBadRequest)
|
resp.WriteHeader(http.StatusBadRequest)
|
||||||
|
@ -31,6 +35,10 @@ func (s *HTTPServer) CatalogRegister(resp http.ResponseWriter, req *http.Request
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) CatalogDeregister(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) CatalogDeregister(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "PUT" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
|
}
|
||||||
|
|
||||||
var args structs.DeregisterRequest
|
var args structs.DeregisterRequest
|
||||||
if err := decodeBody(req, &args, nil); err != nil {
|
if err := decodeBody(req, &args, nil); err != nil {
|
||||||
resp.WriteHeader(http.StatusBadRequest)
|
resp.WriteHeader(http.StatusBadRequest)
|
||||||
|
@ -53,6 +61,10 @@ func (s *HTTPServer) CatalogDeregister(resp http.ResponseWriter, req *http.Reque
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) CatalogDatacenters(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) CatalogDatacenters(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
var out []string
|
var out []string
|
||||||
if err := s.agent.RPC("Catalog.ListDatacenters", struct{}{}, &out); err != nil {
|
if err := s.agent.RPC("Catalog.ListDatacenters", struct{}{}, &out); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -61,6 +73,10 @@ func (s *HTTPServer) CatalogDatacenters(resp http.ResponseWriter, req *http.Requ
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) CatalogNodes(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) CatalogNodes(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
// Setup the request
|
// Setup the request
|
||||||
args := structs.DCSpecificRequest{}
|
args := structs.DCSpecificRequest{}
|
||||||
s.parseSource(req, &args.Source)
|
s.parseSource(req, &args.Source)
|
||||||
|
@ -84,6 +100,10 @@ func (s *HTTPServer) CatalogNodes(resp http.ResponseWriter, req *http.Request) (
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) CatalogServices(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) CatalogServices(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
// Set default DC
|
// Set default DC
|
||||||
args := structs.DCSpecificRequest{}
|
args := structs.DCSpecificRequest{}
|
||||||
args.NodeMetaFilters = s.parseMetaFilter(req)
|
args.NodeMetaFilters = s.parseMetaFilter(req)
|
||||||
|
@ -105,6 +125,10 @@ func (s *HTTPServer) CatalogServices(resp http.ResponseWriter, req *http.Request
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) CatalogServiceNodes(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) CatalogServiceNodes(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
// Set default DC
|
// Set default DC
|
||||||
args := structs.ServiceSpecificRequest{}
|
args := structs.ServiceSpecificRequest{}
|
||||||
s.parseSource(req, &args.Source)
|
s.parseSource(req, &args.Source)
|
||||||
|
@ -149,6 +173,10 @@ func (s *HTTPServer) CatalogServiceNodes(resp http.ResponseWriter, req *http.Req
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) CatalogNodeServices(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) CatalogNodeServices(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
// Set default Datacenter
|
// Set default Datacenter
|
||||||
args := structs.NodeSpecificRequest{}
|
args := structs.NodeSpecificRequest{}
|
||||||
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
||||||
|
|
|
@ -22,7 +22,7 @@ func TestCatalogRegister(t *testing.T) {
|
||||||
Node: "foo",
|
Node: "foo",
|
||||||
Address: "127.0.0.1",
|
Address: "127.0.0.1",
|
||||||
}
|
}
|
||||||
req, _ := http.NewRequest("GET", "/v1/catalog/register", jsonReader(args))
|
req, _ := http.NewRequest("PUT", "/v1/catalog/register", jsonReader(args))
|
||||||
obj, err := a.srv.CatalogRegister(nil, req)
|
obj, err := a.srv.CatalogRegister(nil, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
|
@ -67,7 +67,7 @@ func TestCatalogRegister_Service_InvalidAddress(t *testing.T) {
|
||||||
Port: 8080,
|
Port: 8080,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
req, _ := http.NewRequest("GET", "/v1/catalog/register", jsonReader(args))
|
req, _ := http.NewRequest("PUT", "/v1/catalog/register", jsonReader(args))
|
||||||
_, err := a.srv.CatalogRegister(nil, req)
|
_, err := a.srv.CatalogRegister(nil, req)
|
||||||
if err == nil || err.Error() != "Invalid service address" {
|
if err == nil || err.Error() != "Invalid service address" {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
|
@ -83,7 +83,7 @@ func TestCatalogDeregister(t *testing.T) {
|
||||||
|
|
||||||
// Register node
|
// Register node
|
||||||
args := &structs.DeregisterRequest{Node: "foo"}
|
args := &structs.DeregisterRequest{Node: "foo"}
|
||||||
req, _ := http.NewRequest("GET", "/v1/catalog/deregister", jsonReader(args))
|
req, _ := http.NewRequest("PUT", "/v1/catalog/deregister", jsonReader(args))
|
||||||
obj, err := a.srv.CatalogDeregister(nil, req)
|
obj, err := a.srv.CatalogDeregister(nil, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
|
@ -101,7 +101,8 @@ func TestCatalogDatacenters(t *testing.T) {
|
||||||
defer a.Shutdown()
|
defer a.Shutdown()
|
||||||
|
|
||||||
retry.Run(t, func(r *retry.R) {
|
retry.Run(t, func(r *retry.R) {
|
||||||
obj, err := a.srv.CatalogDatacenters(nil, nil)
|
req, _ := http.NewRequest("GET", "/v1/catalog/datacenters", nil)
|
||||||
|
obj, err := a.srv.CatalogDatacenters(nil, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Fatal(err)
|
r.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,10 @@ func (s *sorter) Less(i, j int) bool {
|
||||||
// CoordinateDatacenters returns the WAN nodes in each datacenter, along with
|
// CoordinateDatacenters returns the WAN nodes in each datacenter, along with
|
||||||
// raw network coordinates.
|
// raw network coordinates.
|
||||||
func (s *HTTPServer) CoordinateDatacenters(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) CoordinateDatacenters(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
var out []structs.DatacenterMap
|
var out []structs.DatacenterMap
|
||||||
if err := s.agent.RPC("Coordinate.ListDatacenters", struct{}{}, &out); err != nil {
|
if err := s.agent.RPC("Coordinate.ListDatacenters", struct{}{}, &out); err != nil {
|
||||||
for i := range out {
|
for i := range out {
|
||||||
|
@ -65,6 +69,10 @@ func (s *HTTPServer) CoordinateDatacenters(resp http.ResponseWriter, req *http.R
|
||||||
// CoordinateNodes returns the LAN nodes in the given datacenter, along with
|
// CoordinateNodes returns the LAN nodes in the given datacenter, along with
|
||||||
// raw network coordinates.
|
// raw network coordinates.
|
||||||
func (s *HTTPServer) CoordinateNodes(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) CoordinateNodes(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
args := structs.DCSpecificRequest{}
|
args := structs.DCSpecificRequest{}
|
||||||
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
@ -20,10 +20,8 @@ const (
|
||||||
|
|
||||||
// EventFire is used to fire a new event
|
// EventFire is used to fire a new event
|
||||||
func (s *HTTPServer) EventFire(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) EventFire(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
// Mandate a PUT request
|
|
||||||
if req.Method != "PUT" {
|
if req.Method != "PUT" {
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the datacenter
|
// Get the datacenter
|
||||||
|
@ -79,6 +77,10 @@ func (s *HTTPServer) EventFire(resp http.ResponseWriter, req *http.Request) (int
|
||||||
|
|
||||||
// EventList is used to retrieve the recent list of events
|
// EventList is used to retrieve the recent list of events
|
||||||
func (s *HTTPServer) EventList(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) EventList(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the query options, since we simulate a blocking query
|
// Parse the query options, since we simulate a blocking query
|
||||||
var b structs.QueryOptions
|
var b structs.QueryOptions
|
||||||
if parseWait(resp, req, &b) {
|
if parseWait(resp, req, &b) {
|
||||||
|
|
|
@ -11,6 +11,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *HTTPServer) HealthChecksInState(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) HealthChecksInState(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
// Set default DC
|
// Set default DC
|
||||||
args := structs.ChecksInStateRequest{}
|
args := structs.ChecksInStateRequest{}
|
||||||
s.parseSource(req, &args.Source)
|
s.parseSource(req, &args.Source)
|
||||||
|
@ -47,6 +51,10 @@ func (s *HTTPServer) HealthChecksInState(resp http.ResponseWriter, req *http.Req
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) HealthNodeChecks(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) HealthNodeChecks(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
// Set default DC
|
// Set default DC
|
||||||
args := structs.NodeSpecificRequest{}
|
args := structs.NodeSpecificRequest{}
|
||||||
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
||||||
|
@ -81,6 +89,10 @@ func (s *HTTPServer) HealthNodeChecks(resp http.ResponseWriter, req *http.Reques
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) HealthServiceChecks(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) HealthServiceChecks(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
// Set default DC
|
// Set default DC
|
||||||
args := structs.ServiceSpecificRequest{}
|
args := structs.ServiceSpecificRequest{}
|
||||||
s.parseSource(req, &args.Source)
|
s.parseSource(req, &args.Source)
|
||||||
|
@ -117,6 +129,10 @@ func (s *HTTPServer) HealthServiceChecks(resp http.ResponseWriter, req *http.Req
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) HealthServiceNodes(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) HealthServiceNodes(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
// Set default DC
|
// Set default DC
|
||||||
args := structs.ServiceSpecificRequest{}
|
args := structs.ServiceSpecificRequest{}
|
||||||
s.parseSource(req, &args.Source)
|
s.parseSource(req, &args.Source)
|
||||||
|
|
|
@ -18,6 +18,16 @@ import (
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// MethodNotAllowedError should be returned by a handler when the HTTP method is not allowed.
|
||||||
|
type MethodNotAllowedError struct {
|
||||||
|
Method string
|
||||||
|
Allow []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e MethodNotAllowedError) Error() string {
|
||||||
|
return fmt.Sprintf("method %s not allowed", e.Method)
|
||||||
|
}
|
||||||
|
|
||||||
// HTTPServer provides an HTTP api for an agent.
|
// HTTPServer provides an HTTP api for an agent.
|
||||||
type HTTPServer struct {
|
type HTTPServer struct {
|
||||||
*http.Server
|
*http.Server
|
||||||
|
@ -234,6 +244,11 @@ func (s *HTTPServer) wrap(handler func(resp http.ResponseWriter, req *http.Reque
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isMethodNotAllowed := func(err error) bool {
|
||||||
|
_, ok := err.(MethodNotAllowedError)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
handleErr := func(err error) {
|
handleErr := func(err error) {
|
||||||
s.agent.logger.Printf("[ERR] http: Request %s %v, error: %v from=%s", req.Method, logURL, err, req.RemoteAddr)
|
s.agent.logger.Printf("[ERR] http: Request %s %v, error: %v from=%s", req.Method, logURL, err, req.RemoteAddr)
|
||||||
switch {
|
switch {
|
||||||
|
@ -242,6 +257,13 @@ func (s *HTTPServer) wrap(handler func(resp http.ResponseWriter, req *http.Reque
|
||||||
fmt.Fprint(resp, err.Error())
|
fmt.Fprint(resp, err.Error())
|
||||||
case structs.IsErrRPCRateExceeded(err):
|
case structs.IsErrRPCRateExceeded(err):
|
||||||
resp.WriteHeader(http.StatusTooManyRequests)
|
resp.WriteHeader(http.StatusTooManyRequests)
|
||||||
|
case isMethodNotAllowed(err):
|
||||||
|
// RFC2616 states that for 405 Method Not Allowed the response
|
||||||
|
// MUST include an Allow header containing the list of valid
|
||||||
|
// methods for the requested resource.
|
||||||
|
// https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
||||||
|
resp.Header()["Allow"] = err.(MethodNotAllowedError).Allow
|
||||||
|
resp.WriteHeader(http.StatusMethodNotAllowed) // 405
|
||||||
fmt.Fprint(resp, err.Error())
|
fmt.Fprint(resp, err.Error())
|
||||||
default:
|
default:
|
||||||
resp.WriteHeader(http.StatusInternalServerError)
|
resp.WriteHeader(http.StatusInternalServerError)
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/agent/structs"
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
|
"github.com/hashicorp/consul/logger"
|
||||||
"github.com/hashicorp/consul/testutil"
|
"github.com/hashicorp/consul/testutil"
|
||||||
"github.com/hashicorp/go-cleanhttp"
|
"github.com/hashicorp/go-cleanhttp"
|
||||||
)
|
)
|
||||||
|
@ -307,6 +308,114 @@ func TestHTTPAPIResponseHeaders(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHTTPAPI_MethodNotAllowed(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
methods, uri string
|
||||||
|
}{
|
||||||
|
{"PUT", "/v1/acl/bootstrap"},
|
||||||
|
{"PUT", "/v1/acl/create"},
|
||||||
|
{"PUT", "/v1/acl/update"},
|
||||||
|
{"PUT", "/v1/acl/destroy/"},
|
||||||
|
{"GET", "/v1/acl/info/"},
|
||||||
|
{"PUT", "/v1/acl/clone/"},
|
||||||
|
{"GET", "/v1/acl/list"},
|
||||||
|
{"GET", "/v1/acl/replication"},
|
||||||
|
{"PUT", "/v1/agent/token/"},
|
||||||
|
{"GET", "/v1/agent/self"},
|
||||||
|
{"GET", "/v1/agent/members"},
|
||||||
|
{"PUT", "/v1/agent/check/deregister/"},
|
||||||
|
{"PUT", "/v1/agent/check/fail/"},
|
||||||
|
{"PUT", "/v1/agent/check/pass/"},
|
||||||
|
{"PUT", "/v1/agent/check/register"},
|
||||||
|
{"PUT", "/v1/agent/check/update/"},
|
||||||
|
{"PUT", "/v1/agent/check/warn/"},
|
||||||
|
{"GET", "/v1/agent/checks"},
|
||||||
|
{"PUT", "/v1/agent/force-leave/"},
|
||||||
|
{"PUT", "/v1/agent/join/"},
|
||||||
|
{"PUT", "/v1/agent/leave"},
|
||||||
|
{"PUT", "/v1/agent/maintenance"},
|
||||||
|
{"GET", "/v1/agent/metrics"},
|
||||||
|
// {"GET", "/v1/agent/monitor"}, // requires LogWriter. Hangs if LogWriter is provided
|
||||||
|
{"PUT", "/v1/agent/reload"},
|
||||||
|
{"PUT", "/v1/agent/service/deregister/"},
|
||||||
|
{"PUT", "/v1/agent/service/maintenance/"},
|
||||||
|
{"PUT", "/v1/agent/service/register"},
|
||||||
|
{"GET", "/v1/agent/services"},
|
||||||
|
{"GET", "/v1/catalog/datacenters"},
|
||||||
|
{"PUT", "/v1/catalog/deregister"},
|
||||||
|
{"GET", "/v1/catalog/node/"},
|
||||||
|
{"GET", "/v1/catalog/nodes"},
|
||||||
|
{"PUT", "/v1/catalog/register"},
|
||||||
|
{"GET", "/v1/catalog/service/"},
|
||||||
|
{"GET", "/v1/catalog/services"},
|
||||||
|
{"GET", "/v1/coordinate/datacenters"},
|
||||||
|
{"GET", "/v1/coordinate/nodes"},
|
||||||
|
{"PUT", "/v1/event/fire/"},
|
||||||
|
{"GET", "/v1/event/list"},
|
||||||
|
{"GET", "/v1/health/checks/"},
|
||||||
|
{"GET", "/v1/health/node/"},
|
||||||
|
{"GET", "/v1/health/service/"},
|
||||||
|
{"GET", "/v1/health/state/"},
|
||||||
|
{"GET", "/v1/internal/ui/node/"},
|
||||||
|
{"GET", "/v1/internal/ui/nodes"},
|
||||||
|
{"GET", "/v1/internal/ui/services"},
|
||||||
|
{"GET PUT DELETE", "/v1/kv/"},
|
||||||
|
{"GET PUT", "/v1/operator/autopilot/configuration"},
|
||||||
|
{"GET", "/v1/operator/autopilot/health"},
|
||||||
|
{"GET POST PUT DELETE", "/v1/operator/keyring"},
|
||||||
|
{"GET", "/v1/operator/raft/configuration"},
|
||||||
|
{"DELETE", "/v1/operator/raft/peer"},
|
||||||
|
{"GET POST", "/v1/query"},
|
||||||
|
{"GET PUT DELETE", "/v1/query/"},
|
||||||
|
{"GET", "/v1/query/xxx/execute"},
|
||||||
|
{"GET", "/v1/query/xxx/explain"},
|
||||||
|
{"PUT", "/v1/session/create"},
|
||||||
|
{"PUT", "/v1/session/destroy/"},
|
||||||
|
{"GET", "/v1/session/info/"},
|
||||||
|
{"GET", "/v1/session/list"},
|
||||||
|
{"GET", "/v1/session/node/"},
|
||||||
|
{"PUT", "/v1/session/renew/"},
|
||||||
|
{"GET PUT", "/v1/snapshot"},
|
||||||
|
{"GET", "/v1/status/leader"},
|
||||||
|
// {"GET", "/v1/status/peers"},// hangs
|
||||||
|
{"PUT", "/v1/txn"},
|
||||||
|
|
||||||
|
// enterprise only
|
||||||
|
// {"GET POST", "/v1/operator/area"},
|
||||||
|
// {"GET PUT DELETE", "/v1/operator/area/"},
|
||||||
|
// {"GET", "/v1/operator/area/xxx/members"},
|
||||||
|
}
|
||||||
|
|
||||||
|
a := NewTestAgent(t.Name(), `acl_datacenter = "dc1"`)
|
||||||
|
a.Agent.LogWriter = logger.NewLogWriter(512)
|
||||||
|
defer a.Shutdown()
|
||||||
|
|
||||||
|
all := []string{"GET", "PUT", "POST", "DELETE", "HEAD"}
|
||||||
|
client := http.Client{}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
for _, m := range all {
|
||||||
|
|
||||||
|
t.Run(m+" "+tt.uri, func(t *testing.T) {
|
||||||
|
uri := fmt.Sprintf("http://%s%s", a.HTTPAddr(), tt.uri)
|
||||||
|
req, _ := http.NewRequest(m, uri, nil)
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("client.Do failed: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
allowed := strings.Contains(tt.methods, m)
|
||||||
|
if allowed && resp.StatusCode == http.StatusMethodNotAllowed {
|
||||||
|
t.Fatalf("method allowed: got status code %d want any other code", resp.StatusCode)
|
||||||
|
}
|
||||||
|
if !allowed && resp.StatusCode != http.StatusMethodNotAllowed {
|
||||||
|
t.Fatalf("method not allowed: got status code %d want %d", resp.StatusCode, http.StatusMethodNotAllowed)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestContentTypeIsJSON(t *testing.T) {
|
func TestContentTypeIsJSON(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
a := NewTestAgent(t.Name(), "")
|
a := NewTestAgent(t.Name(), "")
|
||||||
|
|
|
@ -17,8 +17,7 @@ import (
|
||||||
// This supports the stale query mode in case the cluster doesn't have a leader.
|
// This supports the stale query mode in case the cluster doesn't have a leader.
|
||||||
func (s *HTTPServer) OperatorRaftConfiguration(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) OperatorRaftConfiguration(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
if req.Method != "GET" {
|
if req.Method != "GET" {
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var args structs.DCSpecificRequest
|
var args structs.DCSpecificRequest
|
||||||
|
@ -38,8 +37,7 @@ func (s *HTTPServer) OperatorRaftConfiguration(resp http.ResponseWriter, req *ht
|
||||||
// removing peers by address.
|
// removing peers by address.
|
||||||
func (s *HTTPServer) OperatorRaftPeer(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) OperatorRaftPeer(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
if req.Method != "DELETE" {
|
if req.Method != "DELETE" {
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"DELETE"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var args structs.RaftRemovePeerRequest
|
var args structs.RaftRemovePeerRequest
|
||||||
|
@ -125,8 +123,7 @@ func (s *HTTPServer) OperatorKeyringEndpoint(resp http.ResponseWriter, req *http
|
||||||
case "DELETE":
|
case "DELETE":
|
||||||
return s.KeyringRemove(resp, req, &args)
|
return s.KeyringRemove(resp, req, &args)
|
||||||
default:
|
default:
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"GET", "POST", "PUT", "DELETE"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,8 +261,7 @@ func (s *HTTPServer) OperatorAutopilotConfiguration(resp http.ResponseWriter, re
|
||||||
return reply, nil
|
return reply, nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"GET", "PUT"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,8 +291,7 @@ func FixupConfigDurations(raw interface{}) error {
|
||||||
// OperatorServerHealth is used to get the health of the servers in the local DC
|
// OperatorServerHealth is used to get the health of the servers in the local DC
|
||||||
func (s *HTTPServer) OperatorServerHealth(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) OperatorServerHealth(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
if req.Method != "GET" {
|
if req.Method != "GET" {
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var args structs.DCSpecificRequest
|
var args structs.DCSpecificRequest
|
||||||
|
|
|
@ -10,11 +10,6 @@ import (
|
||||||
"github.com/hashicorp/consul/agent/structs"
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
preparedQueryExecuteSuffix = "/execute"
|
|
||||||
preparedQueryExplainSuffix = "/explain"
|
|
||||||
)
|
|
||||||
|
|
||||||
// preparedQueryCreateResponse is used to wrap the query ID.
|
// preparedQueryCreateResponse is used to wrap the query ID.
|
||||||
type preparedQueryCreateResponse struct {
|
type preparedQueryCreateResponse struct {
|
||||||
ID string
|
ID string
|
||||||
|
@ -71,8 +66,7 @@ func (s *HTTPServer) PreparedQueryGeneral(resp http.ResponseWriter, req *http.Re
|
||||||
return s.preparedQueryList(resp, req)
|
return s.preparedQueryList(resp, req)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"GET", "POST"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,6 +198,10 @@ func (s *HTTPServer) preparedQueryUpdate(id string, resp http.ResponseWriter, re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if args.Query == nil {
|
||||||
|
args.Query = &structs.PreparedQuery{}
|
||||||
|
}
|
||||||
|
|
||||||
// Take the ID from the URL, not the embedded one.
|
// Take the ID from the URL, not the embedded one.
|
||||||
args.Query.ID = id
|
args.Query.ID = id
|
||||||
|
|
||||||
|
@ -235,26 +233,28 @@ func (s *HTTPServer) preparedQueryDelete(id string, resp http.ResponseWriter, re
|
||||||
// PreparedQuerySpecific handles all the prepared query requests specific to a
|
// PreparedQuerySpecific handles all the prepared query requests specific to a
|
||||||
// particular query.
|
// particular query.
|
||||||
func (s *HTTPServer) PreparedQuerySpecific(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) PreparedQuerySpecific(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
id := strings.TrimPrefix(req.URL.Path, "/v1/query/")
|
path := req.URL.Path
|
||||||
|
id := strings.TrimPrefix(path, "/v1/query/")
|
||||||
|
|
||||||
execute, explain := false, false
|
switch {
|
||||||
if strings.HasSuffix(id, preparedQueryExecuteSuffix) {
|
case strings.HasSuffix(path, "/execute"):
|
||||||
execute = true
|
if req.Method != "GET" {
|
||||||
id = strings.TrimSuffix(id, preparedQueryExecuteSuffix)
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
} else if strings.HasSuffix(id, preparedQueryExplainSuffix) {
|
|
||||||
explain = true
|
|
||||||
id = strings.TrimSuffix(id, preparedQueryExplainSuffix)
|
|
||||||
}
|
}
|
||||||
|
id = strings.TrimSuffix(id, "/execute")
|
||||||
|
return s.preparedQueryExecute(id, resp, req)
|
||||||
|
|
||||||
|
case strings.HasSuffix(path, "/explain"):
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
id = strings.TrimSuffix(id, "/explain")
|
||||||
|
return s.preparedQueryExplain(id, resp, req)
|
||||||
|
|
||||||
|
default:
|
||||||
switch req.Method {
|
switch req.Method {
|
||||||
case "GET":
|
case "GET":
|
||||||
if execute {
|
|
||||||
return s.preparedQueryExecute(id, resp, req)
|
|
||||||
} else if explain {
|
|
||||||
return s.preparedQueryExplain(id, resp, req)
|
|
||||||
} else {
|
|
||||||
return s.preparedQueryGet(id, resp, req)
|
return s.preparedQueryGet(id, resp, req)
|
||||||
}
|
|
||||||
|
|
||||||
case "PUT":
|
case "PUT":
|
||||||
return s.preparedQueryUpdate(id, resp, req)
|
return s.preparedQueryUpdate(id, resp, req)
|
||||||
|
@ -263,7 +263,7 @@ func (s *HTTPServer) PreparedQuerySpecific(resp http.ResponseWriter, req *http.R
|
||||||
return s.preparedQueryDelete(id, resp, req)
|
return s.preparedQueryDelete(id, resp, req)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"GET", "PUT", "DELETE"}}
|
||||||
return nil, nil
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -737,39 +737,6 @@ func TestPreparedQuery_Delete(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPreparedQuery_BadMethods(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
t.Run("", func(t *testing.T) {
|
|
||||||
a := NewTestAgent(t.Name(), "")
|
|
||||||
defer a.Shutdown()
|
|
||||||
|
|
||||||
body := bytes.NewBuffer(nil)
|
|
||||||
req, _ := http.NewRequest("DELETE", "/v1/query", body)
|
|
||||||
resp := httptest.NewRecorder()
|
|
||||||
if _, err := a.srv.PreparedQueryGeneral(resp, req); err != nil {
|
|
||||||
t.Fatalf("err: %v", err)
|
|
||||||
}
|
|
||||||
if resp.Code != 405 {
|
|
||||||
t.Fatalf("bad code: %d", resp.Code)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("", func(t *testing.T) {
|
|
||||||
a := NewTestAgent(t.Name(), "")
|
|
||||||
defer a.Shutdown()
|
|
||||||
|
|
||||||
body := bytes.NewBuffer(nil)
|
|
||||||
req, _ := http.NewRequest("POST", "/v1/query/my-id", body)
|
|
||||||
resp := httptest.NewRecorder()
|
|
||||||
if _, err := a.srv.PreparedQuerySpecific(resp, req); err != nil {
|
|
||||||
t.Fatalf("err: %v", err)
|
|
||||||
}
|
|
||||||
if resp.Code != 405 {
|
|
||||||
t.Fatalf("bad code: %d", resp.Code)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPreparedQuery_parseLimit(t *testing.T) {
|
func TestPreparedQuery_parseLimit(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
body := bytes.NewBuffer(nil)
|
body := bytes.NewBuffer(nil)
|
||||||
|
|
|
@ -27,10 +27,8 @@ type sessionCreateResponse struct {
|
||||||
|
|
||||||
// SessionCreate is used to create a new session
|
// SessionCreate is used to create a new session
|
||||||
func (s *HTTPServer) SessionCreate(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) SessionCreate(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
// Mandate a PUT request
|
|
||||||
if req.Method != "PUT" {
|
if req.Method != "PUT" {
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default the session to our node + serf check + release session invalidate behavior
|
// Default the session to our node + serf check + release session invalidate behavior
|
||||||
|
@ -107,10 +105,8 @@ func FixupLockDelay(raw interface{}) error {
|
||||||
|
|
||||||
// SessionDestroy is used to destroy an existing session
|
// SessionDestroy is used to destroy an existing session
|
||||||
func (s *HTTPServer) SessionDestroy(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) SessionDestroy(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
// Mandate a PUT request
|
|
||||||
if req.Method != "PUT" {
|
if req.Method != "PUT" {
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
args := structs.SessionRequest{
|
args := structs.SessionRequest{
|
||||||
|
@ -136,10 +132,8 @@ func (s *HTTPServer) SessionDestroy(resp http.ResponseWriter, req *http.Request)
|
||||||
|
|
||||||
// SessionRenew is used to renew the TTL on an existing TTL session
|
// SessionRenew is used to renew the TTL on an existing TTL session
|
||||||
func (s *HTTPServer) SessionRenew(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) SessionRenew(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
// Mandate a PUT request
|
|
||||||
if req.Method != "PUT" {
|
if req.Method != "PUT" {
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
args := structs.SessionSpecificRequest{}
|
args := structs.SessionSpecificRequest{}
|
||||||
|
@ -169,6 +163,10 @@ func (s *HTTPServer) SessionRenew(resp http.ResponseWriter, req *http.Request) (
|
||||||
|
|
||||||
// SessionGet is used to get info for a particular session
|
// SessionGet is used to get info for a particular session
|
||||||
func (s *HTTPServer) SessionGet(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) SessionGet(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
args := structs.SessionSpecificRequest{}
|
args := structs.SessionSpecificRequest{}
|
||||||
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
@ -197,6 +195,10 @@ func (s *HTTPServer) SessionGet(resp http.ResponseWriter, req *http.Request) (in
|
||||||
|
|
||||||
// SessionList is used to list all the sessions
|
// SessionList is used to list all the sessions
|
||||||
func (s *HTTPServer) SessionList(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) SessionList(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
args := structs.DCSpecificRequest{}
|
args := structs.DCSpecificRequest{}
|
||||||
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
@ -217,6 +219,10 @@ func (s *HTTPServer) SessionList(resp http.ResponseWriter, req *http.Request) (i
|
||||||
|
|
||||||
// SessionsForNode returns all the nodes belonging to a node
|
// SessionsForNode returns all the nodes belonging to a node
|
||||||
func (s *HTTPServer) SessionsForNode(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) SessionsForNode(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
args := structs.NodeSpecificRequest{}
|
args := structs.NodeSpecificRequest{}
|
||||||
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
@ -44,7 +44,6 @@ func (s *HTTPServer) Snapshot(resp http.ResponseWriter, req *http.Request) (inte
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"GET", "PUT"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,38 +101,3 @@ func TestSnapshot_Options(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSnapshot_BadMethods(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
t.Run("", func(t *testing.T) {
|
|
||||||
a := NewTestAgent(t.Name(), "")
|
|
||||||
defer a.Shutdown()
|
|
||||||
|
|
||||||
body := bytes.NewBuffer(nil)
|
|
||||||
req, _ := http.NewRequest("POST", "/v1/snapshot", body)
|
|
||||||
resp := httptest.NewRecorder()
|
|
||||||
_, err := a.srv.Snapshot(resp, req)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("err: %v", err)
|
|
||||||
}
|
|
||||||
if resp.Code != 405 {
|
|
||||||
t.Fatalf("bad code: %d", resp.Code)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("", func(t *testing.T) {
|
|
||||||
a := NewTestAgent(t.Name(), "")
|
|
||||||
defer a.Shutdown()
|
|
||||||
|
|
||||||
body := bytes.NewBuffer(nil)
|
|
||||||
req, _ := http.NewRequest("DELETE", "/v1/snapshot", body)
|
|
||||||
resp := httptest.NewRecorder()
|
|
||||||
_, err := a.srv.Snapshot(resp, req)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("err: %v", err)
|
|
||||||
}
|
|
||||||
if resp.Code != 405 {
|
|
||||||
t.Fatalf("bad code: %d", resp.Code)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,6 +5,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *HTTPServer) StatusLeader(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) StatusLeader(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
var out string
|
var out string
|
||||||
if err := s.agent.RPC("Status.Leader", struct{}{}, &out); err != nil {
|
if err := s.agent.RPC("Status.Leader", struct{}{}, &out); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -13,6 +17,10 @@ func (s *HTTPServer) StatusLeader(resp http.ResponseWriter, req *http.Request) (
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTPServer) StatusPeers(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) StatusPeers(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
var out []string
|
var out []string
|
||||||
if err := s.agent.RPC("Status.Peers", struct{}{}, &out); err != nil {
|
if err := s.agent.RPC("Status.Peers", struct{}{}, &out); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
package agent
|
package agent
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
func TestStatusLeader(t *testing.T) {
|
func TestStatusLeader(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
a := NewTestAgent(t.Name(), "")
|
a := NewTestAgent(t.Name(), "")
|
||||||
defer a.Shutdown()
|
defer a.Shutdown()
|
||||||
|
|
||||||
obj, err := a.srv.StatusLeader(nil, nil)
|
req, _ := http.NewRequest("GET", "/v1/status/leader", nil)
|
||||||
|
obj, err := a.srv.StatusLeader(nil, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Err: %v", err)
|
t.Fatalf("Err: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -22,7 +26,8 @@ func TestStatusPeers(t *testing.T) {
|
||||||
a := NewTestAgent(t.Name(), "")
|
a := NewTestAgent(t.Name(), "")
|
||||||
defer a.Shutdown()
|
defer a.Shutdown()
|
||||||
|
|
||||||
obj, err := a.srv.StatusPeers(nil, nil)
|
req, _ := http.NewRequest("GET", "/v1/status/peers", nil)
|
||||||
|
obj, err := a.srv.StatusPeers(nil, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Err: %v", err)
|
t.Fatalf("Err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
metrics "github.com/armon/go-metrics"
|
||||||
"github.com/hashicorp/consul/agent/config"
|
"github.com/hashicorp/consul/agent/config"
|
||||||
"github.com/hashicorp/consul/agent/consul"
|
"github.com/hashicorp/consul/agent/consul"
|
||||||
"github.com/hashicorp/consul/agent/structs"
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
|
@ -147,6 +148,7 @@ func (a *TestAgent) Start() *TestAgent {
|
||||||
agent.LogOutput = logOutput
|
agent.LogOutput = logOutput
|
||||||
agent.LogWriter = a.LogWriter
|
agent.LogWriter = a.LogWriter
|
||||||
agent.logger = log.New(logOutput, a.Name+" - ", log.LstdFlags|log.Lmicroseconds)
|
agent.logger = log.New(logOutput, a.Name+" - ", log.LstdFlags|log.Lmicroseconds)
|
||||||
|
agent.MemSink = &metrics.InmemSink{}
|
||||||
|
|
||||||
// we need the err var in the next exit condition
|
// we need the err var in the next exit condition
|
||||||
if err := agent.Start(); err == nil {
|
if err := agent.Start(); err == nil {
|
||||||
|
|
|
@ -173,8 +173,7 @@ func (s *HTTPServer) convertOps(resp http.ResponseWriter, req *http.Request) (st
|
||||||
// and everything else will be routed through Raft like a normal write.
|
// and everything else will be routed through Raft like a normal write.
|
||||||
func (s *HTTPServer) Txn(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) Txn(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
if req.Method != "PUT" {
|
if req.Method != "PUT" {
|
||||||
resp.WriteHeader(http.StatusMethodNotAllowed)
|
return nil, MethodNotAllowedError{req.Method, []string{"PUT"}}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the ops from the API format to the internal format.
|
// Convert the ops from the API format to the internal format.
|
||||||
|
|
|
@ -31,22 +31,6 @@ func TestTxnEndpoint_Bad_JSON(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTxnEndpoint_Bad_Method(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
a := NewTestAgent(t.Name(), "")
|
|
||||||
defer a.Shutdown()
|
|
||||||
|
|
||||||
buf := bytes.NewBuffer([]byte("{}"))
|
|
||||||
req, _ := http.NewRequest("GET", "/v1/txn", buf)
|
|
||||||
resp := httptest.NewRecorder()
|
|
||||||
if _, err := a.srv.Txn(resp, req); err != nil {
|
|
||||||
t.Fatalf("err: %v", err)
|
|
||||||
}
|
|
||||||
if resp.Code != 405 {
|
|
||||||
t.Fatalf("expected 405, got %d", resp.Code)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTxnEndpoint_Bad_Size_Item(t *testing.T) {
|
func TestTxnEndpoint_Bad_Size_Item(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
a := NewTestAgent(t.Name(), "")
|
a := NewTestAgent(t.Name(), "")
|
||||||
|
|
|
@ -22,6 +22,10 @@ type ServiceSummary struct {
|
||||||
// UINodes is used to list the nodes in a given datacenter. We return a
|
// UINodes is used to list the nodes in a given datacenter. We return a
|
||||||
// NodeDump which provides overview information for all the nodes
|
// NodeDump which provides overview information for all the nodes
|
||||||
func (s *HTTPServer) UINodes(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) UINodes(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
// Parse arguments
|
// Parse arguments
|
||||||
args := structs.DCSpecificRequest{}
|
args := structs.DCSpecificRequest{}
|
||||||
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
||||||
|
@ -59,6 +63,10 @@ RPC:
|
||||||
// UINodeInfo is used to get info on a single node in a given datacenter. We return a
|
// UINodeInfo is used to get info on a single node in a given datacenter. We return a
|
||||||
// NodeInfo which provides overview information for the node
|
// NodeInfo which provides overview information for the node
|
||||||
func (s *HTTPServer) UINodeInfo(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) UINodeInfo(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
// Parse arguments
|
// Parse arguments
|
||||||
args := structs.NodeSpecificRequest{}
|
args := structs.NodeSpecificRequest{}
|
||||||
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
||||||
|
@ -105,6 +113,10 @@ RPC:
|
||||||
// UIServices is used to list the services in a given datacenter. We return a
|
// UIServices is used to list the services in a given datacenter. We return a
|
||||||
// ServiceSummary which provides overview information for the service
|
// ServiceSummary which provides overview information for the service
|
||||||
func (s *HTTPServer) UIServices(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (s *HTTPServer) UIServices(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
|
if req.Method != "GET" {
|
||||||
|
return nil, MethodNotAllowedError{req.Method, []string{"GET"}}
|
||||||
|
}
|
||||||
|
|
||||||
// Parse arguments
|
// Parse arguments
|
||||||
args := structs.DCSpecificRequest{}
|
args := structs.DCSpecificRequest{}
|
||||||
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
||||||
|
|
|
@ -25,13 +25,13 @@ const (
|
||||||
|
|
||||||
// JoinLAN is used to join local datacenters together.
|
// JoinLAN is used to join local datacenters together.
|
||||||
func (s *TestServer) JoinLAN(t *testing.T, addr string) {
|
func (s *TestServer) JoinLAN(t *testing.T, addr string) {
|
||||||
resp := s.get(t, "/v1/agent/join/"+addr)
|
resp := s.put(t, "/v1/agent/join/"+addr, nil)
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// JoinWAN is used to join remote datacenters together.
|
// JoinWAN is used to join remote datacenters together.
|
||||||
func (s *TestServer) JoinWAN(t *testing.T, addr string) {
|
func (s *TestServer) JoinWAN(t *testing.T, addr string) {
|
||||||
resp := s.get(t, "/v1/agent/join/"+addr+"?wan=1")
|
resp := s.put(t, "/v1/agent/join/"+addr+"?wan=1", nil)
|
||||||
resp.Body.Close()
|
resp.Body.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -423,7 +423,7 @@ This endpoint instructs the agent to attempt to connect to a given address.
|
||||||
|
|
||||||
| Method | Path | Produces |
|
| Method | Path | Produces |
|
||||||
| ------ | ---------------------------- | -------------------------- |
|
| ------ | ---------------------------- | -------------------------- |
|
||||||
| `GET` | `/agent/join/:address` | `application/json` |
|
| `PUT` | `/agent/join/:address` | `application/json` |
|
||||||
|
|
||||||
The table below shows this endpoint's support for
|
The table below shows this endpoint's support for
|
||||||
[blocking queries](/api/index.html#blocking-queries),
|
[blocking queries](/api/index.html#blocking-queries),
|
||||||
|
|
|
@ -214,7 +214,7 @@ This endpoint is used with a TTL type check to set the status of the check to
|
||||||
|
|
||||||
| Method | Path | Produces |
|
| Method | Path | Produces |
|
||||||
| ------ | ----------------------------- | -------------------------- |
|
| ------ | ----------------------------- | -------------------------- |
|
||||||
| `GET` | `/agent/check/pass/:check_id` | `application/json` |
|
| `PUT` | `/agent/check/pass/:check_id` | `application/json` |
|
||||||
|
|
||||||
The table below shows this endpoint's support for
|
The table below shows this endpoint's support for
|
||||||
[blocking queries](/api/index.html#blocking-queries),
|
[blocking queries](/api/index.html#blocking-queries),
|
||||||
|
@ -247,7 +247,7 @@ This endpoint is used with a TTL type check to set the status of the check to
|
||||||
|
|
||||||
| Method | Path | Produces |
|
| Method | Path | Produces |
|
||||||
| ------ | ----------------------------- | -------------------------- |
|
| ------ | ----------------------------- | -------------------------- |
|
||||||
| `GET` | `/agent/check/warn/:check_id` | `application/json` |
|
| `PUT` | `/agent/check/warn/:check_id` | `application/json` |
|
||||||
|
|
||||||
The table below shows this endpoint's support for
|
The table below shows this endpoint's support for
|
||||||
[blocking queries](/api/index.html#blocking-queries),
|
[blocking queries](/api/index.html#blocking-queries),
|
||||||
|
@ -280,7 +280,7 @@ This endpoint is used with a TTL type check to set the status of the check to
|
||||||
|
|
||||||
| Method | Path | Produces |
|
| Method | Path | Produces |
|
||||||
| ------ | ----------------------------- | -------------------------- |
|
| ------ | ----------------------------- | -------------------------- |
|
||||||
| `GET` | `/agent/check/fail/:check_id` | `application/json` |
|
| `PUT` | `/agent/check/fail/:check_id` | `application/json` |
|
||||||
|
|
||||||
The table below shows this endpoint's support for
|
The table below shows this endpoint's support for
|
||||||
[blocking queries](/api/index.html#blocking-queries),
|
[blocking queries](/api/index.html#blocking-queries),
|
||||||
|
|
Loading…
Reference in New Issue