fargo

package module
Version: v1.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 14, 2021 License: MIT Imports: 21 Imported by: 74

README

fargo

Netflix Eureka client in golang. Named for the show Eureka.

c = fargo.NewConn("http://127.0.0.1:8080/eureka/v2")
c.GetApps() // returns a map[String]fargo.Application

Testing

Tests can be executed using docker container. See the below section to build and start all the required containers. Once the Eureka containers are running, and fargo image is built then you can run the command as follows:

Run:

docker run --rm -v "$PWD":/go/src/github.com/hudl/fargo -w /go/src/github.com/hudl/fargo hudloss/fargo:master go test -v ./...

Note: If you are running bash for Windows add MSYS_NO_PATHCONV=1 at the beginning.

The tests may need to be run a couple of times to allow changes to propagate between the two Eureka servers. If the tests are failing, try running them again approximately 30 seconds later.

If you are adding new packages to godep you may want to update the hudloss/fargo image first.

Known Issues

Until this PR is in an official vagrant release, the Fedora 19 opscode box will fail when setting up private networks in vagrant 1.2.5 and later.

FAQ

Q: Is this a full client?

A: Not yet. It's very much a work in progress, and it's also being built with consideration for Go idioms, which means some Java-isms will never be included.

Q: Does it cache?

A: No, it does not support caching records.

Q: Can I integrate this into my Go app and have it manage hearbeats to Eureka?

A: Glad you asked, of course you can. Just grab an application (for this example, "TESTAPP")

// register a couple instances, and then set up to only heartbeat one of them
e, _ := fargo.NewConnFromConfigFile("/etc/fargo.gcfg")
app, _ := e.GetApp("TESTAPP")
// starts a goroutine that updates the application on poll interval
e.UpdateApp(&app)
for {
    for _, ins := range app.Instances {
        fmt.Printf("%s, ", ins.HostName)
    }
    fmt.Println(len(app.Instances))
    <-time.After(10 * time.Second)
}
// You'll see all the instances at first, and within a minute or two all the
// ones that aren't heartbeating will disappear from the list. Note that after
// calling `UpdateApp` there's no need to manually update

TODO

  • Actually do something with AWS availability zone info
  • Currently the load balancing is random, and does not give preference to servers within a zone.
  • Make releases available on gopkg.in

Hacking

Just Let Me Import Already

go get github.com/hudl/fargo


package main

import (
    "github.com/hudl/fargo"
)

func main() {
    e, _ := fargo.NewConnFromConfigFile("/etc/fargo.gcfg")
    e.AppWatchChannel
}

Adding Stuff

go test is your friend. I use the excellent goconvey library in addition to the standard lib's testing package. If you add something, write a test. If something is broken, write a test that reproduces your issue or post repro steps to the issues on this repository. The tests require that you have a eureka install and are designed to run against the included vagrant specs.

Verifying Releases

We're on semver and tag releases accordingly. The releases are signed and can be verified with git tag --verify vA.B.C.

Using Docker

Fargo is tested against two eureka versions, v1.1.147 and v1.3.1. To support testing, we provide Docker containers that supply Eureka locally. Here's how to get started.

  1. Clone Fargo
  2. If you don't have it, install Docker.
# Defaults to 1.1.147, can be set to 1.3.1
EUREKA_VERSION=1.1.147

cp docker-compose.override.yml.dist docker-compose.override.yml

docker-compose up -d

# Run the tests

Contributors

  • Ryan S. Brown (ryansb)
  • Carl Quinn (cquinn)

MIT License

The MIT License (MIT). Please see License File for more information.

Documentation

Index

Examples

Constants

View Source
const (
	Amazon = "Amazon"
	MyOwn  = "MyOwn"
)

Datacenter names

Variables

View Source
var ErrNotInAWS = fmt.Errorf("Not in AWS")
View Source
var EurekaURLSlugs = map[string]string{
	"Apps":                        "apps",
	"Instances":                   "instances",
	"InstancesByVIPAddress":       "vips",
	"InstancesBySecureVIPAddress": "svips",
}

EurekaURLSlugs is a map of resource names->Eureka URLs.

View Source
var HttpClient = &http.Client{
	Transport: transport,
	Timeout:   30 * time.Second,
}

Functions

func HTTPResponseStatusCode

func HTTPResponseStatusCode(err error) (code int, present bool)

HTTPResponseStatusCode extracts the HTTP status code for the response from Eureka that motivated the supplied error, if any. If the returned present value is true, the returned code is an HTTP status code.

func Shuffled

func Shuffled(o *instanceQueryOptions) error

Shuffled requests randomizing the order of the sequence of instances returned, using the default shared rand.Source.

func ThatAreUp

func ThatAreUp(o *instanceQueryOptions) error

ThatAreUp restricts the set of instances returned to only those with status UP.

Combining this function with the options produced by WithStatus applies their logical disjunction.

Types

type AmazonMetadataType

type AmazonMetadataType struct {
	AmiLaunchIndex   string `xml:"ami-launch-index" json:"ami-launch-index"`
	LocalHostname    string `xml:"local-hostname" json:"local-hostname"`
	AvailabilityZone string `xml:"availability-zone" json:"availability-zone"`
	InstanceID       string `xml:"instance-id" json:"instance-id"`
	PublicIpv4       string `xml:"public-ipv4" json:"public-ipv4"`
	PublicHostname   string `xml:"public-hostname" json:"public-hostname"`
	AmiManifestPath  string `xml:"ami-manifest-path" json:"ami-manifest-path"`
	LocalIpv4        string `xml:"local-ipv4" json:"local-ipv4"`
	HostName         string `xml:"hostname" json:"hostname"`
	AmiID            string `xml:"ami-id" json:"ami-id"`
	InstanceType     string `xml:"instance-type" json:"instance-type"`
}

AmazonMetadataType is information about AZ's, AMI's, and the AWS instance. <xsd:complexType name="amazonMetdataType"> from http://docs.amazonwebservices.com/AWSEC2/latest/DeveloperGuide/index.html?AESDG-chapter-instancedata.html

type AppNotFoundError

type AppNotFoundError struct {
	// contains filtered or unexported fields
}

func (AppNotFoundError) Error

func (e AppNotFoundError) Error() string

type AppSource

type AppSource struct {
	// contains filtered or unexported fields
}

An AppSource holds a periodically updated copy of a Eureka application.

func (*AppSource) CopyLatestTo

func (s *AppSource) CopyLatestTo(dst *Application) bool

CopyLatestTo copies the most recently acquired Eureka application to dst, if any, and returns true if such an application was available. If no preceding update attempt had succeeded, such that no application is available to be copied, it returns false.

Example
e := makeConnection()
name := "my_app"
source := e.NewAppSource(name, true)
defer source.Stop()
var app fargo.Application
if !source.CopyLatestTo(&app) {
	fmt.Printf("No application named %q is available.\n", name)
}
time.Sleep(time.Minute)
if source.CopyLatestTo(&app) {
	fmt.Printf("Application %q has %d instances.\n", name, len(app.Instances))
}
Output:

func (*AppSource) Latest

func (s *AppSource) Latest() *Application

Latest returns the most recently acquired Eureka application, if any. If the most recent update attempt failed, or if no update attempt has yet to complete, it returns nil.

Example
e := makeConnection()
name := "my_app"
source := e.NewAppSource(name, false)
defer source.Stop()
time.Sleep(30 * time.Second)
if app := source.Latest(); app != nil {
	fmt.Printf("Application %q has %d instances.\n", name, len(app.Instances))
}
time.Sleep(time.Minute)
if app := source.Latest(); app == nil {
	fmt.Printf("No application named %q is available.\n", name)
}
Output:

func (*AppSource) Stop

func (s *AppSource) Stop()

Stop turns off an AppSource, so that it will no longer attempt to update its latest application.

It is safe to call Latest or CopyLatestTo on a stopped source.

type AppUpdate

type AppUpdate struct {
	App *Application
	Err error
}

AppUpdate is the outcome of an attempt to get a fresh snapshot of a Eureka application's state, together with an error that may have occurred in that attempt. If the Err field is nil, the App field will be non-nil.

type Application

type Application struct {
	Name      string      `xml:"name" json:"name"`
	Instances []*Instance `xml:"instance" json:"instance"`
}

Application deserializeable from Eureka XML.

func (*Application) ParseAllMetadata

func (a *Application) ParseAllMetadata() error

ParseAllMetadata iterates through all instances in an application

func (*Application) UnmarshalJSON

func (a *Application) UnmarshalJSON(b []byte) error

UnmarshalJSON is a custom JSON unmarshaler for Application to deal with sometimes non-wrapped Instance array when there is only a single Instance item.

type Config

type Config struct {
	AWS    aws
	Eureka eureka
}

Config is a base struct to be read by code.google.com/p/gcfg

func ReadConfig

func ReadConfig(loc string) (conf Config, err error)

ReadConfig from a file location. Minimal error handling. Just bails and passes up an error if the file isn't found

type DataCenterInfo

type DataCenterInfo struct {
	// Name indicates which type of data center hosts this instance.
	Name string
	// Class indicates the Java class name representing this structure in the Eureka server,
	// noted only when encoding communication with JSON.
	//
	// When registering an instance, if the name is neither "Amazon" nor "MyOwn", this field's
	// value is used. Otherwise, a suitable default value will be supplied to the server. This field
	// is available for specifying custom data center types other than the two built-in ones, for
	// which no suitable default value could be known.
	Class string
	// Metadata provides details specific to an Amazon data center,
	// populated and honored when the Name field's value is "Amazon".
	Metadata AmazonMetadataType
	// AlternateMetadata provides details specific to a data center other than Amazon,
	// populated and honored when the Name field's value is not "Amazon".
	AlternateMetadata map[string]string
}

DataCenterInfo indicates which type of data center hosts this instance and conveys details about the instance's environment.

func (*DataCenterInfo) MarshalJSON

func (i *DataCenterInfo) MarshalJSON() ([]byte, error)

MarshalJSON is a custom JSON marshaler for DataCenterInfo, writing either Metadata or AlternateMetadata depending on the type of data center indicated by the Name.

func (*DataCenterInfo) MarshalXML

func (i *DataCenterInfo) MarshalXML(e *xml.Encoder, start xml.StartElement) error

MarshalXML is a custom XML marshaler for DataCenterInfo, writing either Metadata or AlternateMetadata depending on the type of data center indicated by the Name.

func (*DataCenterInfo) UnmarshalJSON

func (i *DataCenterInfo) UnmarshalJSON(b []byte) error

UnmarshalJSON is a custom JSON unmarshaler for DataCenterInfo, populating either Metadata or AlternateMetadata depending on the type of data center indicated by the Name.

func (*DataCenterInfo) UnmarshalXML

func (i *DataCenterInfo) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML is a custom XML unmarshaler for DataCenterInfo, populating either Metadata or AlternateMetadata depending on the type of data center indicated by the Name.

type EurekaConnection

type EurekaConnection struct {
	ServiceUrls    []string
	ServicePort    int
	ServerURLBase  string
	Timeout        time.Duration
	PollInterval   time.Duration
	PreferSameZone bool
	Retries        int
	DNSDiscovery   bool
	DiscoveryZone  string

	UseJson bool
	// contains filtered or unexported fields
}

EurekaConnection is the settings required to make Eureka requests.

func NewConn

func NewConn(address ...string) (e EurekaConnection)

NewConn is a default connection with just a list of ServiceUrls. Most basic way to make a new connection. Generally only if you know what you're doing and are going to do the configuration yourself some other way.

func NewConnFromConfig

func NewConnFromConfig(conf Config) (c EurekaConnection)

NewConnFromConfig will, given a Config struct, return a connection based on those options

func NewConnFromConfigFile

func NewConnFromConfigFile(location string) (c EurekaConnection, err error)

NewConnFromConfigFile sets up a connection object based on a config in specified path

func (EurekaConnection) AddMetadataString

func (e EurekaConnection) AddMetadataString(ins *Instance, key, value string) error

AddMetadataString to a given instance. Is immediately sent to Eureka server.

func (*EurekaConnection) DeregisterInstance

func (e *EurekaConnection) DeregisterInstance(ins *Instance) error

DeregisterInstance will deregister the given Instance from eureka. This is good practice to do before exiting or otherwise going off line.

func (*EurekaConnection) GetApp

func (e *EurekaConnection) GetApp(name string) (*Application, error)

GetApp returns a single eureka application by name

func (*EurekaConnection) GetApps

func (e *EurekaConnection) GetApps() (map[string]*Application, error)

GetApps returns a map of all Applications

func (*EurekaConnection) GetInstance

func (e *EurekaConnection) GetInstance(app, insId string) (*Instance, error)

GetInstance gets an Instance from eureka given its app and instanceid.

func (*EurekaConnection) GetInstancesByVIPAddress

func (e *EurekaConnection) GetInstancesByVIPAddress(addr string, secure bool, opts ...InstanceQueryOption) ([]*Instance, error)

GetInstancesByVIPAddress returns the set of instances registered with the given VIP address, selecting either an insecure or secure VIP address with the given name, potentially filtered per the constraints supplied as options.

NB: The VIP address is case-sensitive, and must match the address used at registration time.

func (*EurekaConnection) HeartBeatInstance

func (e *EurekaConnection) HeartBeatInstance(ins *Instance) error

HeartBeatInstance sends a single eureka heartbeat. Does not continue sending heartbeats. Errors if the response is not 200.

func (*EurekaConnection) NewAppSource

func (e *EurekaConnection) NewAppSource(name string, await bool) *AppSource

NewAppSource returns a new AppSource that offers a periodically updated copy of the Eureka application with the given name, using the connection's configured polling interval as its period.

If await is true, it waits for the first application update to complete before returning, though it's possible that that first update attempt could fail, so that a subsequent call to Latest would return nil and CopyLatestTo would return false.

func (*EurekaConnection) NewInstanceSetSourceForApp

func (e *EurekaConnection) NewInstanceSetSourceForApp(name string, await bool, opts ...InstanceQueryOption) (*InstanceSetSource, error)

NewInstanceSetSourceForApp returns a new InstantSetSource that offers a periodically updated set of instances from the Eureka application with the given name, potentially filtered per the constraints supplied as options, using the connection's configured polling interval as its period.

If await is true, it waits for the first instance set update to complete before returning, though it's possible that that first update attempt could fail, so that a subsequent call to Latest would return nil.

It returns an error if any of the supplied options are invalid, precluding it from scheduling the intended updates.

func (*EurekaConnection) NewInstanceSetSourceForVIPAddress

func (e *EurekaConnection) NewInstanceSetSourceForVIPAddress(addr string, secure bool, await bool, opts ...InstanceQueryOption) (*InstanceSetSource, error)

NewInstanceSetSourceForVIPAddress returns a new InstantSetSource that offers a periodically updated set of instances registered with the given Eureka VIP address, selecting either an insecure or secure VIP address with the given name, potentially filtered per the constraints supplied as options, using the connection's configured polling interval as its period.

If await is true, it waits for the first instance set update to complete before returning, though it's possible that that first update attempt could fail, so that a subsequent call to Latest would return nil.

It returns an error if any of the supplied options are invalid, precluding it from scheduling the intended updates.

func (*EurekaConnection) RegisterInstance

func (e *EurekaConnection) RegisterInstance(ins *Instance) error

RegisterInstance will register the given Instance with eureka if it is not already registered, but DOES NOT automatically send heartbeats. See HeartBeatInstance for that functionality

func (*EurekaConnection) ReregisterInstance

func (e *EurekaConnection) ReregisterInstance(ins *Instance) error

ReregisterInstance will register the given Instance with eureka but DOES NOT automatically send heartbeats. See HeartBeatInstance for that functionality

func (*EurekaConnection) ScheduleAppInstanceUpdates

func (e *EurekaConnection) ScheduleAppInstanceUpdates(name string, await bool, done <-chan struct{}, opts ...InstanceQueryOption) (<-chan InstanceSetUpdate, error)

ScheduleAppInstanceUpdates starts polling for updates to the set of instances from the Eureka application with the given name, potentially filtered per the constraints supplied as options, using the connection's configured polling interval as its period. It sends the outcome of each update attempt to the returned channel, and continues until the supplied done channel is either closed or has a value available. Once done sending updates to the returned channel, it closes it.

If await is true, it sends at least one instance set update outcome to the returned channel before returning.

It returns an error if any of the supplied options are invalid, precluding it from scheduling the intended updates.

Example
e := makeConnection()
done := make(chan struct{})
time.AfterFunc(2*time.Minute, func() {
	close(done)
})
name := "my_app"
updates, err := e.ScheduleAppInstanceUpdates(name, true, done, fargo.ThatAreUp, fargo.Shuffled)
if err != nil {
	fmt.Println(err)
	return
}
fmt.Printf("Monitoring instances of application %q.\n", name)
for update := range updates {
	if update.Err != nil {
		fmt.Printf("Most recent request for application %q failed: %v\n", name, update.Err)
		continue
	}
	fmt.Printf("Application %q has %d instances available.\n", name, len(update.Instances))
}
fmt.Printf("Done monitoring instances of application %q.\n", name)
Output:

func (*EurekaConnection) ScheduleAppUpdates

func (e *EurekaConnection) ScheduleAppUpdates(name string, await bool, done <-chan struct{}) <-chan AppUpdate

ScheduleAppUpdates starts polling for updates to the Eureka application with the given name, using the connection's configured polling interval as its period. It sends the outcome of each update attempt to the returned channel, and continues until the supplied done channel is either closed or has a value available. Once done sending updates to the returned channel, it closes it.

If await is true, it sends at least one application update outcome to the returned channel before returning.

Example
e := makeConnection()
done := make(chan struct{})
time.AfterFunc(2*time.Minute, func() {
	close(done)
})
name := "my_app"
fmt.Printf("Monitoring application %q.\n", name)
for update := range e.ScheduleAppUpdates(name, true, done) {
	if update.Err != nil {
		fmt.Printf("Most recent request for application %q failed: %v\n", name, update.Err)
		continue
	}
	fmt.Printf("Application %q has %d instances.\n", name, len(update.App.Instances))
}
fmt.Printf("Done monitoring application %q.\n", name)
Output:

func (*EurekaConnection) ScheduleVIPAddressUpdates

func (e *EurekaConnection) ScheduleVIPAddressUpdates(addr string, secure bool, await bool, done <-chan struct{}, opts ...InstanceQueryOption) (<-chan InstanceSetUpdate, error)

ScheduleVIPAddressUpdates starts polling for updates to the set of instances registered with the given Eureka VIP address, selecting either an insecure or secure VIP address with the given name, potentially filtered per the constraints supplied as options, using the connection's configured polling interval as its period. It sends the outcome of each update attempt to the returned channel, and continues until the supplied done channel is either closed or has a value available. Once done sending updates to the returned channel, it closes it.

If await is true, it sends at least one instance set update outcome to the returned channel before returning.

It returns an error if any of the supplied options are invalid, precluding it from scheduling the intended updates.

Example (Context)
e := makeConnection()
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
vipAddress := "my_vip"
// Look for instances that are in trouble.
updates, err := e.ScheduleVIPAddressUpdates(vipAddress, false, true, ctx.Done(), fargo.WithStatus(fargo.DOWN), fargo.WithStatus(fargo.OUTOFSERVICE))
if err != nil {
	fmt.Println(err)
	return
}
fmt.Printf("Monitoring VIP address %q.\n", vipAddress)
for update := range updates {
	if update.Err != nil {
		fmt.Printf("Most recent request for VIP address %q's instances failed: %v\n", vipAddress, update.Err)
		continue
	}
	fmt.Printf("VIP address %q has %d instances in trouble.\n", vipAddress, len(update.Instances))
}
fmt.Printf("Done monitoring VIP address %q.\n", vipAddress)
Output:

Example (Manual)
e := makeConnection()
done := make(chan struct{})
time.AfterFunc(2*time.Minute, func() {
	close(done)
})
vipAddress := "my_vip"
// We only care about those instances that are available to receive requests.
updates, err := e.ScheduleVIPAddressUpdates(vipAddress, false, true, done, fargo.ThatAreUp, fargo.Shuffled)
if err != nil {
	fmt.Println(err)
	return
}
fmt.Printf("Monitoring VIP address %q.\n", vipAddress)
for update := range updates {
	if update.Err != nil {
		fmt.Printf("Most recent request for VIP address %q's instances failed: %v\n", vipAddress, update.Err)
		continue
	}
	fmt.Printf("VIP address %q has %d instances available.\n", vipAddress, len(update.Instances))
}
fmt.Printf("Done monitoring VIP address %q.\n", vipAddress)
Output:

func (*EurekaConnection) SelectServiceURL

func (e *EurekaConnection) SelectServiceURL() string

SelectServiceURL gets a eureka instance based on the connection's load balancing scheme. TODO: Make this not just pick a random one.

func (*EurekaConnection) UpdateApp

func (e *EurekaConnection) UpdateApp(app *Application)

UpdateApp creates a goroutine that continues to keep an application updated with its status in Eureka.

func (EurekaConnection) UpdateInstanceStatus

func (e EurekaConnection) UpdateInstanceStatus(ins *Instance, status StatusType) error

UpdateInstanceStatus updates the status of a given instance with eureka.

type GetAppResponseJson

type GetAppResponseJson struct {
	Application Application `json:"application"`
}

GetAppResponseJson wraps an Application for deserializing from Eureka JSON.

type GetAppsResponse

type GetAppsResponse struct {
	Applications  []*Application `xml:"application" json:"application"`
	AppsHashcode  string         `xml:"apps__hashcode" json:"apps__hashcode"`
	VersionsDelta int            `xml:"versions__delta" json:"versions__delta"`
}

GetAppsResponse lets us deserialize the eureka/v2/apps response XML.

func (*GetAppsResponse) UnmarshalJSON

func (r *GetAppsResponse) UnmarshalJSON(b []byte) error

UnmarshalJSON is a custom JSON unmarshaler for GetAppsResponse to deal with sometimes non-wrapped Application arrays when there is only a single Application item.

type GetAppsResponseJson

type GetAppsResponseJson struct {
	Response *GetAppsResponse `json:"applications"`
}

GetAppsResponseJson lets us deserialize the eureka/v2/apps response JSON—a wrapped GetAppsResponse.

type Instance

type Instance struct {
	InstanceId       string `xml:"instanceId" json:"instanceId"`
	HostName         string `xml:"hostName" json:"hostName"`
	App              string `xml:"app" json:"app"`
	IPAddr           string `xml:"ipAddr" json:"ipAddr"`
	VipAddress       string `xml:"vipAddress" json:"vipAddress"`
	SecureVipAddress string `xml:"secureVipAddress" json:"secureVipAddress"`

	Status           StatusType `xml:"status" json:"status"`
	Overriddenstatus StatusType `xml:"overriddenstatus" json:"overriddenstatus"`

	Port              int  `xml:"-" json:"-"`
	PortEnabled       bool `xml:"-" json:"-"`
	SecurePort        int  `xml:"-" json:"-"`
	SecurePortEnabled bool `xml:"-" json:"-"`

	HomePageUrl    string `xml:"homePageUrl" json:"homePageUrl"`
	StatusPageUrl  string `xml:"statusPageUrl" json:"statusPageUrl"`
	HealthCheckUrl string `xml:"healthCheckUrl" json:"healthCheckUrl"`

	CountryId      int64          `xml:"countryId" json:"countryId"`
	DataCenterInfo DataCenterInfo `xml:"dataCenterInfo" json:"dataCenterInfo"`

	LeaseInfo LeaseInfo        `xml:"leaseInfo" json:"leaseInfo"`
	Metadata  InstanceMetadata `xml:"metadata" json:"metadata"`

	UniqueID func(i Instance) string `xml:"-" json:"-"`
}

Instance [de]serializeable [to|from] Eureka [XML|JSON].

func (*Instance) Id

func (i *Instance) Id() string

func (*Instance) MarshalJSON

func (i *Instance) MarshalJSON() ([]byte, error)

MarshalJSON is a custom JSON marshaler for Instance, adapting the top-level raw port values to the composite port specifications.

func (*Instance) MarshalXML

func (i *Instance) MarshalXML(e *xml.Encoder, start xml.StartElement) error

MarshalXML is a custom XML marshaler for Instance, adapting the top-level raw port values to the composite port specifications.

func (*Instance) SetMetadataString

func (ins *Instance) SetMetadataString(key, value string)

SetMetadataString for a given instance before register

func (*Instance) UnmarshalJSON

func (i *Instance) UnmarshalJSON(b []byte) error

UnmarshalJSON is a custom JSON unmarshaler for Instance, transcribing the two composite port specifications up to top-level fields.

func (*Instance) UnmarshalXML

func (i *Instance) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML is a custom XML unmarshaler for Instance, transcribing the two composite port specifications up to top-level fields.

type InstanceMetadata

type InstanceMetadata struct {
	Raw []byte `xml:",innerxml" json:"-"`
	// contains filtered or unexported fields
}

InstanceMetadata represents the eureka metadata, which is arbitrary XML. See metadata.go for more info.

func (*InstanceMetadata) GetBool

func (im *InstanceMetadata) GetBool(key string) (b bool, err error)

GetBool pulls a value cast as bool. Swallows panics from type assertion and returns false + an error if conversion fails

func (*InstanceMetadata) GetFloat32

func (im *InstanceMetadata) GetFloat32(key string) (f float32, err error)

GetFloat32 pulls a value cast as float. Swallows panics from type assertion and returns 0.0 + an error if conversion fails

func (*InstanceMetadata) GetFloat64

func (im *InstanceMetadata) GetFloat64(key string) (f float64, err error)

GetFloat64 pulls a value cast as float. Swallows panics from type assertion and returns 0.0 + an error if conversion fails

func (*InstanceMetadata) GetInt

func (im *InstanceMetadata) GetInt(key string) (i int, err error)

GetInt pulls a value cast as int. Swallows panics from type assertion and returns 0 + an error if conversion fails

func (*InstanceMetadata) GetMap

func (im *InstanceMetadata) GetMap() map[string]interface{}

GetMap returns a map of the metadata parameters for this instance

func (*InstanceMetadata) GetString

func (im *InstanceMetadata) GetString(key string) (s string, err error)

GetString pulls a value cast as a string. Swallows panics from type assertion and returns empty string + an error if conversion fails

func (*InstanceMetadata) MarshalJSON

func (i *InstanceMetadata) MarshalJSON() ([]byte, error)

MarshalJSON is a custom JSON marshaler for InstanceMetadata.

func (InstanceMetadata) MarshalXML

func (i InstanceMetadata) MarshalXML(e *xml.Encoder, start xml.StartElement) error

MarshalXML is a custom XML marshaler for InstanceMetadata.

func (*InstanceMetadata) UnmarshalJSON

func (i *InstanceMetadata) UnmarshalJSON(b []byte) error

UnmarshalJSON is a custom JSON unmarshaler for InstanceMetadata to handle squirreling away the raw JSON for later parsing.

type InstanceQueryOption

type InstanceQueryOption func(*instanceQueryOptions) error

InstanceQueryOption is a customization supplied to instance query functions like GetInstancesByVIPAddress to tailor the set of instances returned.

func ShuffledWith

func ShuffledWith(r *rand.Rand) InstanceQueryOption

ShuffledWith requests randomizing the order of the sequence of instances returned, using the supplied source of random numbers.

func WithStatus

func WithStatus(status StatusType) InstanceQueryOption

WithStatus restricts the set of instances returned to only those with the given status.

Supplying multiple options produced by this function applies their logical disjunction.

type InstanceSetSource

type InstanceSetSource struct {
	// contains filtered or unexported fields
}

An InstanceSetSource holds a periodically updated set of instances registered with Eureka.

func (*InstanceSetSource) Latest

func (s *InstanceSetSource) Latest() []*Instance

Latest returns the most recently acquired set of Eureka instances, if any. If the most recent update attempt failed, or if no update attempt has yet to complete, it returns nil.

Note that if the most recent update attempt was successful but resulted in no instances, it returns a non-nil empty slice.

Example (App)
e := makeConnection()
name := "my_app"
source, err := e.NewInstanceSetSourceForApp(name, true, fargo.ThatAreUp, fargo.Shuffled)
if err != nil {
	fmt.Println(err)
	return
}
defer source.Stop()
for remaining := 10; ; {
	if instances := source.Latest(); len(instances) > 0 {
		instance := instances[0]
		// Assume the insecure port is enabled.
		fmt.Printf("Chose service %s:%d for application %q.\n", instance.IPAddr, instance.Port, name)
	}
	remaining--
	if remaining == 0 {
		break
	}
	time.Sleep(30 * time.Second)
}
Output:

Example (Compare)
e := makeConnection()
svipAddress := "my_vip"
source, err := e.NewInstanceSetSourceForVIPAddress(svipAddress, true, true, fargo.WithStatus(fargo.DOWN), fargo.WithStatus(fargo.OUTOFSERVICE))
if err != nil {
	fmt.Println(err)
	return
}
defer source.Stop()
var troubled []*fargo.Instance
for remaining := 10; ; {
	if instances := source.Latest(); instances != nil {
		fmt.Printf("VIP address %q has %d troubled instances.", svipAddress, len(instances))
		switch diff := len(instances) - len(troubled); {
		case diff > 0:
			fmt.Printf(" (%d more than last time)\n", diff)
		case diff < 0:
			fmt.Printf(" (%d fewer than last time)\n", diff)
		default:
			fmt.Println()
		}
		troubled = instances
	}
	remaining--
	if remaining == 0 {
		break
	}
	time.Sleep(30 * time.Second)
}
Output:

Example (Outcomes)
e := makeConnection()
vipAddress := "my_vip"
source, err := e.NewInstanceSetSourceForVIPAddress(vipAddress, false, false, fargo.ThatAreUp)
if err != nil {
	fmt.Println(err)
	return
}
defer source.Stop()
time.Sleep(30 * time.Second)
if instances := source.Latest(); instances != nil {
	fmt.Printf("VIP address %q has %d instances available.\n", vipAddress, len(instances))
}
time.Sleep(time.Minute)
switch instances := source.Latest(); {
case instances == nil:
	fmt.Printf("Unsure whether any instances for VIP address %q are available.\n", vipAddress)
case len(instances) == 0:
	fmt.Printf("No instances for VIP address %q are available.\n", vipAddress)
default:
	fmt.Printf("VIP address %q has %d instances available.\n", vipAddress, len(instances))
}
Output:

func (*InstanceSetSource) Stop

func (s *InstanceSetSource) Stop()

Stop turns off an InstantSetSource, so that it will no longer attempt to update its latest set of Eureka instances.

It is safe to call Latest or CopyLatestTo on a stopped source.

type InstanceSetUpdate

type InstanceSetUpdate struct {
	Instances []*Instance
	Err       error
}

InstanceSetUpdate is the outcome of an attempt to get a fresh snapshot of a Eureka VIP address's set of instances, together with an error that may have occurred in that attempt. If the Err field is nil, the Instances field will be populated—though possibly with an empty set.

type LeaseInfo

type LeaseInfo struct {
	RenewalIntervalInSecs int32 `xml:"renewalIntervalInSecs" json:"renewalIntervalInSecs"`
	DurationInSecs        int32 `xml:"durationInSecs" json:"durationInSecs"`
	RegistrationTimestamp int64 `xml:"registrationTimestamp" json:"registrationTimestamp"`
	LastRenewalTimestamp  int64 `xml:"lastRenewalTimestamp" json:"lastRenewalTimestamp"`
	EvictionTimestamp     int64 `xml:"evictionTimestamp" json:"evictionTimestamp"`
	ServiceUpTimestamp    int64 `xml:"serviceUpTimestamp" json:"serviceUpTimestamp"`
}

LeaseInfo tells us about the renewal from Eureka, including how old it is.

type PreliminaryDataCenterInfo

type PreliminaryDataCenterInfo struct {
	Name     string      `xml:"name" json:"name"`
	Class    string      `xml:"-" json:"@class"`
	Metadata metadataMap `xml:"metadata" json:"metadata"`
}

type RegisterInstanceJson

type RegisterInstanceJson struct {
	Instance *Instance `json:"instance"`
}

RegisterInstanceJson lets us serialize the eureka/v2/apps/<ins> request JSON—a wrapped Instance.

type StatusType

type StatusType string

StatusType is an enum of the different statuses allowed by Eureka.

const (
	UP           StatusType = "UP"
	DOWN         StatusType = "DOWN"
	STARTING     StatusType = "STARTING"
	OUTOFSERVICE StatusType = "OUT_OF_SERVICE"
	UNKNOWN      StatusType = "UNKNOWN"
)

Supported statuses

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
t or T : Toggle theme light dark auto
y or Y : Canonical URL