-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwarden.go
143 lines (111 loc) · 4.36 KB
/
warden.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package warden
import (
"fmt"
"time"
"strings"
// "strconv"
"gopkg.in/redis.v3"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/aws/ec2metadata"
// "os/exec"
)
// Warden holds basic instance data plus redis clients for both global service management and intra-host load-balancing.
type Warden struct {
region string
availabilityZone string
instanceId string
services []*ServiceDescription
redisServiceManagement *redis.Client
redisLocal *redis.Client
}
const MaxHeartbeatAge = 300
const GuardTime = 15
const ActivityPause = 300
const ServiceManagerPause = 30
const CandidateExpiry = 30
func wardenLog(s string) {
fmt.Printf("warden: %s\n", s)
} // WardenLog
// Start will run both the registrar and manager co-routines.
func (warden *Warden) Start() {
wardenLog("starting...")
// fetch some runtime constants:
// get instance ID
// get current availability zone
warden.region, warden.availabilityZone, warden.instanceId = warden.getInstanceIdentity(wardenLog)
wardenLog(fmt.Sprintf("region is %s, availability zone is %s, instance ID is %s", warden.region, warden.availabilityZone, warden.instanceId))
configReader := NewConfigurationReader("config.json")
configuration := configReader.Read()
var serviceDescriptionReader ServiceDescriptionReader
serviceDescriptionReader = NewFileServiceDescriptionReader(configuration.ServiceDescriptionFilename)
warden.services = (serviceDescriptionReader).Read()
if warden.ourAvailabilityZoneIsActive(wardenLog) {
wardenLog("our availability zone is active")
} else {
wardenLog("our availability zone is not active!")
}
warden.redisServiceManagement = redis.NewClient(&redis.Options{
Addr: configuration.ServiceManagementRedisAddress,
Password: "",
DB: configuration.ServiceManagementRedisDatabaseNumber,
})
warden.redisLocal = redis.NewClient(&redis.Options{
Addr: configuration.NginxRedisAddress,
Password: "",
DB: configuration.NginxRedisDatabaseNumber,
})
// start registrar coroutine
go warden.startRegistrar(func(s string) { fmt.Printf("registrar: %s\n", s) }, configuration)
// start manager coroutine
warden.startManager(func(s string) { fmt.Printf("manager: %s\n", s) }, configuration)
fmt.Println("Warden finishing...")
} // main
func (warden *Warden) ourAvailabilityZoneIsActive(logger func(s string)) bool {
return warden.availabilityZoneIsActive(logger, warden.availabilityZone)
} // ourAvailabilityZoneIsActive
func (warden *Warden) getActiveAvailabilityZones(logger func(s string)) []string {
logger("getActiveAvailabilityZones")
svc := ec2.New(session.New(), &aws.Config{Region: aws.String(warden.region)})
resp, err := svc.DescribeAvailabilityZones(nil)
if err != nil {
logger(fmt.Sprintf("error: %s", err))
return nil
}
var zones []string
for _, az := range resp.AvailabilityZones {
if *az.State == "available" {
zones = append(zones, *az.ZoneName)
}
}
logger(fmt.Sprintf("active availability zones: %s", strings.Join(zones, ", ")))
return zones
} // getActiveAvailabilityZones
func (warden *Warden) getTimeDifference(logger func(s string), t1 string, t2 string) int {
time1, _ := time.Parse(time.RFC3339, t1)
time2, _ := time.Parse(time.RFC3339, t2)
duration := time2.Sub(time1)
return int(duration.Seconds())
} // getTimeDifference
func (warden *Warden) getInstanceIdentity(logger func(s string)) (string, string, string) {
logger("getting instance identity")
m := ec2metadata.New(session.New())
doc, err := m.GetInstanceIdentityDocument()
if err != nil {
panic(err)
}
return doc.Region, doc.AvailabilityZone, doc.InstanceID
} // getInstanceIdentity
func (warden *Warden) availabilityZoneIsActive(logger func(s string), z string) bool {
// get list of active availability zones
activeZones := warden.getActiveAvailabilityZones(logger)
if activeZones != nil {
for _, v := range activeZones {
if v == z {
return true
}
}
}
return false
} // availabilityZoneIsActive