Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@

# Dependency directories (remove the comment below to include it)
# vendor/
/.idea/
14 changes: 14 additions & 0 deletions discover-eureka/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package discover_eureka


type Config struct {
Name string `json:"name"`
Driver string `json:"driver"`
Labels map[string]string
Config AccessConfig `json:"config"`
}

type AccessConfig struct {
Address []string
Params map[string]string
}
46 changes: 46 additions & 0 deletions discover-eureka/driver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package discover_eureka

import (
"errors"
"fmt"
"github.com/eolinker/eosc"
"github.com/eolinker/goku-eosc/discovery"
"reflect"
)

const (
driverName = "eureka"
)
//driver 实现github.com/eolinker/eosc.eosc.IProfessionDriver接口
type driver struct {
profession string
name string
driver string
label string
desc string
configType reflect.Type
params map[string]string
}

func (d *driver) ConfigType() reflect.Type {
return d.configType
}

func (d *driver) Create(id, name string, v interface{}, workers map[eosc.RequireId]interface{}) (eosc.IWorker, error) {
cfg, ok := v.(*Config)
if !ok {
return nil, errors.New(fmt.Sprintf("error struct type: %s, need struct type: %s", eosc.TypeNameOf(v), d.configType))
}
return &eureka{
id: id,
name: name,
address: cfg.Config.Address,
params: cfg.Config.Params,
labels: cfg.Labels,
services: discovery.NewServices(),
context: nil,
cancelFunc: nil,
}, nil

}

176 changes: 176 additions & 0 deletions discover-eureka/eureka.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package discover_eureka

import (
"context"
"encoding/xml"
"fmt"
"github.com/eolinker/eosc"
"github.com/eolinker/goku-eosc/discovery"
"io/ioutil"
"net/http"
"strings"
"time"
)

type eureka struct {
id string
name string
address []string
params map[string]string
labels map[string]string
services discovery.IServices
context context.Context
cancelFunc context.CancelFunc
}

func (e *eureka) GetApp(serviceName string) (discovery.IApp, error) {
app, err := e.Create(serviceName)
if err != nil {
return nil, err
}
err = e.services.Set(serviceName, app.Id(), app)
if err != nil {
return nil, err
}
return app, nil
}
func (e *eureka) Create(serviceName string) (discovery.IApp, error) {
nodes, err := e.GetNodeList(serviceName)
if err != nil {
return nil, err
}
attrs := make(discovery.Attrs)
app := discovery.NewApp(nil, e, attrs, nodes)
return app, nil
}

func (e *eureka) Remove(id string) error {
return e.services.Remove(id)
}

func (e *eureka) Id() string {
return e.id
}

func (e *eureka) Start() error {
ctx, cancelFunc := context.WithCancel(context.Background())
e.context = ctx
e.cancelFunc = cancelFunc
go func() {
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
EXIT:
for {
select {
case <-ctx.Done():
break EXIT
case <-ticker.C:
{
keys := e.services.AppKeys()
for _, serviceName := range keys {
res, err := e.GetNodeList(serviceName)
if err != nil {
continue
}
nodes := make([]discovery.INode, len(res))
for _, v := range res {
nodes = append(nodes, v)
}
e.services.Update(serviceName, nodes)
}
}
}

}
}()
return nil
}

func (e *eureka) Reset(conf interface{}, workers map[eosc.RequireId]interface{}) error {
cfg, ok := conf.(*Config)
if !ok {
return fmt.Errorf("need %s,now %s:%w", eosc.TypeNameOf((*Config)(nil)), eosc.TypeNameOf(conf), eosc.ErrorStructType)
}
e.address = cfg.Config.Address
e.params = cfg.Config.Params
e.labels = cfg.Labels
return nil
}

func (e *eureka) Stop() error {
e.cancelFunc()
return nil
}

func (e *eureka) CheckSkill(skill string) bool {
return discovery.CheckSkill(skill)
}

func (e *eureka) GetNodeList(serviceName string) (map[string]discovery.INode, error) {
nodes := make(map[string]discovery.INode)
for _, addr := range e.address {
// 获取每个ip中指定服务名的实例列表
app, err := e.GetApplication(addr, serviceName)
if err != nil {
return nil, err
}
for _, ins := range app.Instances {
if ins.Status != EurekaStatusUp {
continue
}
port := 0
if ins.Port.Enabled {
port = ins.Port.Port
} else if ins.SecurePort.Enabled {
port = ins.SecurePort.Port
}
label := map[string]string{
"app": ins.App,
"hostName": ins.HostName,
}
//for k, v := range ins.Metadata {
// label[k] = v
//}
node := discovery.NewNode(label, ins.InstanceID, ins.IPAddr, port)
if _, ok := nodes[node.Id()]; ok {
continue
}
nodes[node.Id()] = node
}
}
return nodes, nil
}

func (e *eureka) GetApplication(addr, serviceName string) (*Application, error) {

if !strings.Contains(addr, "http://") && !strings.Contains(addr, "https://") {
addr = fmt.Sprintf("http://%s", addr)
if v, ok := e.labels["schema"]; ok {
if v == "https" {
addr = fmt.Sprintf("https://%s", addr)
}
}
}
addr = fmt.Sprintf("%s/apps/%s", addr, serviceName)
res, err := http.Get(addr)
if err != nil {
return nil, err
}
respBody, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
err = res.Body.Close()
if err != nil {
return nil, err
}
if res.StatusCode != http.StatusOK {
return nil, err
}
var application = &Application{}
err = xml.Unmarshal(respBody, application)
if err != nil {
return nil, err
}
return application, err
}
80 changes: 80 additions & 0 deletions discover-eureka/eureka_request.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package discover_eureka
const EurekaStatusUp = "UP"

//Application application
type Application struct {
Name string `xml:"name"`
Instances []InstanceInfo `xml:"instance" json:"instance"`
}

//Instance instance
type Instance struct {
Instance *InstanceInfo `xml:"instance" json:"instance"`
}

//InstanceInfo instanceInfo
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"`
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"`
InstanceID string `xml:"instanceId" json:"instanceId"`
AppName string `xml:"appName,omitempty" json:"appName,omitempty"`
AppGroupName string `xml:"appGroupName,omitempty" json:"appGroupName,omitempty"`
}



//Port port
type Port struct {
Port int `xml:",chardata" json:"$"`
Enabled bool `xml:"enabled,attr" json:"@enabled"`
}

//DataCenterInfo dataCenterInfo
type DataCenterInfo struct {
Name string `xml:"name" json:"name"`
Class string `xml:"class,attr" json:"@class"`
Metadata *DataCenterMetadata `xml:"metadata,omitempty" json:"metadata,omitempty"`
}

//DataCenterMetadata dataCenterMetaData
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"`
}

//LeaseInfo leaseInfo
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"`
}
34 changes: 34 additions & 0 deletions discover-eureka/eureka_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package discover_eureka

import (
"fmt"
"github.com/eolinker/goku-eosc/discovery"
"testing"
)

func TestGetApp(t *testing.T) {
serviceName := "DEMO"
e := &eureka{
id: "1",
name: "eolinker",
address: []string{
"http://39.108.94.48:8761/eureka",
},
params: map[string]string{
"username": "test",
"password": "test",
},
labels: nil,
services: discovery.NewServices(),
context: nil,
cancelFunc: nil,
}

app, err := e.GetApp(serviceName)
if err!=nil {
fmt.Println("error:", err)
}
for _, node := range app.Nodes(){
fmt.Println(node.Id())
}
}
Loading