Vendor main dependencies.
This commit is contained in:
parent
49a09ab7dd
commit
dd5e3fba01
2738 changed files with 1045689 additions and 0 deletions
357
vendor/github.com/ArthurHlt/go-eureka-client/eureka/client.go
generated
vendored
Normal file
357
vendor/github.com/ArthurHlt/go-eureka-client/eureka/client.go
generated
vendored
Normal file
|
@ -0,0 +1,357 @@
|
|||
package eureka
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultBufferSize = 10
|
||||
UP = "UP"
|
||||
DOWN = "DOWN"
|
||||
STARTING = "STARTING"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
CertFile string `json:"certFile"`
|
||||
KeyFile string `json:"keyFile"`
|
||||
CaCertFile []string `json:"caCertFiles"`
|
||||
DialTimeout time.Duration `json:"timeout"`
|
||||
Consistency string `json:"consistency"`
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
Config Config `json:"config"`
|
||||
Cluster *Cluster `json:"cluster"`
|
||||
httpClient *http.Client
|
||||
persistence io.Writer
|
||||
cURLch chan string
|
||||
// CheckRetry can be used to control the policy for failed requests
|
||||
// and modify the cluster if needed.
|
||||
// The client calls it before sending requests again, and
|
||||
// stops retrying if CheckRetry returns some error. The cases that
|
||||
// this function needs to handle include no response and unexpected
|
||||
// http status code of response.
|
||||
// If CheckRetry is nil, client will call the default one
|
||||
// `DefaultCheckRetry`.
|
||||
// Argument cluster is the eureka.Cluster object that these requests have been made on.
|
||||
// Argument numReqs is the number of http.Requests that have been made so far.
|
||||
// Argument lastResp is the http.Responses from the last request.
|
||||
// Argument err is the reason of the failure.
|
||||
CheckRetry func(cluster *Cluster, numReqs int,
|
||||
lastResp http.Response, err error) error
|
||||
}
|
||||
|
||||
// NewClient create a basic client that is configured to be used
|
||||
// with the given machine list.
|
||||
func NewClient(machines []string) *Client {
|
||||
config := Config{
|
||||
// default timeout is one second
|
||||
DialTimeout: time.Second,
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
Cluster: NewCluster(machines),
|
||||
Config: config,
|
||||
}
|
||||
|
||||
client.initHTTPClient()
|
||||
return client
|
||||
}
|
||||
|
||||
// NewTLSClient create a basic client with TLS configuration
|
||||
func NewTLSClient(machines []string, cert string, key string, caCerts []string) (*Client, error) {
|
||||
// overwrite the default machine to use https
|
||||
if len(machines) == 0 {
|
||||
machines = []string{"https://127.0.0.1:4001"}
|
||||
}
|
||||
|
||||
config := Config{
|
||||
// default timeout is one second
|
||||
DialTimeout: time.Second,
|
||||
CertFile: cert,
|
||||
KeyFile: key,
|
||||
CaCertFile: make([]string, 0),
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
Cluster: NewCluster(machines),
|
||||
Config: config,
|
||||
}
|
||||
|
||||
err := client.initHTTPSClient(cert, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, caCert := range caCerts {
|
||||
if err := client.AddRootCA(caCert); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// NewClientFromFile creates a client from a given file path.
|
||||
// The given file is expected to use the JSON format.
|
||||
func NewClientFromFile(fpath string) (*Client, error) {
|
||||
fi, err := os.Open(fpath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := fi.Close(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
return NewClientFromReader(fi)
|
||||
}
|
||||
|
||||
// NewClientFromReader creates a Client configured from a given reader.
|
||||
// The configuration is expected to use the JSON format.
|
||||
func NewClientFromReader(reader io.Reader) (*Client, error) {
|
||||
c := new(Client)
|
||||
|
||||
b, err := ioutil.ReadAll(reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(b, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if c.Config.CertFile == "" {
|
||||
c.initHTTPClient()
|
||||
} else {
|
||||
err = c.initHTTPSClient(c.Config.CertFile, c.Config.KeyFile)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, caCert := range c.Config.CaCertFile {
|
||||
if err := c.AddRootCA(caCert); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Override the Client's HTTP Transport object
|
||||
func (c *Client) SetTransport(tr *http.Transport) {
|
||||
c.httpClient.Transport = tr
|
||||
}
|
||||
|
||||
// initHTTPClient initializes a HTTP client for eureka client
|
||||
func (c *Client) initHTTPClient() {
|
||||
tr := &http.Transport{
|
||||
Dial: c.dial,
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
}
|
||||
c.httpClient = &http.Client{Transport: tr}
|
||||
}
|
||||
|
||||
// initHTTPClient initializes a HTTPS client for eureka client
|
||||
func (c *Client) initHTTPSClient(cert, key string) error {
|
||||
if cert == "" || key == "" {
|
||||
return errors.New("Require both cert and key path")
|
||||
}
|
||||
|
||||
tlsCert, err := tls.LoadX509KeyPair(cert, key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tlsConfig := &tls.Config{
|
||||
Certificates: []tls.Certificate{tlsCert},
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: tlsConfig,
|
||||
Dial: c.dial,
|
||||
}
|
||||
|
||||
c.httpClient = &http.Client{Transport: tr}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sets the DialTimeout value
|
||||
func (c *Client) SetDialTimeout(d time.Duration) {
|
||||
c.Config.DialTimeout = d
|
||||
}
|
||||
|
||||
// AddRootCA adds a root CA cert for the eureka client
|
||||
func (c *Client) AddRootCA(caCert string) error {
|
||||
if c.httpClient == nil {
|
||||
return errors.New("Client has not been initialized yet!")
|
||||
}
|
||||
|
||||
certBytes, err := ioutil.ReadFile(caCert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tr, ok := c.httpClient.Transport.(*http.Transport)
|
||||
|
||||
if !ok {
|
||||
panic("AddRootCA(): Transport type assert should not fail")
|
||||
}
|
||||
|
||||
if tr.TLSClientConfig.RootCAs == nil {
|
||||
caCertPool := x509.NewCertPool()
|
||||
ok = caCertPool.AppendCertsFromPEM(certBytes)
|
||||
if ok {
|
||||
tr.TLSClientConfig.RootCAs = caCertPool
|
||||
}
|
||||
tr.TLSClientConfig.InsecureSkipVerify = false
|
||||
} else {
|
||||
ok = tr.TLSClientConfig.RootCAs.AppendCertsFromPEM(certBytes)
|
||||
}
|
||||
|
||||
if !ok {
|
||||
err = errors.New("Unable to load caCert")
|
||||
}
|
||||
|
||||
c.Config.CaCertFile = append(c.Config.CaCertFile, caCert)
|
||||
return err
|
||||
}
|
||||
|
||||
// SetCluster updates cluster information using the given machine list.
|
||||
func (c *Client) SetCluster(machines []string) bool {
|
||||
success := c.internalSyncCluster(machines)
|
||||
return success
|
||||
}
|
||||
|
||||
func (c *Client) GetCluster() []string {
|
||||
return c.Cluster.Machines
|
||||
}
|
||||
|
||||
// SyncCluster updates the cluster information using the internal machine list.
|
||||
func (c *Client) SyncCluster() bool {
|
||||
return c.internalSyncCluster(c.Cluster.Machines)
|
||||
}
|
||||
|
||||
// internalSyncCluster syncs cluster information using the given machine list.
|
||||
func (c *Client) internalSyncCluster(machines []string) bool {
|
||||
for _, machine := range machines {
|
||||
httpPath := c.createHttpPath(machine, "machines")
|
||||
resp, err := c.httpClient.Get(httpPath)
|
||||
if err != nil {
|
||||
// try another machine in the cluster
|
||||
continue
|
||||
} else {
|
||||
b, err := ioutil.ReadAll(resp.Body)
|
||||
resp.Body.Close()
|
||||
if err != nil {
|
||||
// try another machine in the cluster
|
||||
continue
|
||||
}
|
||||
|
||||
// update Machines List
|
||||
c.Cluster.updateFromStr(string(b))
|
||||
|
||||
// update leader
|
||||
// the first one in the machine list is the leader
|
||||
c.Cluster.switchLeader(0)
|
||||
|
||||
logger.Debug("sync.machines " + strings.Join(c.Cluster.Machines, ", "))
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// createHttpPath creates a complete HTTP URL.
|
||||
// serverName should contain both the host name and a port number, if any.
|
||||
func (c *Client) createHttpPath(serverName string, _path string) string {
|
||||
u, err := url.Parse(serverName)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
u.Path = path.Join(u.Path, _path)
|
||||
|
||||
if u.Scheme == "" {
|
||||
u.Scheme = "http"
|
||||
}
|
||||
return u.String()
|
||||
}
|
||||
|
||||
// dial attempts to open a TCP connection to the provided address, explicitly
|
||||
// enabling keep-alives with a one-second interval.
|
||||
func (c *Client) dial(network, addr string) (net.Conn, error) {
|
||||
conn, err := net.DialTimeout(network, addr, c.Config.DialTimeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tcpConn, ok := conn.(*net.TCPConn)
|
||||
if !ok {
|
||||
return nil, errors.New("Failed type-assertion of net.Conn as *net.TCPConn")
|
||||
}
|
||||
|
||||
// Keep TCP alive to check whether or not the remote machine is down
|
||||
if err = tcpConn.SetKeepAlive(true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = tcpConn.SetKeepAlivePeriod(time.Second); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tcpConn, nil
|
||||
}
|
||||
|
||||
// MarshalJSON implements the Marshaller interface
|
||||
// as defined by the standard JSON package.
|
||||
func (c *Client) MarshalJSON() ([]byte, error) {
|
||||
b, err := json.Marshal(struct {
|
||||
Config Config `json:"config"`
|
||||
Cluster *Cluster `json:"cluster"`
|
||||
}{
|
||||
Config: c.Config,
|
||||
Cluster: c.Cluster,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the Unmarshaller interface
|
||||
// as defined by the standard JSON package.
|
||||
func (c *Client) UnmarshalJSON(b []byte) error {
|
||||
temp := struct {
|
||||
Config Config `json:"config"`
|
||||
Cluster *Cluster `json:"cluster"`
|
||||
}{}
|
||||
err := json.Unmarshal(b, &temp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.Cluster = temp.Cluster
|
||||
c.Config = temp.Config
|
||||
return nil
|
||||
}
|
51
vendor/github.com/ArthurHlt/go-eureka-client/eureka/cluster.go
generated
vendored
Normal file
51
vendor/github.com/ArthurHlt/go-eureka-client/eureka/cluster.go
generated
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
package eureka
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Cluster struct {
|
||||
Leader string `json:"leader"`
|
||||
Machines []string `json:"machines"`
|
||||
}
|
||||
|
||||
func NewCluster(machines []string) *Cluster {
|
||||
// if an empty slice was sent in then just assume HTTP 4001 on localhost
|
||||
if len(machines) == 0 {
|
||||
machines = []string{"http://127.0.0.1:4001"}
|
||||
}
|
||||
|
||||
// default leader and machines
|
||||
return &Cluster{
|
||||
Leader: machines[0],
|
||||
Machines: machines,
|
||||
}
|
||||
}
|
||||
|
||||
// switchLeader switch the current leader to machines[num]
|
||||
func (cl *Cluster) switchLeader(num int) {
|
||||
logger.Debug("switch.leader[from %v to %v]",
|
||||
cl.Leader, cl.Machines[num])
|
||||
|
||||
cl.Leader = cl.Machines[num]
|
||||
}
|
||||
|
||||
func (cl *Cluster) updateFromStr(machines string) {
|
||||
cl.Machines = strings.Split(machines, ", ")
|
||||
}
|
||||
|
||||
func (cl *Cluster) updateLeader(leader string) {
|
||||
logger.Debug("update.leader[%s,%s]", cl.Leader, leader)
|
||||
cl.Leader = leader
|
||||
}
|
||||
|
||||
func (cl *Cluster) updateLeaderFromURL(u *url.URL) {
|
||||
var leader string
|
||||
if u.Scheme == "" {
|
||||
leader = "http://" + u.Host
|
||||
} else {
|
||||
leader = u.Scheme + "://" + u.Host
|
||||
}
|
||||
cl.updateLeader(leader)
|
||||
}
|
21
vendor/github.com/ArthurHlt/go-eureka-client/eureka/debug.go
generated
vendored
Normal file
21
vendor/github.com/ArthurHlt/go-eureka-client/eureka/debug.go
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
package eureka
|
||||
|
||||
import (
|
||||
"github.com/ArthurHlt/gominlog"
|
||||
"log"
|
||||
)
|
||||
|
||||
var logger *gominlog.MinLog
|
||||
|
||||
func GetLogger() *log.Logger {
|
||||
return logger.GetLogger()
|
||||
}
|
||||
|
||||
func SetLogger(loggerLog *log.Logger) {
|
||||
logger.SetLogger(loggerLog)
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Default logger uses the go default log.
|
||||
logger = gominlog.NewClassicMinLogWithPackageName("go-eureka-client")
|
||||
}
|
10
vendor/github.com/ArthurHlt/go-eureka-client/eureka/delete.go
generated
vendored
Normal file
10
vendor/github.com/ArthurHlt/go-eureka-client/eureka/delete.go
generated
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
package eureka
|
||||
|
||||
import "strings"
|
||||
|
||||
func (c *Client) UnregisterInstance(appId, instanceId string) error {
|
||||
values := []string{"apps", appId, instanceId}
|
||||
path := strings.Join(values, "/")
|
||||
_, err := c.Delete(path)
|
||||
return err
|
||||
}
|
48
vendor/github.com/ArthurHlt/go-eureka-client/eureka/error.go
generated
vendored
Normal file
48
vendor/github.com/ArthurHlt/go-eureka-client/eureka/error.go
generated
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
package eureka
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const (
|
||||
ErrCodeEurekaNotReachable = 501
|
||||
)
|
||||
|
||||
var (
|
||||
errorMap = map[int]string{
|
||||
ErrCodeEurekaNotReachable: "All the given peers are not reachable",
|
||||
}
|
||||
)
|
||||
|
||||
type EurekaError struct {
|
||||
ErrorCode int `json:"errorCode"`
|
||||
Message string `json:"message"`
|
||||
Cause string `json:"cause,omitempty"`
|
||||
Index uint64 `json:"index"`
|
||||
}
|
||||
|
||||
func (e EurekaError) Error() string {
|
||||
return fmt.Sprintf("%v: %v (%v) [%v]", e.ErrorCode, e.Message, e.Cause, e.Index)
|
||||
}
|
||||
|
||||
func newError(errorCode int, cause string, index uint64) *EurekaError {
|
||||
return &EurekaError{
|
||||
ErrorCode: errorCode,
|
||||
Message: errorMap[errorCode],
|
||||
Cause: cause,
|
||||
Index: index,
|
||||
}
|
||||
}
|
||||
|
||||
func handleError(b []byte) error {
|
||||
eurekaErr := new(EurekaError)
|
||||
|
||||
err := json.Unmarshal(b, eurekaErr)
|
||||
if err != nil {
|
||||
logger.Warning("cannot unmarshal eureka error: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return eurekaErr
|
||||
}
|
38
vendor/github.com/ArthurHlt/go-eureka-client/eureka/get.go
generated
vendored
Normal file
38
vendor/github.com/ArthurHlt/go-eureka-client/eureka/get.go
generated
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
package eureka
|
||||
import (
|
||||
"encoding/xml"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (c *Client) GetApplications() (*Applications, error) {
|
||||
response, err := c.Get("apps");
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var applications *Applications = new(Applications)
|
||||
err = xml.Unmarshal(response.Body, applications)
|
||||
return applications, err
|
||||
}
|
||||
|
||||
func (c *Client) GetApplication(appId string) (*Application, error) {
|
||||
values := []string{"apps", appId}
|
||||
path := strings.Join(values, "/")
|
||||
response, err := c.Get(path);
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var application *Application = new(Application)
|
||||
err = xml.Unmarshal(response.Body, application)
|
||||
return application, err
|
||||
}
|
||||
func (c *Client) GetInstance(appId, instanceId string) (*InstanceInfo, error) {
|
||||
values := []string{"apps", appId, instanceId}
|
||||
path := strings.Join(values, "/")
|
||||
response, err := c.Get(path);
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var instance *InstanceInfo = new(InstanceInfo)
|
||||
err = xml.Unmarshal(response.Body, instance)
|
||||
return instance, err
|
||||
}
|
95
vendor/github.com/ArthurHlt/go-eureka-client/eureka/metadata_marshaller.go
generated
vendored
Normal file
95
vendor/github.com/ArthurHlt/go-eureka-client/eureka/metadata_marshaller.go
generated
vendored
Normal file
|
@ -0,0 +1,95 @@
|
|||
package eureka
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"encoding/json"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
type MetaData struct {
|
||||
Map map[string]string
|
||||
Class string
|
||||
}
|
||||
|
||||
|
||||
type Vraw struct {
|
||||
Content []byte `xml:",innerxml"`
|
||||
Class string `xml:"class,attr" json:"@class"`
|
||||
}
|
||||
|
||||
func (s *MetaData) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
|
||||
var attributes []xml.Attr = make([]xml.Attr, 0)
|
||||
if s.Class != "" {
|
||||
attributes = append(attributes, xml.Attr{
|
||||
Name: xml.Name{
|
||||
Local: "class",
|
||||
},
|
||||
Value: s.Class,
|
||||
})
|
||||
}
|
||||
start.Attr = attributes
|
||||
tokens := []xml.Token{start}
|
||||
|
||||
for key, value := range s.Map {
|
||||
t := xml.StartElement{Name: xml.Name{"", key}}
|
||||
tokens = append(tokens, t, xml.CharData(value), xml.EndElement{t.Name})
|
||||
}
|
||||
|
||||
tokens = append(tokens, xml.EndElement{
|
||||
Name: start.Name,
|
||||
})
|
||||
|
||||
|
||||
for _, t := range tokens {
|
||||
err := e.EncodeToken(t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// flush to ensure tokens are written
|
||||
err := e.Flush()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *MetaData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
s.Map = make(map[string]string)
|
||||
vraw := &Vraw{}
|
||||
d.DecodeElement(vraw, &start)
|
||||
dataInString := string(vraw.Content)
|
||||
regex, err := regexp.Compile("\\s*<([^<>]+)>([^<>]+)</[^<>]+>\\s*")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
subMatches := regex.FindAllStringSubmatch(dataInString, -1)
|
||||
for _, subMatch := range subMatches {
|
||||
s.Map[subMatch[1]] = subMatch[2]
|
||||
}
|
||||
s.Class = vraw.Class
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *MetaData) MarshalJSON() ([]byte, error) {
|
||||
mapIt := make(map[string]string)
|
||||
for key, value := range s.Map {
|
||||
mapIt[key] = value
|
||||
}
|
||||
if s.Class != "" {
|
||||
mapIt["@class"] = s.Class
|
||||
}
|
||||
return json.Marshal(mapIt)
|
||||
}
|
||||
func (s *MetaData) UnmarshalJSON(data []byte) error {
|
||||
dataUnmarshal := make(map[string]string)
|
||||
err := json.Unmarshal(data, dataUnmarshal)
|
||||
s.Map = dataUnmarshal
|
||||
if val, ok := s.Map["@class"]; ok {
|
||||
s.Class = val
|
||||
delete(s.Map, "@class")
|
||||
}
|
||||
return err
|
||||
}
|
21
vendor/github.com/ArthurHlt/go-eureka-client/eureka/post.go
generated
vendored
Normal file
21
vendor/github.com/ArthurHlt/go-eureka-client/eureka/post.go
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
package eureka
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (c *Client) RegisterInstance(appId string, instanceInfo *InstanceInfo) error {
|
||||
values := []string{"apps", appId}
|
||||
path := strings.Join(values, "/")
|
||||
instance := &Instance{
|
||||
Instance: instanceInfo,
|
||||
}
|
||||
body, err := json.Marshal(instance)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = c.Post(path, body)
|
||||
return err
|
||||
}
|
10
vendor/github.com/ArthurHlt/go-eureka-client/eureka/put.go
generated
vendored
Normal file
10
vendor/github.com/ArthurHlt/go-eureka-client/eureka/put.go
generated
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
package eureka
|
||||
|
||||
import "strings"
|
||||
|
||||
func (c *Client) SendHeartbeat(appId, instanceId string) error {
|
||||
values := []string{"apps", appId, instanceId}
|
||||
path := strings.Join(values, "/")
|
||||
_, err := c.Put(path, nil)
|
||||
return err
|
||||
}
|
437
vendor/github.com/ArthurHlt/go-eureka-client/eureka/requests.go
generated
vendored
Normal file
437
vendor/github.com/ArthurHlt/go-eureka-client/eureka/requests.go
generated
vendored
Normal file
|
@ -0,0 +1,437 @@
|
|||
package eureka
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
"time"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Errors introduced by handling requests
|
||||
var (
|
||||
ErrRequestCancelled = errors.New("sending request is cancelled")
|
||||
)
|
||||
|
||||
type RawRequest struct {
|
||||
method string
|
||||
relativePath string
|
||||
body []byte
|
||||
cancel <-chan bool
|
||||
}
|
||||
type Applications struct {
|
||||
VersionsDelta int `xml:"versions__delta"`
|
||||
AppsHashcode string `xml:"apps__hashcode"`
|
||||
Applications []Application `xml:"application,omitempty"`
|
||||
}
|
||||
type Application struct {
|
||||
Name string `xml:"name"`
|
||||
Instances []InstanceInfo `xml:"instance"`
|
||||
}
|
||||
type Instance struct {
|
||||
Instance *InstanceInfo `xml:"instance" json:"instance"`
|
||||
}
|
||||
type Port struct {
|
||||
Port int `xml:",chardata" json:"$"`
|
||||
Enabled bool `xml:"enabled,attr" json:"@enabled"`
|
||||
}
|
||||
type InstanceInfo struct {
|
||||
HostName string `xml:"hostName" json:"hostName"`
|
||||
HomePageUrl string `xml:"homePageUrl,omitempty" json:"homePageUrl,omitempty"`
|
||||
StatusPageUrl string `xml:"statusPageUrl" json:"statusPageUrl"`
|
||||
HealthCheckUrl string `xml:"healthCheckUrl,omitempty" json:"healthCheckUrl,omitempty"`
|
||||
App string `xml:"app" json:"app"`
|
||||
IpAddr string `xml:"ipAddr" json:"ipAddr"`
|
||||
VipAddress string `xml:"vipAddress" json:"vipAddress"`
|
||||
secureVipAddress string `xml:"secureVipAddress,omitempty" json:"secureVipAddress,omitempty"`
|
||||
Status string `xml:"status" json:"status"`
|
||||
Port *Port `xml:"port,omitempty" json:"port,omitempty"`
|
||||
SecurePort *Port `xml:"securePort,omitempty" json:"securePort,omitempty"`
|
||||
DataCenterInfo *DataCenterInfo `xml:"dataCenterInfo" json:"dataCenterInfo"`
|
||||
LeaseInfo *LeaseInfo `xml:"leaseInfo,omitempty" json:"leaseInfo,omitempty"`
|
||||
Metadata *MetaData `xml:"metadata,omitempty" json:"metadata,omitempty"`
|
||||
IsCoordinatingDiscoveryServer bool `xml:"isCoordinatingDiscoveryServer,omitempty" json:"isCoordinatingDiscoveryServer,omitempty"`
|
||||
LastUpdatedTimestamp int `xml:"lastUpdatedTimestamp,omitempty" json:"lastUpdatedTimestamp,omitempty"`
|
||||
LastDirtyTimestamp int `xml:"lastDirtyTimestamp,omitempty" json:"lastDirtyTimestamp,omitempty"`
|
||||
ActionType string `xml:"actionType,omitempty" json:"actionType,omitempty"`
|
||||
Overriddenstatus string `xml:"overriddenstatus,omitempty" json:"overriddenstatus,omitempty"`
|
||||
CountryId int `xml:"countryId,omitempty" json:"countryId,omitempty"`
|
||||
|
||||
}
|
||||
type DataCenterInfo struct {
|
||||
Name string `xml:"name" json:"name"`
|
||||
Class string `xml:"class,attr" json:"@class"`
|
||||
Metadata DataCenterMetadata `xml:"metadata,omitempty" json:"metadata,omitempty"`
|
||||
}
|
||||
|
||||
type DataCenterMetadata struct {
|
||||
AmiLaunchIndex string `xml:"ami-launch-index,omitempty" json:"ami-launch-index,omitempty"`
|
||||
LocalHostname string `xml:"local-hostname,omitempty" json:"local-hostname,omitempty"`
|
||||
AvailabilityZone string `xml:"availability-zone,omitempty" json:"availability-zone,omitempty"`
|
||||
InstanceId string `xml:"instance-id,omitempty" json:"instance-id,omitempty"`
|
||||
PublicIpv4 string `xml:"public-ipv4,omitempty" json:"public-ipv4,omitempty"`
|
||||
PublicHostname string `xml:"public-hostname,omitempty" json:"public-hostname,omitempty"`
|
||||
AmiManifestPath string `xml:"ami-manifest-path,omitempty" json:"ami-manifest-path,omitempty"`
|
||||
LocalIpv4 string `xml:"local-ipv4,omitempty" json:"local-ipv4,omitempty"`
|
||||
Hostname string `xml:"hostname,omitempty" json:"hostname,omitempty"`
|
||||
AmiId string `xml:"ami-id,omitempty" json:"ami-id,omitempty"`
|
||||
InstanceType string `xml:"instance-type,omitempty" json:"instance-type,omitempty"`
|
||||
}
|
||||
|
||||
type LeaseInfo struct {
|
||||
EvictionDurationInSecs uint `xml:"evictionDurationInSecs,omitempty" json:"evictionDurationInSecs,omitempty"`
|
||||
RenewalIntervalInSecs int `xml:"renewalIntervalInSecs,omitempty" json:"renewalIntervalInSecs,omitempty"`
|
||||
DurationInSecs int `xml:"durationInSecs,omitempty" json:"durationInSecs,omitempty"`
|
||||
RegistrationTimestamp int `xml:"registrationTimestamp,omitempty" json:"registrationTimestamp,omitempty"`
|
||||
LastRenewalTimestamp int `xml:"lastRenewalTimestamp,omitempty" json:"lastRenewalTimestamp,omitempty"`
|
||||
EvictionTimestamp int `xml:"evictionTimestamp,omitempty" json:"evictionTimestamp,omitempty"`
|
||||
ServiceUpTimestamp int `xml:"serviceUpTimestamp,omitempty" json:"serviceUpTimestamp,omitempty"`
|
||||
}
|
||||
|
||||
func NewRawRequest(method, relativePath string, body []byte, cancel <-chan bool) *RawRequest {
|
||||
return &RawRequest{
|
||||
method: method,
|
||||
relativePath: relativePath,
|
||||
body: body,
|
||||
cancel: cancel,
|
||||
}
|
||||
}
|
||||
|
||||
func NewInstanceInfo(hostName, app, ip string, port int, ttl uint, isSsl bool) *InstanceInfo {
|
||||
dataCenterInfo := &DataCenterInfo{
|
||||
Name: "MyOwn",
|
||||
}
|
||||
leaseInfo := &LeaseInfo{
|
||||
EvictionDurationInSecs: ttl,
|
||||
}
|
||||
instanceInfo := &InstanceInfo{
|
||||
HostName: hostName,
|
||||
App: app,
|
||||
IpAddr: ip,
|
||||
Status: UP,
|
||||
DataCenterInfo: dataCenterInfo,
|
||||
LeaseInfo: leaseInfo,
|
||||
Metadata: nil,
|
||||
}
|
||||
stringPort := ""
|
||||
if (port != 80 && port != 443) {
|
||||
stringPort = ":" + strconv.Itoa(port)
|
||||
}
|
||||
var protocol string = "http"
|
||||
if (isSsl) {
|
||||
protocol = "https"
|
||||
instanceInfo.secureVipAddress = protocol + "://" + hostName + stringPort
|
||||
instanceInfo.SecurePort = &Port{
|
||||
Port: port,
|
||||
Enabled: true,
|
||||
}
|
||||
}else {
|
||||
instanceInfo.VipAddress = protocol + "://" + hostName + stringPort
|
||||
instanceInfo.Port = &Port{
|
||||
Port: port,
|
||||
Enabled: true,
|
||||
}
|
||||
}
|
||||
instanceInfo.StatusPageUrl = protocol + "://" + hostName + stringPort + "/info"
|
||||
return instanceInfo
|
||||
}
|
||||
|
||||
// getCancelable issues a cancelable GET request
|
||||
func (c *Client) getCancelable(endpoint string,
|
||||
cancel <-chan bool) (*RawResponse, error) {
|
||||
logger.Debug("get %s [%s]", endpoint, c.Cluster.Leader)
|
||||
p := endpoint
|
||||
|
||||
req := NewRawRequest("GET", p, nil, cancel)
|
||||
resp, err := c.SendRequest(req)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// get issues a GET request
|
||||
func (c *Client) Get(endpoint string) (*RawResponse, error) {
|
||||
return c.getCancelable(endpoint, nil)
|
||||
}
|
||||
|
||||
// put issues a PUT request
|
||||
func (c *Client) Put(endpoint string, body []byte) (*RawResponse, error) {
|
||||
|
||||
logger.Debug("put %s, %s, [%s]", endpoint, body, c.Cluster.Leader)
|
||||
p := endpoint
|
||||
|
||||
req := NewRawRequest("PUT", p, body, nil)
|
||||
resp, err := c.SendRequest(req)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// post issues a POST request
|
||||
func (c *Client) Post(endpoint string, body []byte) (*RawResponse, error) {
|
||||
logger.Debug("post %s, %s, [%s]", endpoint, body, c.Cluster.Leader)
|
||||
p := endpoint
|
||||
|
||||
req := NewRawRequest("POST", p, body, nil)
|
||||
resp, err := c.SendRequest(req)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// delete issues a DELETE request
|
||||
func (c *Client) Delete(endpoint string) (*RawResponse, error) {
|
||||
logger.Debug("delete %s [%s]", endpoint, c.Cluster.Leader)
|
||||
p := endpoint
|
||||
|
||||
req := NewRawRequest("DELETE", p, nil, nil)
|
||||
resp, err := c.SendRequest(req)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c *Client) SendRequest(rr *RawRequest) (*RawResponse, error) {
|
||||
|
||||
var req *http.Request
|
||||
var resp *http.Response
|
||||
var httpPath string
|
||||
var err error
|
||||
var respBody []byte
|
||||
|
||||
var numReqs = 1
|
||||
|
||||
checkRetry := c.CheckRetry
|
||||
if checkRetry == nil {
|
||||
checkRetry = DefaultCheckRetry
|
||||
}
|
||||
|
||||
cancelled := make(chan bool, 1)
|
||||
reqLock := new(sync.Mutex)
|
||||
|
||||
if rr.cancel != nil {
|
||||
cancelRoutine := make(chan bool)
|
||||
defer close(cancelRoutine)
|
||||
|
||||
go func() {
|
||||
select {
|
||||
case <-rr.cancel:
|
||||
cancelled <- true
|
||||
logger.Debug("send.request is cancelled")
|
||||
case <-cancelRoutine:
|
||||
return
|
||||
}
|
||||
|
||||
// Repeat canceling request until this thread is stopped
|
||||
// because we have no idea about whether it succeeds.
|
||||
for {
|
||||
reqLock.Lock()
|
||||
c.httpClient.Transport.(*http.Transport).CancelRequest(req)
|
||||
reqLock.Unlock()
|
||||
|
||||
select {
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
case <-cancelRoutine:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// If we connect to a follower and consistency is required, retry until
|
||||
// we connect to a leader
|
||||
sleep := 25 * time.Millisecond
|
||||
maxSleep := time.Second
|
||||
|
||||
for attempt := 0;; attempt++ {
|
||||
if attempt > 0 {
|
||||
select {
|
||||
case <-cancelled:
|
||||
return nil, ErrRequestCancelled
|
||||
case <-time.After(sleep):
|
||||
sleep = sleep * 2
|
||||
if sleep > maxSleep {
|
||||
sleep = maxSleep
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.Debug("Connecting to eureka: attempt %d for %s", attempt + 1, rr.relativePath)
|
||||
|
||||
httpPath = c.getHttpPath(false, rr.relativePath)
|
||||
|
||||
logger.Debug("send.request.to %s | method %s", httpPath, rr.method)
|
||||
|
||||
req, err := func() (*http.Request, error) {
|
||||
reqLock.Lock()
|
||||
defer reqLock.Unlock()
|
||||
|
||||
if req, err = http.NewRequest(rr.method, httpPath, bytes.NewReader(rr.body)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type",
|
||||
"application/json")
|
||||
return req, nil
|
||||
}()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err = c.httpClient.Do(req)
|
||||
defer func() {
|
||||
if resp != nil {
|
||||
resp.Body.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
// If the request was cancelled, return ErrRequestCancelled directly
|
||||
select {
|
||||
case <-cancelled:
|
||||
return nil, ErrRequestCancelled
|
||||
default:
|
||||
}
|
||||
|
||||
numReqs++
|
||||
|
||||
// network error, change a machine!
|
||||
if err != nil {
|
||||
logger.Error("network error: %v", err.Error())
|
||||
lastResp := http.Response{}
|
||||
if checkErr := checkRetry(c.Cluster, numReqs, lastResp, err); checkErr != nil {
|
||||
return nil, checkErr
|
||||
}
|
||||
|
||||
c.Cluster.switchLeader(attempt % len(c.Cluster.Machines))
|
||||
continue
|
||||
}
|
||||
|
||||
// if there is no error, it should receive response
|
||||
logger.Debug("recv.response.from "+httpPath)
|
||||
|
||||
if validHttpStatusCode[resp.StatusCode] {
|
||||
// try to read byte code and break the loop
|
||||
respBody, err = ioutil.ReadAll(resp.Body)
|
||||
if err == nil {
|
||||
logger.Debug("recv.success "+ httpPath)
|
||||
break
|
||||
}
|
||||
// ReadAll error may be caused due to cancel request
|
||||
select {
|
||||
case <-cancelled:
|
||||
return nil, ErrRequestCancelled
|
||||
default:
|
||||
}
|
||||
|
||||
if err == io.ErrUnexpectedEOF {
|
||||
// underlying connection was closed prematurely, probably by timeout
|
||||
// TODO: empty body or unexpectedEOF can cause http.Transport to get hosed;
|
||||
// this allows the client to detect that and take evasive action. Need
|
||||
// to revisit once code.google.com/p/go/issues/detail?id=8648 gets fixed.
|
||||
respBody = []byte{}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// if resp is TemporaryRedirect, set the new leader and retry
|
||||
if resp.StatusCode == http.StatusTemporaryRedirect {
|
||||
u, err := resp.Location()
|
||||
|
||||
if err != nil {
|
||||
logger.Warning("%v", err)
|
||||
} else {
|
||||
// Update cluster leader based on redirect location
|
||||
// because it should point to the leader address
|
||||
c.Cluster.updateLeaderFromURL(u)
|
||||
logger.Debug("recv.response.relocate "+ u.String())
|
||||
}
|
||||
resp.Body.Close()
|
||||
continue
|
||||
}
|
||||
|
||||
if checkErr := checkRetry(c.Cluster, numReqs, *resp,
|
||||
errors.New("Unexpected HTTP status code")); checkErr != nil {
|
||||
return nil, checkErr
|
||||
}
|
||||
resp.Body.Close()
|
||||
}
|
||||
|
||||
r := &RawResponse{
|
||||
StatusCode: resp.StatusCode,
|
||||
Body: respBody,
|
||||
Header: resp.Header,
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// DefaultCheckRetry defines the retrying behaviour for bad HTTP requests
|
||||
// If we have retried 2 * machine number, stop retrying.
|
||||
// If status code is InternalServerError, sleep for 200ms.
|
||||
func DefaultCheckRetry(cluster *Cluster, numReqs int, lastResp http.Response,
|
||||
err error) error {
|
||||
|
||||
if numReqs >= 2 * len(cluster.Machines) {
|
||||
return newError(ErrCodeEurekaNotReachable,
|
||||
"Tried to connect to each peer twice and failed", 0)
|
||||
}
|
||||
|
||||
code := lastResp.StatusCode
|
||||
if code == http.StatusInternalServerError {
|
||||
time.Sleep(time.Millisecond * 200)
|
||||
|
||||
}
|
||||
|
||||
logger.Warning("bad response status code %d", code)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) getHttpPath(random bool, s ...string) string {
|
||||
var machine string
|
||||
if random {
|
||||
machine = c.Cluster.Machines[rand.Intn(len(c.Cluster.Machines))]
|
||||
} else {
|
||||
machine = c.Cluster.Leader
|
||||
}
|
||||
|
||||
fullPath := machine
|
||||
for _, seg := range s {
|
||||
fullPath += "/" + seg
|
||||
}
|
||||
|
||||
return fullPath
|
||||
}
|
||||
|
||||
// buildValues builds a url.Values map according to the given value and ttl
|
||||
func buildValues(value string, ttl uint64) url.Values {
|
||||
v := url.Values{}
|
||||
|
||||
if value != "" {
|
||||
v.Set("value", value)
|
||||
}
|
||||
|
||||
if ttl > 0 {
|
||||
v.Set("ttl", fmt.Sprintf("%v", ttl))
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
21
vendor/github.com/ArthurHlt/go-eureka-client/eureka/response.go
generated
vendored
Normal file
21
vendor/github.com/ArthurHlt/go-eureka-client/eureka/response.go
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
package eureka
|
||||
|
||||
import "net/http"
|
||||
|
||||
type RawResponse struct {
|
||||
StatusCode int
|
||||
Body []byte
|
||||
Header http.Header
|
||||
}
|
||||
|
||||
var (
|
||||
validHttpStatusCode = map[int]bool{
|
||||
http.StatusNoContent: true,
|
||||
http.StatusCreated: true,
|
||||
http.StatusOK: true,
|
||||
http.StatusBadRequest: true,
|
||||
http.StatusNotFound: true,
|
||||
http.StatusPreconditionFailed: true,
|
||||
http.StatusForbidden: true,
|
||||
}
|
||||
)
|
3
vendor/github.com/ArthurHlt/go-eureka-client/eureka/version.go
generated
vendored
Normal file
3
vendor/github.com/ArthurHlt/go-eureka-client/eureka/version.go
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
package eureka
|
||||
|
||||
const version = "v2"
|
Loading…
Add table
Add a link
Reference in a new issue