2014-01-04 01:15:51 +00:00
|
|
|
package agent
|
|
|
|
|
|
|
|
import (
|
2014-01-30 23:35:38 +00:00
|
|
|
"fmt"
|
2016-11-16 21:45:26 +00:00
|
|
|
"log"
|
2014-01-04 01:15:51 +00:00
|
|
|
"net/http"
|
2015-01-21 17:53:31 +00:00
|
|
|
"strconv"
|
2014-01-04 01:15:51 +00:00
|
|
|
"strings"
|
2016-06-06 08:53:30 +00:00
|
|
|
|
pkg refactor
command/agent/* -> agent/*
command/consul/* -> agent/consul/*
command/agent/command{,_test}.go -> command/agent{,_test}.go
command/base/command.go -> command/base.go
command/base/* -> command/*
commands.go -> command/commands.go
The script which did the refactor is:
(
cd $GOPATH/src/github.com/hashicorp/consul
git mv command/agent/command.go command/agent.go
git mv command/agent/command_test.go command/agent_test.go
git mv command/agent/flag_slice_value{,_test}.go command/
git mv command/agent .
git mv command/base/command.go command/base.go
git mv command/base/config_util{,_test}.go command/
git mv commands.go command/
git mv consul agent
rmdir command/base/
gsed -i -e 's|package agent|package command|' command/agent{,_test}.go
gsed -i -e 's|package agent|package command|' command/flag_slice_value{,_test}.go
gsed -i -e 's|package base|package command|' command/base.go command/config_util{,_test}.go
gsed -i -e 's|package main|package command|' command/commands.go
gsed -i -e 's|base.Command|BaseCommand|' command/commands.go
gsed -i -e 's|agent.Command|AgentCommand|' command/commands.go
gsed -i -e 's|\tCommand:|\tBaseCommand:|' command/commands.go
gsed -i -e 's|base\.||' command/commands.go
gsed -i -e 's|command\.||' command/commands.go
gsed -i -e 's|command|c|' main.go
gsed -i -e 's|range Commands|range command.Commands|' main.go
gsed -i -e 's|Commands: Commands|Commands: command.Commands|' main.go
gsed -i -e 's|base\.BoolValue|BoolValue|' command/operator_autopilot_set.go
gsed -i -e 's|base\.DurationValue|DurationValue|' command/operator_autopilot_set.go
gsed -i -e 's|base\.StringValue|StringValue|' command/operator_autopilot_set.go
gsed -i -e 's|base\.UintValue|UintValue|' command/operator_autopilot_set.go
gsed -i -e 's|\bCommand\b|BaseCommand|' command/base.go
gsed -i -e 's|BaseCommand Options|Command Options|' command/base.go
gsed -i -e 's|base.Command|BaseCommand|' command/*.go
gsed -i -e 's|c\.Command|c.BaseCommand|g' command/*.go
gsed -i -e 's|\tCommand:|\tBaseCommand:|' command/*_test.go
gsed -i -e 's|base\.||' command/*_test.go
gsed -i -e 's|\bCommand\b|AgentCommand|' command/agent{,_test}.go
gsed -i -e 's|cmd.AgentCommand|cmd.BaseCommand|' command/agent.go
gsed -i -e 's|cli.AgentCommand = new(Command)|cli.Command = new(AgentCommand)|' command/agent_test.go
gsed -i -e 's|exec.AgentCommand|exec.Command|' command/agent_test.go
gsed -i -e 's|exec.BaseCommand|exec.Command|' command/agent_test.go
gsed -i -e 's|NewTestAgent|agent.NewTestAgent|' command/agent_test.go
gsed -i -e 's|= TestConfig|= agent.TestConfig|' command/agent_test.go
gsed -i -e 's|: RetryJoin|: agent.RetryJoin|' command/agent_test.go
gsed -i -e 's|\.\./\.\./|../|' command/config_util_test.go
gsed -i -e 's|\bverifyUniqueListeners|VerifyUniqueListeners|' agent/config{,_test}.go command/agent.go
gsed -i -e 's|\bserfLANKeyring\b|SerfLANKeyring|g' agent/{agent,keyring,testagent}.go command/agent.go
gsed -i -e 's|\bserfWANKeyring\b|SerfWANKeyring|g' agent/{agent,keyring,testagent}.go command/agent.go
gsed -i -e 's|\bNewAgent\b|agent.New|g' command/agent{,_test}.go
gsed -i -e 's|\bNewAgent|New|' agent/{acl_test,agent,testagent}.go
gsed -i -e 's|\bAgent\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bBool\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bConfig\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bDefaultConfig\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bDevConfig\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bMergeConfig\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bReadConfigPaths\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bParseMetaPair\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bSerfLANKeyring\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|\bSerfWANKeyring\b|agent.&|g' command/agent{,_test}.go
gsed -i -e 's|circonus\.agent|circonus|g' command/agent{,_test}.go
gsed -i -e 's|logger\.agent|logger|g' command/agent{,_test}.go
gsed -i -e 's|metrics\.agent|metrics|g' command/agent{,_test}.go
gsed -i -e 's|// agent.Agent|// agent|' command/agent{,_test}.go
gsed -i -e 's|a\.agent\.Config|a.Config|' command/agent{,_test}.go
gsed -i -e 's|agent\.AppendSliceValue|AppendSliceValue|' command/{configtest,validate}.go
gsed -i -e 's|consul/consul|agent/consul|' GNUmakefile
gsed -i -e 's|\.\./test|../../test|' agent/consul/server_test.go
# fix imports
f=$(grep -rl 'github.com/hashicorp/consul/command/agent' * | grep '\.go')
gsed -i -e 's|github.com/hashicorp/consul/command/agent|github.com/hashicorp/consul/agent|' $f
goimports -w $f
f=$(grep -rl 'github.com/hashicorp/consul/consul' * | grep '\.go')
gsed -i -e 's|github.com/hashicorp/consul/consul|github.com/hashicorp/consul/agent/consul|' $f
goimports -w $f
goimports -w command/*.go main.go
)
2017-06-09 22:28:28 +00:00
|
|
|
"github.com/hashicorp/consul/agent/consul/structs"
|
2017-04-19 23:00:11 +00:00
|
|
|
"github.com/hashicorp/consul/api"
|
2017-05-15 20:10:36 +00:00
|
|
|
"github.com/hashicorp/consul/ipaddr"
|
2016-11-16 21:45:26 +00:00
|
|
|
"github.com/hashicorp/consul/logger"
|
2016-06-06 20:19:31 +00:00
|
|
|
"github.com/hashicorp/consul/types"
|
2016-11-16 21:45:26 +00:00
|
|
|
"github.com/hashicorp/logutils"
|
2016-06-06 08:53:30 +00:00
|
|
|
"github.com/hashicorp/serf/coordinate"
|
|
|
|
"github.com/hashicorp/serf/serf"
|
2014-01-04 01:15:51 +00:00
|
|
|
)
|
|
|
|
|
2017-04-21 00:46:29 +00:00
|
|
|
type Self struct {
|
2014-05-27 22:09:28 +00:00
|
|
|
Config *Config
|
2015-07-30 19:02:37 +00:00
|
|
|
Coord *coordinate.Coordinate
|
2014-05-27 22:09:28 +00:00
|
|
|
Member serf.Member
|
2016-07-20 22:12:26 +00:00
|
|
|
Stats map[string]map[string]string
|
2017-01-05 22:10:26 +00:00
|
|
|
Meta map[string]string
|
2014-05-27 22:09:28 +00:00
|
|
|
}
|
|
|
|
|
2014-05-25 23:59:48 +00:00
|
|
|
func (s *HTTPServer) AgentSelf(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
2015-10-16 02:28:31 +00:00
|
|
|
var c *coordinate.Coordinate
|
2015-07-30 19:02:37 +00:00
|
|
|
if !s.agent.config.DisableCoordinates {
|
|
|
|
var err error
|
2017-05-15 14:05:17 +00:00
|
|
|
if c, err = s.agent.GetLANCoordinate(); err != nil {
|
2015-07-30 19:02:37 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-14 17:33:57 +00:00
|
|
|
// Fetch the ACL token, if any, and enforce agent policy.
|
|
|
|
var token string
|
|
|
|
s.parseToken(req, &token)
|
|
|
|
acl, err := s.agent.resolveToken(token)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if acl != nil && !acl.AgentRead(s.agent.config.NodeName) {
|
2017-04-21 00:02:42 +00:00
|
|
|
return nil, errPermissionDenied
|
2016-12-14 17:33:57 +00:00
|
|
|
}
|
|
|
|
|
2017-04-21 00:46:29 +00:00
|
|
|
return Self{
|
2014-05-27 22:09:28 +00:00
|
|
|
Config: s.agent.config,
|
2015-10-16 02:28:31 +00:00
|
|
|
Coord: c,
|
2014-05-27 22:09:28 +00:00
|
|
|
Member: s.agent.LocalMember(),
|
2016-07-20 22:12:26 +00:00
|
|
|
Stats: s.agent.Stats(),
|
2017-01-05 22:10:26 +00:00
|
|
|
Meta: s.agent.state.Metadata(),
|
2014-05-27 22:09:28 +00:00
|
|
|
}, nil
|
2014-05-25 23:59:48 +00:00
|
|
|
}
|
|
|
|
|
2016-11-30 18:29:42 +00:00
|
|
|
func (s *HTTPServer) AgentReload(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
|
|
|
if req.Method != "PUT" {
|
|
|
|
resp.WriteHeader(http.StatusMethodNotAllowed)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2016-12-14 17:33:57 +00:00
|
|
|
// Fetch the ACL token, if any, and enforce agent policy.
|
|
|
|
var token string
|
|
|
|
s.parseToken(req, &token)
|
|
|
|
acl, err := s.agent.resolveToken(token)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if acl != nil && !acl.AgentWrite(s.agent.config.NodeName) {
|
2017-04-21 00:02:42 +00:00
|
|
|
return nil, errPermissionDenied
|
2016-12-14 17:33:57 +00:00
|
|
|
}
|
2016-11-30 18:29:42 +00:00
|
|
|
|
|
|
|
// Trigger the reload
|
2016-12-14 17:33:57 +00:00
|
|
|
errCh := make(chan error, 0)
|
2016-11-30 18:29:42 +00:00
|
|
|
select {
|
2017-05-19 15:51:39 +00:00
|
|
|
case <-s.agent.shutdownCh:
|
2016-11-30 18:29:42 +00:00
|
|
|
return nil, fmt.Errorf("Agent was shutdown before reload could be completed")
|
|
|
|
case s.agent.reloadCh <- errCh:
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait for the result of the reload, or for the agent to shutdown
|
|
|
|
select {
|
2017-05-19 15:51:39 +00:00
|
|
|
case <-s.agent.shutdownCh:
|
2016-11-30 18:29:42 +00:00
|
|
|
return nil, fmt.Errorf("Agent was shutdown before reload could be completed")
|
|
|
|
case err := <-errCh:
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-04 01:15:51 +00:00
|
|
|
func (s *HTTPServer) AgentServices(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
2016-12-14 22:16:46 +00:00
|
|
|
// Fetch the ACL token, if any.
|
|
|
|
var token string
|
|
|
|
s.parseToken(req, &token)
|
|
|
|
|
2014-01-21 19:52:25 +00:00
|
|
|
services := s.agent.state.Services()
|
2016-12-14 22:16:46 +00:00
|
|
|
if err := s.agent.filterServices(token, &services); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-04-28 01:22:07 +00:00
|
|
|
|
|
|
|
// Use empty list instead of nil
|
|
|
|
for _, s := range services {
|
|
|
|
if s.Tags == nil {
|
|
|
|
s.Tags = make([]string, 0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-21 01:00:52 +00:00
|
|
|
return services, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *HTTPServer) AgentChecks(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
2016-12-14 22:16:46 +00:00
|
|
|
// Fetch the ACL token, if any.
|
|
|
|
var token string
|
|
|
|
s.parseToken(req, &token)
|
|
|
|
|
2014-01-21 19:52:25 +00:00
|
|
|
checks := s.agent.state.Checks()
|
2016-12-14 22:16:46 +00:00
|
|
|
if err := s.agent.filterChecks(token, &checks); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-04-28 01:22:07 +00:00
|
|
|
|
|
|
|
// Use empty list instead of nil
|
|
|
|
for _, c := range checks {
|
|
|
|
if c.ServiceTags == nil {
|
|
|
|
c.ServiceTags = make([]string, 0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-21 01:00:52 +00:00
|
|
|
return checks, nil
|
2014-01-04 01:15:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *HTTPServer) AgentMembers(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
2016-12-14 22:16:46 +00:00
|
|
|
// Fetch the ACL token, if any.
|
|
|
|
var token string
|
|
|
|
s.parseToken(req, &token)
|
|
|
|
|
2014-01-04 01:15:51 +00:00
|
|
|
// Check if the WAN is being queried
|
|
|
|
wan := false
|
|
|
|
if other := req.URL.Query().Get("wan"); other != "" {
|
|
|
|
wan = true
|
|
|
|
}
|
2016-12-14 22:16:46 +00:00
|
|
|
|
|
|
|
var members []serf.Member
|
2014-01-04 01:15:51 +00:00
|
|
|
if wan {
|
2016-12-14 22:16:46 +00:00
|
|
|
members = s.agent.WANMembers()
|
2014-01-04 01:15:51 +00:00
|
|
|
} else {
|
2016-12-14 22:16:46 +00:00
|
|
|
members = s.agent.LANMembers()
|
|
|
|
}
|
|
|
|
if err := s.agent.filterMembers(token, &members); err != nil {
|
|
|
|
return nil, err
|
2014-01-04 01:15:51 +00:00
|
|
|
}
|
2016-12-14 22:16:46 +00:00
|
|
|
return members, nil
|
2014-01-04 01:15:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *HTTPServer) AgentJoin(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
2016-12-14 17:33:57 +00:00
|
|
|
// Fetch the ACL token, if any, and enforce agent policy.
|
|
|
|
var token string
|
|
|
|
s.parseToken(req, &token)
|
|
|
|
acl, err := s.agent.resolveToken(token)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if acl != nil && !acl.AgentWrite(s.agent.config.NodeName) {
|
2017-04-21 00:02:42 +00:00
|
|
|
return nil, errPermissionDenied
|
2016-12-14 17:33:57 +00:00
|
|
|
}
|
|
|
|
|
2014-01-04 01:15:51 +00:00
|
|
|
// Check if the WAN is being queried
|
|
|
|
wan := false
|
|
|
|
if other := req.URL.Query().Get("wan"); other != "" {
|
|
|
|
wan = true
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the address
|
|
|
|
addr := strings.TrimPrefix(req.URL.Path, "/v1/agent/join/")
|
|
|
|
if wan {
|
2017-04-21 01:59:42 +00:00
|
|
|
_, err = s.agent.JoinWAN([]string{addr})
|
2014-01-04 01:15:51 +00:00
|
|
|
} else {
|
2017-04-21 01:59:42 +00:00
|
|
|
_, err = s.agent.JoinLAN([]string{addr})
|
2014-01-04 01:15:51 +00:00
|
|
|
}
|
2017-04-21 01:59:42 +00:00
|
|
|
return nil, err
|
2014-01-04 01:15:51 +00:00
|
|
|
}
|
|
|
|
|
2016-11-30 18:29:42 +00:00
|
|
|
func (s *HTTPServer) AgentLeave(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
|
|
|
if req.Method != "PUT" {
|
|
|
|
resp.WriteHeader(http.StatusMethodNotAllowed)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2016-12-14 17:33:57 +00:00
|
|
|
// Fetch the ACL token, if any, and enforce agent policy.
|
|
|
|
var token string
|
|
|
|
s.parseToken(req, &token)
|
|
|
|
acl, err := s.agent.resolveToken(token)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if acl != nil && !acl.AgentWrite(s.agent.config.NodeName) {
|
2017-04-21 00:02:42 +00:00
|
|
|
return nil, errPermissionDenied
|
2016-12-14 17:33:57 +00:00
|
|
|
}
|
|
|
|
|
2016-11-30 18:29:42 +00:00
|
|
|
if err := s.agent.Leave(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-06-20 07:29:20 +00:00
|
|
|
return nil, s.agent.ShutdownAgent()
|
2016-11-30 18:29:42 +00:00
|
|
|
}
|
|
|
|
|
2014-01-04 01:15:51 +00:00
|
|
|
func (s *HTTPServer) AgentForceLeave(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
2016-12-14 17:33:57 +00:00
|
|
|
// Fetch the ACL token, if any, and enforce agent policy.
|
|
|
|
var token string
|
|
|
|
s.parseToken(req, &token)
|
|
|
|
acl, err := s.agent.resolveToken(token)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if acl != nil && !acl.AgentWrite(s.agent.config.NodeName) {
|
2017-04-21 00:02:42 +00:00
|
|
|
return nil, errPermissionDenied
|
2016-12-14 17:33:57 +00:00
|
|
|
}
|
|
|
|
|
2014-01-04 01:15:51 +00:00
|
|
|
addr := strings.TrimPrefix(req.URL.Path, "/v1/agent/force-leave/")
|
2014-02-19 22:27:01 +00:00
|
|
|
return nil, s.agent.ForceLeave(addr)
|
2014-01-04 01:15:51 +00:00
|
|
|
}
|
2014-01-30 22:58:36 +00:00
|
|
|
|
2016-12-14 17:33:57 +00:00
|
|
|
// syncChanges is a helper function which wraps a blocking call to sync
|
|
|
|
// services and checks to the server. If the operation fails, we only
|
|
|
|
// only warn because the write did succeed and anti-entropy will sync later.
|
|
|
|
func (s *HTTPServer) syncChanges() {
|
|
|
|
if err := s.agent.state.syncChanges(); err != nil {
|
2017-05-19 09:53:41 +00:00
|
|
|
s.agent.logger.Printf("[ERR] agent: failed to sync changes: %v", err)
|
2016-12-14 17:33:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-27 16:20:19 +00:00
|
|
|
const invalidCheckMessage = "Must provide TTL or Script/DockerContainerID/HTTP/TCP and Interval"
|
|
|
|
|
2014-01-30 22:58:36 +00:00
|
|
|
func (s *HTTPServer) AgentRegisterCheck(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
2017-06-15 16:46:06 +00:00
|
|
|
var args structs.CheckDefinition
|
2016-12-14 22:16:46 +00:00
|
|
|
// Fixup the type decode of TTL or Interval.
|
2014-04-21 22:02:36 +00:00
|
|
|
decodeCB := func(raw interface{}) error {
|
|
|
|
return FixupCheckType(raw)
|
|
|
|
}
|
|
|
|
if err := decodeBody(req, &args, decodeCB); err != nil {
|
2014-01-30 23:35:38 +00:00
|
|
|
resp.WriteHeader(400)
|
Use fmt.Fprint/Fprintf/Fprintln
Used the following rewrite rules:
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c, d))) -> fmt.Fprintf(resp, a, b, c, d)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c))) -> fmt.Fprintf(resp, a, b, c)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b))) -> fmt.Fprintf(resp, a, b)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a))) -> fmt.Fprint(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a + "\n")) -> fmt.Fprintln(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a)) -> fmt.Fprint(resp, a)' *.go
2017-04-20 14:07:42 +00:00
|
|
|
fmt.Fprintf(resp, "Request decode failed: %v", err)
|
2014-01-30 23:35:38 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2016-12-14 22:16:46 +00:00
|
|
|
// Verify the check has a name.
|
2014-01-30 23:35:38 +00:00
|
|
|
if args.Name == "" {
|
|
|
|
resp.WriteHeader(400)
|
Use fmt.Fprint/Fprintf/Fprintln
Used the following rewrite rules:
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c, d))) -> fmt.Fprintf(resp, a, b, c, d)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c))) -> fmt.Fprintf(resp, a, b, c)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b))) -> fmt.Fprintf(resp, a, b)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a))) -> fmt.Fprint(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a + "\n")) -> fmt.Fprintln(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a)) -> fmt.Fprint(resp, a)' *.go
2017-04-20 14:07:42 +00:00
|
|
|
fmt.Fprint(resp, "Missing check name")
|
2014-01-30 23:35:38 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2015-04-12 00:53:48 +00:00
|
|
|
if args.Status != "" && !structs.ValidStatus(args.Status) {
|
|
|
|
resp.WriteHeader(400)
|
Use fmt.Fprint/Fprintf/Fprintln
Used the following rewrite rules:
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c, d))) -> fmt.Fprintf(resp, a, b, c, d)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c))) -> fmt.Fprintf(resp, a, b, c)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b))) -> fmt.Fprintf(resp, a, b)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a))) -> fmt.Fprint(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a + "\n")) -> fmt.Fprintln(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a)) -> fmt.Fprint(resp, a)' *.go
2017-04-20 14:07:42 +00:00
|
|
|
fmt.Fprint(resp, "Bad check status")
|
2015-04-12 00:53:48 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2016-12-14 22:16:46 +00:00
|
|
|
// Construct the health check.
|
2014-02-03 23:15:35 +00:00
|
|
|
health := args.HealthCheck(s.agent.config.NodeName)
|
2014-01-30 23:35:38 +00:00
|
|
|
|
2016-12-14 22:16:46 +00:00
|
|
|
// Verify the check type.
|
2017-05-15 19:49:13 +00:00
|
|
|
chkType := args.CheckType()
|
2014-01-30 23:35:38 +00:00
|
|
|
if !chkType.Valid() {
|
|
|
|
resp.WriteHeader(400)
|
Use fmt.Fprint/Fprintf/Fprintln
Used the following rewrite rules:
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c, d))) -> fmt.Fprintf(resp, a, b, c, d)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c))) -> fmt.Fprintf(resp, a, b, c)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b))) -> fmt.Fprintf(resp, a, b)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a))) -> fmt.Fprint(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a + "\n")) -> fmt.Fprintln(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a)) -> fmt.Fprint(resp, a)' *.go
2017-04-20 14:07:42 +00:00
|
|
|
fmt.Fprint(resp, invalidCheckMessage)
|
2014-01-30 23:35:38 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2016-12-14 22:16:46 +00:00
|
|
|
// Get the provided token, if any, and vet against any ACL policies.
|
2015-04-28 01:26:23 +00:00
|
|
|
var token string
|
|
|
|
s.parseToken(req, &token)
|
2016-12-14 22:16:46 +00:00
|
|
|
if err := s.agent.vetCheckRegister(token, health); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2015-04-28 01:26:23 +00:00
|
|
|
|
2016-12-14 22:16:46 +00:00
|
|
|
// Add the check.
|
2015-05-05 00:36:17 +00:00
|
|
|
if err := s.agent.AddCheck(health, chkType, true, token); err != nil {
|
2015-02-20 23:45:06 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
s.syncChanges()
|
|
|
|
return nil, nil
|
2014-01-30 22:58:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *HTTPServer) AgentDeregisterCheck(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
2016-06-06 20:19:31 +00:00
|
|
|
checkID := types.CheckID(strings.TrimPrefix(req.URL.Path, "/v1/agent/check/deregister/"))
|
2016-12-14 22:16:46 +00:00
|
|
|
|
|
|
|
// Get the provided token, if any, and vet against any ACL policies.
|
|
|
|
var token string
|
|
|
|
s.parseToken(req, &token)
|
|
|
|
if err := s.agent.vetCheckUpdate(token, checkID); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2015-02-20 23:45:06 +00:00
|
|
|
if err := s.agent.RemoveCheck(checkID, true); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
s.syncChanges()
|
|
|
|
return nil, nil
|
2014-01-30 22:58:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *HTTPServer) AgentCheckPass(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
2016-06-06 20:19:31 +00:00
|
|
|
checkID := types.CheckID(strings.TrimPrefix(req.URL.Path, "/v1/agent/check/pass/"))
|
2014-01-30 23:18:05 +00:00
|
|
|
note := req.URL.Query().Get("note")
|
2016-12-14 22:16:46 +00:00
|
|
|
|
|
|
|
// Get the provided token, if any, and vet against any ACL policies.
|
|
|
|
var token string
|
|
|
|
s.parseToken(req, &token)
|
|
|
|
if err := s.agent.vetCheckUpdate(token, checkID); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-04-19 23:00:11 +00:00
|
|
|
if err := s.agent.updateTTLCheck(checkID, api.HealthPassing, note); err != nil {
|
2015-02-20 23:45:06 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
s.syncChanges()
|
|
|
|
return nil, nil
|
2014-01-30 22:58:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *HTTPServer) AgentCheckWarn(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
2016-06-06 20:19:31 +00:00
|
|
|
checkID := types.CheckID(strings.TrimPrefix(req.URL.Path, "/v1/agent/check/warn/"))
|
2014-01-30 23:18:05 +00:00
|
|
|
note := req.URL.Query().Get("note")
|
2016-12-14 22:16:46 +00:00
|
|
|
|
|
|
|
// Get the provided token, if any, and vet against any ACL policies.
|
|
|
|
var token string
|
|
|
|
s.parseToken(req, &token)
|
|
|
|
if err := s.agent.vetCheckUpdate(token, checkID); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-04-19 23:00:11 +00:00
|
|
|
if err := s.agent.updateTTLCheck(checkID, api.HealthWarning, note); err != nil {
|
2015-02-20 23:45:06 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
s.syncChanges()
|
|
|
|
return nil, nil
|
2014-01-30 22:58:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *HTTPServer) AgentCheckFail(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
2016-06-06 20:19:31 +00:00
|
|
|
checkID := types.CheckID(strings.TrimPrefix(req.URL.Path, "/v1/agent/check/fail/"))
|
2014-01-30 23:18:05 +00:00
|
|
|
note := req.URL.Query().Get("note")
|
2016-12-14 22:16:46 +00:00
|
|
|
|
|
|
|
// Get the provided token, if any, and vet against any ACL policies.
|
|
|
|
var token string
|
|
|
|
s.parseToken(req, &token)
|
|
|
|
if err := s.agent.vetCheckUpdate(token, checkID); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-04-19 23:00:11 +00:00
|
|
|
if err := s.agent.updateTTLCheck(checkID, api.HealthCritical, note); err != nil {
|
2015-02-20 23:45:06 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
s.syncChanges()
|
|
|
|
return nil, nil
|
2014-01-30 22:58:36 +00:00
|
|
|
}
|
|
|
|
|
2016-03-03 01:08:06 +00:00
|
|
|
// checkUpdate is the payload for a PUT to AgentCheckUpdate.
|
|
|
|
type checkUpdate struct {
|
2017-04-19 23:00:11 +00:00
|
|
|
// Status us one of the api.Health* states, "passing", "warning", or
|
2016-03-03 01:08:06 +00:00
|
|
|
// "critical".
|
|
|
|
Status string
|
|
|
|
|
|
|
|
// Output is the information to post to the UI for operators as the
|
|
|
|
// output of the process that decided to hit the TTL check. This is
|
|
|
|
// different from the note field that's associated with the check
|
|
|
|
// itself.
|
|
|
|
Output string
|
|
|
|
}
|
|
|
|
|
|
|
|
// AgentCheckUpdate is a PUT-based alternative to the GET-based Pass/Warn/Fail
|
|
|
|
// APIs.
|
|
|
|
func (s *HTTPServer) AgentCheckUpdate(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
|
|
|
if req.Method != "PUT" {
|
|
|
|
resp.WriteHeader(405)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var update checkUpdate
|
|
|
|
if err := decodeBody(req, &update, nil); err != nil {
|
|
|
|
resp.WriteHeader(400)
|
Use fmt.Fprint/Fprintf/Fprintln
Used the following rewrite rules:
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c, d))) -> fmt.Fprintf(resp, a, b, c, d)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c))) -> fmt.Fprintf(resp, a, b, c)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b))) -> fmt.Fprintf(resp, a, b)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a))) -> fmt.Fprint(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a + "\n")) -> fmt.Fprintln(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a)) -> fmt.Fprint(resp, a)' *.go
2017-04-20 14:07:42 +00:00
|
|
|
fmt.Fprintf(resp, "Request decode failed: %v", err)
|
2016-03-03 01:08:06 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
switch update.Status {
|
2017-04-19 23:00:11 +00:00
|
|
|
case api.HealthPassing:
|
|
|
|
case api.HealthWarning:
|
|
|
|
case api.HealthCritical:
|
2016-03-03 01:08:06 +00:00
|
|
|
default:
|
|
|
|
resp.WriteHeader(400)
|
Use fmt.Fprint/Fprintf/Fprintln
Used the following rewrite rules:
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c, d))) -> fmt.Fprintf(resp, a, b, c, d)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c))) -> fmt.Fprintf(resp, a, b, c)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b))) -> fmt.Fprintf(resp, a, b)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a))) -> fmt.Fprint(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a + "\n")) -> fmt.Fprintln(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a)) -> fmt.Fprint(resp, a)' *.go
2017-04-20 14:07:42 +00:00
|
|
|
fmt.Fprintf(resp, "Invalid check status: '%s'", update.Status)
|
2016-03-03 01:08:06 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
total := len(update.Output)
|
|
|
|
if total > CheckBufSize {
|
2016-03-03 03:47:00 +00:00
|
|
|
update.Output = fmt.Sprintf("%s ... (captured %d of %d bytes)",
|
2016-03-03 01:08:06 +00:00
|
|
|
update.Output[:CheckBufSize], CheckBufSize, total)
|
|
|
|
}
|
|
|
|
|
2016-06-06 20:19:31 +00:00
|
|
|
checkID := types.CheckID(strings.TrimPrefix(req.URL.Path, "/v1/agent/check/update/"))
|
2016-12-14 22:16:46 +00:00
|
|
|
|
|
|
|
// Get the provided token, if any, and vet against any ACL policies.
|
|
|
|
var token string
|
|
|
|
s.parseToken(req, &token)
|
|
|
|
if err := s.agent.vetCheckUpdate(token, checkID); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2016-08-16 07:05:55 +00:00
|
|
|
if err := s.agent.updateTTLCheck(checkID, update.Status, update.Output); err != nil {
|
2016-03-03 01:08:06 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
s.syncChanges()
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2014-01-30 22:58:36 +00:00
|
|
|
func (s *HTTPServer) AgentRegisterService(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
2017-06-15 16:46:06 +00:00
|
|
|
var args structs.ServiceDefinition
|
2016-12-14 22:16:46 +00:00
|
|
|
// Fixup the type decode of TTL or Interval if a check if provided.
|
2014-04-21 22:02:36 +00:00
|
|
|
decodeCB := func(raw interface{}) error {
|
|
|
|
rawMap, ok := raw.(map[string]interface{})
|
|
|
|
if !ok {
|
|
|
|
return nil
|
|
|
|
}
|
2014-04-25 02:44:27 +00:00
|
|
|
|
|
|
|
for k, v := range rawMap {
|
2015-01-14 03:08:30 +00:00
|
|
|
switch strings.ToLower(k) {
|
|
|
|
case "check":
|
|
|
|
if err := FixupCheckType(v); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
case "checks":
|
|
|
|
chkTypes, ok := v.([]interface{})
|
|
|
|
if !ok {
|
2015-01-24 02:50:51 +00:00
|
|
|
continue
|
2015-01-14 03:08:30 +00:00
|
|
|
}
|
|
|
|
for _, chkType := range chkTypes {
|
|
|
|
if err := FixupCheckType(chkType); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2014-04-25 02:44:27 +00:00
|
|
|
}
|
|
|
|
}
|
2015-01-14 03:08:30 +00:00
|
|
|
return nil
|
2014-04-21 22:02:36 +00:00
|
|
|
}
|
|
|
|
if err := decodeBody(req, &args, decodeCB); err != nil {
|
2014-01-30 23:35:38 +00:00
|
|
|
resp.WriteHeader(400)
|
Use fmt.Fprint/Fprintf/Fprintln
Used the following rewrite rules:
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c, d))) -> fmt.Fprintf(resp, a, b, c, d)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c))) -> fmt.Fprintf(resp, a, b, c)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b))) -> fmt.Fprintf(resp, a, b)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a))) -> fmt.Fprint(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a + "\n")) -> fmt.Fprintln(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a)) -> fmt.Fprint(resp, a)' *.go
2017-04-20 14:07:42 +00:00
|
|
|
fmt.Fprintf(resp, "Request decode failed: %v", err)
|
2014-01-30 23:35:38 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2016-12-14 22:16:46 +00:00
|
|
|
// Verify the service has a name.
|
2014-01-30 23:35:38 +00:00
|
|
|
if args.Name == "" {
|
|
|
|
resp.WriteHeader(400)
|
Use fmt.Fprint/Fprintf/Fprintln
Used the following rewrite rules:
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c, d))) -> fmt.Fprintf(resp, a, b, c, d)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c))) -> fmt.Fprintf(resp, a, b, c)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b))) -> fmt.Fprintf(resp, a, b)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a))) -> fmt.Fprint(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a + "\n")) -> fmt.Fprintln(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a)) -> fmt.Fprint(resp, a)' *.go
2017-04-20 14:07:42 +00:00
|
|
|
fmt.Fprint(resp, "Missing service name")
|
2014-01-30 23:35:38 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2017-05-08 16:34:45 +00:00
|
|
|
// Check the service address here and in the catalog RPC endpoint
|
|
|
|
// since service registration isn't sychronous.
|
2017-05-15 20:10:36 +00:00
|
|
|
if ipaddr.IsAny(args.Address) {
|
2017-05-08 16:34:45 +00:00
|
|
|
resp.WriteHeader(400)
|
|
|
|
fmt.Fprintf(resp, "Invalid service address")
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2016-12-14 22:16:46 +00:00
|
|
|
// Get the node service.
|
2014-02-03 23:15:35 +00:00
|
|
|
ns := args.NodeService()
|
2014-01-30 23:35:38 +00:00
|
|
|
|
2016-12-14 22:16:46 +00:00
|
|
|
// Verify the check type.
|
2015-01-14 01:52:17 +00:00
|
|
|
chkTypes := args.CheckTypes()
|
|
|
|
for _, check := range chkTypes {
|
2015-04-12 00:53:48 +00:00
|
|
|
if check.Status != "" && !structs.ValidStatus(check.Status) {
|
|
|
|
resp.WriteHeader(400)
|
Use fmt.Fprint/Fprintf/Fprintln
Used the following rewrite rules:
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c, d))) -> fmt.Fprintf(resp, a, b, c, d)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c))) -> fmt.Fprintf(resp, a, b, c)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b))) -> fmt.Fprintf(resp, a, b)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a))) -> fmt.Fprint(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a + "\n")) -> fmt.Fprintln(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a)) -> fmt.Fprint(resp, a)' *.go
2017-04-20 14:07:42 +00:00
|
|
|
fmt.Fprint(resp, "Status for checks must 'passing', 'warning', 'critical'")
|
2015-04-12 00:53:48 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
2015-01-14 01:52:17 +00:00
|
|
|
if !check.Valid() {
|
|
|
|
resp.WriteHeader(400)
|
Use fmt.Fprint/Fprintf/Fprintln
Used the following rewrite rules:
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c, d))) -> fmt.Fprintf(resp, a, b, c, d)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c))) -> fmt.Fprintf(resp, a, b, c)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b))) -> fmt.Fprintf(resp, a, b)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a))) -> fmt.Fprint(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a + "\n")) -> fmt.Fprintln(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a)) -> fmt.Fprint(resp, a)' *.go
2017-04-20 14:07:42 +00:00
|
|
|
fmt.Fprint(resp, invalidCheckMessage)
|
2015-01-14 01:52:17 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
2014-01-30 23:35:38 +00:00
|
|
|
}
|
|
|
|
|
2016-12-14 22:16:46 +00:00
|
|
|
// Get the provided token, if any, and vet against any ACL policies.
|
2015-04-28 01:26:23 +00:00
|
|
|
var token string
|
|
|
|
s.parseToken(req, &token)
|
2016-12-14 22:16:46 +00:00
|
|
|
if err := s.agent.vetServiceRegister(token, ns); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2015-04-28 01:26:23 +00:00
|
|
|
|
2016-12-14 22:16:46 +00:00
|
|
|
// Add the service.
|
2015-05-05 00:36:17 +00:00
|
|
|
if err := s.agent.AddService(ns, chkTypes, true, token); err != nil {
|
2015-02-20 23:45:06 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
s.syncChanges()
|
|
|
|
return nil, nil
|
2014-01-30 22:58:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *HTTPServer) AgentDeregisterService(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
2014-01-30 23:18:05 +00:00
|
|
|
serviceID := strings.TrimPrefix(req.URL.Path, "/v1/agent/service/deregister/")
|
2016-12-14 22:16:46 +00:00
|
|
|
|
|
|
|
// Get the provided token, if any, and vet against any ACL policies.
|
|
|
|
var token string
|
|
|
|
s.parseToken(req, &token)
|
|
|
|
if err := s.agent.vetServiceUpdate(token, serviceID); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2015-02-20 23:45:06 +00:00
|
|
|
if err := s.agent.RemoveService(serviceID, true); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
s.syncChanges()
|
|
|
|
return nil, nil
|
2014-01-30 22:58:36 +00:00
|
|
|
}
|
2015-01-15 08:16:34 +00:00
|
|
|
|
|
|
|
func (s *HTTPServer) AgentServiceMaintenance(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
2015-01-15 09:17:35 +00:00
|
|
|
// Only PUT supported
|
|
|
|
if req.Method != "PUT" {
|
|
|
|
resp.WriteHeader(405)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2015-01-15 08:16:34 +00:00
|
|
|
// Ensure we have a service ID
|
|
|
|
serviceID := strings.TrimPrefix(req.URL.Path, "/v1/agent/service/maintenance/")
|
|
|
|
if serviceID == "" {
|
|
|
|
resp.WriteHeader(400)
|
Use fmt.Fprint/Fprintf/Fprintln
Used the following rewrite rules:
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c, d))) -> fmt.Fprintf(resp, a, b, c, d)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c))) -> fmt.Fprintf(resp, a, b, c)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b))) -> fmt.Fprintf(resp, a, b)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a))) -> fmt.Fprint(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a + "\n")) -> fmt.Fprintln(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a)) -> fmt.Fprint(resp, a)' *.go
2017-04-20 14:07:42 +00:00
|
|
|
fmt.Fprint(resp, "Missing service ID")
|
2015-01-15 08:16:34 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure we have some action
|
|
|
|
params := req.URL.Query()
|
|
|
|
if _, ok := params["enable"]; !ok {
|
|
|
|
resp.WriteHeader(400)
|
Use fmt.Fprint/Fprintf/Fprintln
Used the following rewrite rules:
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c, d))) -> fmt.Fprintf(resp, a, b, c, d)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c))) -> fmt.Fprintf(resp, a, b, c)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b))) -> fmt.Fprintf(resp, a, b)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a))) -> fmt.Fprint(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a + "\n")) -> fmt.Fprintln(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a)) -> fmt.Fprint(resp, a)' *.go
2017-04-20 14:07:42 +00:00
|
|
|
fmt.Fprint(resp, "Missing value for enable")
|
2015-01-15 08:16:34 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
raw := params.Get("enable")
|
2015-01-21 17:53:31 +00:00
|
|
|
enable, err := strconv.ParseBool(raw)
|
|
|
|
if err != nil {
|
2015-01-15 08:16:34 +00:00
|
|
|
resp.WriteHeader(400)
|
Use fmt.Fprint/Fprintf/Fprintln
Used the following rewrite rules:
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c, d))) -> fmt.Fprintf(resp, a, b, c, d)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c))) -> fmt.Fprintf(resp, a, b, c)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b))) -> fmt.Fprintf(resp, a, b)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a))) -> fmt.Fprint(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a + "\n")) -> fmt.Fprintln(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a)) -> fmt.Fprint(resp, a)' *.go
2017-04-20 14:07:42 +00:00
|
|
|
fmt.Fprintf(resp, "Invalid value for enable: %q", raw)
|
2015-01-15 08:16:34 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2016-12-14 22:16:46 +00:00
|
|
|
// Get the provided token, if any, and vet against any ACL policies.
|
2015-09-10 18:43:59 +00:00
|
|
|
var token string
|
|
|
|
s.parseToken(req, &token)
|
2016-12-14 22:16:46 +00:00
|
|
|
if err := s.agent.vetServiceUpdate(token, serviceID); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2015-09-10 18:43:59 +00:00
|
|
|
|
2015-01-15 08:16:34 +00:00
|
|
|
if enable {
|
2015-01-21 20:21:57 +00:00
|
|
|
reason := params.Get("reason")
|
2015-09-10 18:43:59 +00:00
|
|
|
if err = s.agent.EnableServiceMaintenance(serviceID, reason, token); err != nil {
|
2015-01-15 18:51:00 +00:00
|
|
|
resp.WriteHeader(404)
|
Use fmt.Fprint/Fprintf/Fprintln
Used the following rewrite rules:
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c, d))) -> fmt.Fprintf(resp, a, b, c, d)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c))) -> fmt.Fprintf(resp, a, b, c)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b))) -> fmt.Fprintf(resp, a, b)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a))) -> fmt.Fprint(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a + "\n")) -> fmt.Fprintln(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a)) -> fmt.Fprint(resp, a)' *.go
2017-04-20 14:07:42 +00:00
|
|
|
fmt.Fprint(resp, err.Error())
|
2015-01-21 21:28:26 +00:00
|
|
|
return nil, nil
|
2015-01-15 09:17:35 +00:00
|
|
|
}
|
2015-01-15 08:16:34 +00:00
|
|
|
} else {
|
2015-01-15 09:17:35 +00:00
|
|
|
if err = s.agent.DisableServiceMaintenance(serviceID); err != nil {
|
2015-01-15 18:51:00 +00:00
|
|
|
resp.WriteHeader(404)
|
Use fmt.Fprint/Fprintf/Fprintln
Used the following rewrite rules:
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c, d))) -> fmt.Fprintf(resp, a, b, c, d)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c))) -> fmt.Fprintf(resp, a, b, c)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b))) -> fmt.Fprintf(resp, a, b)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a))) -> fmt.Fprint(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a + "\n")) -> fmt.Fprintln(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a)) -> fmt.Fprint(resp, a)' *.go
2017-04-20 14:07:42 +00:00
|
|
|
fmt.Fprint(resp, err.Error())
|
2015-01-21 21:28:26 +00:00
|
|
|
return nil, nil
|
2015-01-15 09:17:35 +00:00
|
|
|
}
|
2015-01-15 08:16:34 +00:00
|
|
|
}
|
2015-02-20 23:45:06 +00:00
|
|
|
s.syncChanges()
|
2015-01-21 21:28:26 +00:00
|
|
|
return nil, nil
|
2015-01-15 08:16:34 +00:00
|
|
|
}
|
2015-01-15 19:20:22 +00:00
|
|
|
|
|
|
|
func (s *HTTPServer) AgentNodeMaintenance(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
|
|
|
// Only PUT supported
|
|
|
|
if req.Method != "PUT" {
|
|
|
|
resp.WriteHeader(405)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure we have some action
|
|
|
|
params := req.URL.Query()
|
|
|
|
if _, ok := params["enable"]; !ok {
|
|
|
|
resp.WriteHeader(400)
|
Use fmt.Fprint/Fprintf/Fprintln
Used the following rewrite rules:
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c, d))) -> fmt.Fprintf(resp, a, b, c, d)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c))) -> fmt.Fprintf(resp, a, b, c)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b))) -> fmt.Fprintf(resp, a, b)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a))) -> fmt.Fprint(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a + "\n")) -> fmt.Fprintln(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a)) -> fmt.Fprint(resp, a)' *.go
2017-04-20 14:07:42 +00:00
|
|
|
fmt.Fprint(resp, "Missing value for enable")
|
2015-01-15 19:20:22 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
raw := params.Get("enable")
|
2015-01-21 17:53:31 +00:00
|
|
|
enable, err := strconv.ParseBool(raw)
|
|
|
|
if err != nil {
|
2015-01-15 19:20:22 +00:00
|
|
|
resp.WriteHeader(400)
|
Use fmt.Fprint/Fprintf/Fprintln
Used the following rewrite rules:
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c, d))) -> fmt.Fprintf(resp, a, b, c, d)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c))) -> fmt.Fprintf(resp, a, b, c)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b))) -> fmt.Fprintf(resp, a, b)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a))) -> fmt.Fprint(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a + "\n")) -> fmt.Fprintln(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a)) -> fmt.Fprint(resp, a)' *.go
2017-04-20 14:07:42 +00:00
|
|
|
fmt.Fprintf(resp, "Invalid value for enable: %q", raw)
|
2015-01-15 19:20:22 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2016-12-14 22:16:46 +00:00
|
|
|
// Get the provided token, if any, and vet against any ACL policies.
|
2015-09-10 18:43:59 +00:00
|
|
|
var token string
|
|
|
|
s.parseToken(req, &token)
|
2016-12-14 22:16:46 +00:00
|
|
|
acl, err := s.agent.resolveToken(token)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if acl != nil && !acl.NodeWrite(s.agent.config.NodeName) {
|
2017-04-21 00:02:42 +00:00
|
|
|
return nil, errPermissionDenied
|
2016-12-14 22:16:46 +00:00
|
|
|
}
|
2015-09-10 18:43:59 +00:00
|
|
|
|
2015-01-15 19:20:22 +00:00
|
|
|
if enable {
|
2015-09-10 18:43:59 +00:00
|
|
|
s.agent.EnableNodeMaintenance(params.Get("reason"), token)
|
2015-01-15 19:20:22 +00:00
|
|
|
} else {
|
|
|
|
s.agent.DisableNodeMaintenance()
|
|
|
|
}
|
2015-02-20 23:45:06 +00:00
|
|
|
s.syncChanges()
|
2015-01-15 19:20:22 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
2015-02-20 23:45:06 +00:00
|
|
|
|
2016-11-16 21:45:26 +00:00
|
|
|
func (s *HTTPServer) AgentMonitor(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
2016-12-14 17:33:57 +00:00
|
|
|
// Only GET supported.
|
2016-11-16 21:45:26 +00:00
|
|
|
if req.Method != "GET" {
|
|
|
|
resp.WriteHeader(405)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2016-12-14 17:33:57 +00:00
|
|
|
// Fetch the ACL token, if any, and enforce agent policy.
|
|
|
|
var token string
|
|
|
|
s.parseToken(req, &token)
|
|
|
|
acl, err := s.agent.resolveToken(token)
|
|
|
|
if err != nil {
|
2016-11-28 21:08:31 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
2016-12-14 17:33:57 +00:00
|
|
|
if acl != nil && !acl.AgentRead(s.agent.config.NodeName) {
|
2017-04-21 00:02:42 +00:00
|
|
|
return nil, errPermissionDenied
|
2016-12-14 17:33:57 +00:00
|
|
|
}
|
2016-11-28 21:08:31 +00:00
|
|
|
|
2016-12-14 17:33:57 +00:00
|
|
|
// Get the provided loglevel.
|
2016-11-16 21:45:26 +00:00
|
|
|
logLevel := req.URL.Query().Get("loglevel")
|
|
|
|
if logLevel == "" {
|
|
|
|
logLevel = "INFO"
|
|
|
|
}
|
|
|
|
|
2016-12-14 17:33:57 +00:00
|
|
|
// Upper case the level since that's required by the filter.
|
2016-11-16 21:45:26 +00:00
|
|
|
logLevel = strings.ToUpper(logLevel)
|
|
|
|
|
2016-12-14 17:33:57 +00:00
|
|
|
// Create a level filter and flusher.
|
2016-11-16 21:45:26 +00:00
|
|
|
filter := logger.LevelFilter()
|
|
|
|
filter.MinLevel = logutils.LogLevel(logLevel)
|
|
|
|
if !logger.ValidateLevelFilter(filter.MinLevel, filter) {
|
|
|
|
resp.WriteHeader(400)
|
Use fmt.Fprint/Fprintf/Fprintln
Used the following rewrite rules:
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c, d))) -> fmt.Fprintf(resp, a, b, c, d)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c))) -> fmt.Fprintf(resp, a, b, c)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b))) -> fmt.Fprintf(resp, a, b)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a))) -> fmt.Fprint(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a + "\n")) -> fmt.Fprintln(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a)) -> fmt.Fprint(resp, a)' *.go
2017-04-20 14:07:42 +00:00
|
|
|
fmt.Fprintf(resp, "Unknown log level: %s", filter.MinLevel)
|
2016-11-16 21:45:26 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
flusher, ok := resp.(http.Flusher)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("Streaming not supported")
|
|
|
|
}
|
|
|
|
|
2016-12-14 17:33:57 +00:00
|
|
|
// Set up a log handler.
|
2016-11-16 21:45:26 +00:00
|
|
|
handler := &httpLogHandler{
|
|
|
|
filter: filter,
|
|
|
|
logCh: make(chan string, 512),
|
2017-05-19 09:53:41 +00:00
|
|
|
logger: s.agent.logger,
|
2016-11-16 21:45:26 +00:00
|
|
|
}
|
2017-05-19 15:51:39 +00:00
|
|
|
s.agent.LogWriter.RegisterHandler(handler)
|
|
|
|
defer s.agent.LogWriter.DeregisterHandler(handler)
|
2016-11-16 21:45:26 +00:00
|
|
|
notify := resp.(http.CloseNotifier).CloseNotify()
|
|
|
|
|
2016-12-14 17:33:57 +00:00
|
|
|
// Stream logs until the connection is closed.
|
2016-11-16 21:45:26 +00:00
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-notify:
|
2017-05-19 15:51:39 +00:00
|
|
|
s.agent.LogWriter.DeregisterHandler(handler)
|
2016-11-28 21:08:31 +00:00
|
|
|
if handler.droppedCount > 0 {
|
|
|
|
s.agent.logger.Printf("[WARN] agent: Dropped %d logs during monitor request", handler.droppedCount)
|
|
|
|
}
|
2016-11-16 21:45:26 +00:00
|
|
|
return nil, nil
|
|
|
|
case log := <-handler.logCh:
|
Use fmt.Fprint/Fprintf/Fprintln
Used the following rewrite rules:
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c, d))) -> fmt.Fprintf(resp, a, b, c, d)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b, c))) -> fmt.Fprintf(resp, a, b, c)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a, b))) -> fmt.Fprintf(resp, a, b)' *.go
gofmt -w -r 'resp.Write([]byte(fmt.Sprintf(a))) -> fmt.Fprint(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a + "\n")) -> fmt.Fprintln(resp, a)' *.go
gofmt -w -r 'resp.Write([]byte(a)) -> fmt.Fprint(resp, a)' *.go
2017-04-20 14:07:42 +00:00
|
|
|
fmt.Fprintln(resp, log)
|
2016-11-16 21:45:26 +00:00
|
|
|
flusher.Flush()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type httpLogHandler struct {
|
2016-11-28 21:08:31 +00:00
|
|
|
filter *logutils.LevelFilter
|
|
|
|
logCh chan string
|
|
|
|
logger *log.Logger
|
|
|
|
droppedCount int
|
2016-11-16 21:45:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (h *httpLogHandler) HandleLog(log string) {
|
|
|
|
// Check the log level
|
|
|
|
if !h.filter.Check([]byte(log)) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do a non-blocking send
|
|
|
|
select {
|
|
|
|
case h.logCh <- log:
|
|
|
|
default:
|
2016-11-28 21:08:31 +00:00
|
|
|
// Just increment a counter for dropped logs to this handler; we can't log now
|
|
|
|
// because the lock is already held by the LogWriter invoking this
|
2017-04-20 19:00:03 +00:00
|
|
|
h.droppedCount++
|
2016-11-16 21:45:26 +00:00
|
|
|
}
|
|
|
|
}
|
2017-07-26 18:03:43 +00:00
|
|
|
|
|
|
|
func (s *HTTPServer) AgentToken(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
|
|
|
if req.Method != "PUT" {
|
|
|
|
resp.WriteHeader(http.StatusMethodNotAllowed)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fetch the ACL token, if any, and enforce agent policy.
|
|
|
|
var token string
|
|
|
|
s.parseToken(req, &token)
|
|
|
|
acl, err := s.agent.resolveToken(token)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if acl != nil && !acl.AgentWrite(s.agent.config.NodeName) {
|
|
|
|
return nil, errPermissionDenied
|
|
|
|
}
|
|
|
|
|
|
|
|
// The body is just the token, but it's in a JSON object so we can add
|
|
|
|
// fields to this later if needed.
|
|
|
|
var args api.AgentToken
|
|
|
|
if err := decodeBody(req, &args, nil); err != nil {
|
|
|
|
resp.WriteHeader(http.StatusBadRequest)
|
|
|
|
fmt.Fprintf(resp, "Request decode failed: %v", err)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Figure out the target token.
|
|
|
|
target := strings.TrimPrefix(req.URL.Path, "/v1/agent/token/")
|
|
|
|
switch target {
|
|
|
|
case "acl_token":
|
|
|
|
s.agent.tokens.UpdateUserToken(args.Token)
|
|
|
|
|
|
|
|
case "acl_agent_token":
|
|
|
|
s.agent.tokens.UpdateAgentToken(args.Token)
|
|
|
|
|
|
|
|
case "acl_agent_master_token":
|
|
|
|
s.agent.tokens.UpdateAgentMasterToken(args.Token)
|
|
|
|
|
2017-08-03 22:39:31 +00:00
|
|
|
case "acl_replication_token":
|
|
|
|
s.agent.tokens.UpdateACLReplicationToken(args.Token)
|
|
|
|
|
2017-07-26 18:03:43 +00:00
|
|
|
default:
|
|
|
|
resp.WriteHeader(http.StatusNotFound)
|
|
|
|
fmt.Fprintf(resp, "Token %q is unknown", target)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2017-08-03 00:05:18 +00:00
|
|
|
s.agent.logger.Printf("[INFO] Updated agent's ACL token %q", target)
|
2017-07-26 18:03:43 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|