-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathposture.go
More file actions
130 lines (111 loc) · 3.18 KB
/
Copy pathposture.go
File metadata and controls
130 lines (111 loc) · 3.18 KB
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
package capstan
import (
"encoding/json"
"fmt"
)
type Geography string
const (
GeoEUCentral Geography = "eu-central"
GeoEUNorth Geography = "eu-north"
GeoEUWest Geography = "eu-west"
GeoEUSouth Geography = "eu-south"
GeoUSEast Geography = "us-east"
GeoUSCentral Geography = "us-central"
GeoUSWest Geography = "us-west"
GeoCanada Geography = "canada"
GeoSingapore Geography = "singapore"
GeoJapan Geography = "japan"
GeoIndia Geography = "india"
GeoIndonesia Geography = "indonesia"
GeoAustralia Geography = "australia"
GeoLatam Geography = "latam"
)
type Workload string
const (
WorkloadIOMultitenant Workload = "io-multitenant"
WorkloadCPULatency Workload = "cpu-latency"
WorkloadCPUThroughput Workload = "cpu-throughput"
WorkloadGeneral Workload = "general"
)
type SlaTier string
const (
SLABestEffort SlaTier = "best-effort"
SLAStandard SlaTier = "standard"
SLAPremium SlaTier = "premium"
)
type Placement struct {
Provider ProviderName `json:"provider"`
Region string `json:"region"`
Size string `json:"size"`
}
type Recommendation struct {
Primary Placement `json:"primary"`
Fallbacks []Placement `json:"fallbacks"`
Caveats []string `json:"caveats"`
}
type postureData struct {
GeoRouting map[Geography][]regionCandidate `json:"geoRouting"`
TierMap map[ProviderName]map[Workload]map[SlaTier]string `json:"tierMap"`
CellCaveats map[string][]string `json:"cellCaveats"`
SizeCaveats map[string][]string `json:"sizeCaveats"`
}
type regionCandidate struct {
Provider ProviderName `json:"provider"`
Region string `json:"region"`
}
var posture postureData
func init() {
if err := json.Unmarshal(postureSpecData, &posture); err != nil {
panic("capstan: bad embedded posture spec: " + err.Error())
}
}
func RecommendPlacement(geography Geography, workload Workload, sla SlaTier) (*Recommendation, error) {
if workload == "" {
workload = WorkloadIOMultitenant
}
if sla == "" {
sla = SLAStandard
}
candidates, ok := posture.GeoRouting[geography]
if !ok || len(candidates) == 0 {
return nil, fmt.Errorf("capstan: no regions catalogued for geography %q", geography)
}
placements := make([]Placement, 0, len(candidates))
for _, c := range candidates {
tierMap, ok := posture.TierMap[c.Provider]
if !ok {
continue
}
workloadMap, ok := tierMap[workload]
if !ok {
continue
}
size, ok := workloadMap[sla]
if !ok {
continue
}
placements = append(placements, Placement{
Provider: c.Provider,
Region: c.Region,
Size: size,
})
}
if len(placements) == 0 {
return nil, fmt.Errorf("capstan: no placements for geography %q, workload %q, sla %q", geography, workload, sla)
}
primary := placements[0]
var caveats []string
cellKey := string(primary.Provider) + "/" + primary.Region
sizeKey := string(primary.Provider) + "/" + primary.Size
if cc, ok := posture.CellCaveats[cellKey]; ok {
caveats = append(caveats, cc...)
}
if sc, ok := posture.SizeCaveats[sizeKey]; ok {
caveats = append(caveats, sc...)
}
return &Recommendation{
Primary: primary,
Fallbacks: placements[1:],
Caveats: caveats,
}, nil
}