-
Notifications
You must be signed in to change notification settings - Fork 22
/
cache.go
153 lines (131 loc) · 5.15 KB
/
cache.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
144
145
146
147
148
149
150
151
152
153
package cluster
import (
"sync"
toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1"
"k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/client"
)
var clusterCache = toolchainClusterClients{clusters: map[string]*CachedToolchainCluster{}}
type toolchainClusterClients struct {
sync.RWMutex
clusters map[string]*CachedToolchainCluster
refreshCache func()
}
type Config struct {
// RestConfig contains rest config data
RestConfig *rest.Config
// Name is the name of the cluster. Has to be unique - is used as a key in a map.
Name string
// APIEndpoint is the API endpoint of the corresponding ToolchainCluster. This can be a hostname,
// hostname:port, IP or IP:port.
APIEndpoint string
// OperatorNamespace is a name of a namespace (in the cluster) the operator is running in
OperatorNamespace string
// OwnerClusterName keeps the name of the cluster the ToolchainCluster resource is created in
// eg. if this ToolchainCluster identifies a Host cluster (and thus is created in Member)
// then the OwnerClusterName has a name of the member - it has to be same name as the name
// that is used for identifying the member in a Host cluster
OwnerClusterName string
// Labels contains all the labels of the corresponding ToolchainCluster.
// They will be used for filtering ToolchainCluster's based on a given list of cluster-role labels.
Labels map[string]string `json:"labels,omitempty"`
}
// CachedToolchainCluster stores cluster client; cluster related info and previous health check probe results
type CachedToolchainCluster struct {
*Config
// Client is the kube client for the cluster.
Client client.Client
// ClusterStatus is the cluster result as of the last health check probe.
ClusterStatus *toolchainv1alpha1.ToolchainClusterStatus
}
func (c *toolchainClusterClients) addCachedToolchainCluster(cluster *CachedToolchainCluster) {
c.Lock()
defer c.Unlock()
c.clusters[cluster.Name] = cluster
}
func (c *toolchainClusterClients) deleteCachedToolchainCluster(name string) {
c.Lock()
defer c.Unlock()
delete(c.clusters, name)
}
func (c *toolchainClusterClients) getCachedToolchainCluster(name string, canRefreshCache bool) (*CachedToolchainCluster, bool) {
c.RLock()
defer c.RUnlock()
_, ok := c.clusters[name]
if !ok && canRefreshCache && c.refreshCache != nil {
c.RUnlock()
c.refreshCache()
c.RLock()
}
cluster, ok := c.clusters[name]
return cluster, ok
}
// Condition an expected cluster condition
type Condition func(cluster *CachedToolchainCluster) bool
// Ready checks that the cluster is in a 'Ready' status condition
var Ready Condition = func(cluster *CachedToolchainCluster) bool {
return IsReady(cluster.ClusterStatus)
}
func (c *toolchainClusterClients) getCachedToolchainClusters(conditions ...Condition) []*CachedToolchainCluster {
c.RLock()
defer c.RUnlock()
return Filter(c.clusters, conditions...)
}
func Filter(clusters map[string]*CachedToolchainCluster, conditions ...Condition) []*CachedToolchainCluster {
filteredClusters := make([]*CachedToolchainCluster, 0, len(clusters))
clusters:
for _, cluster := range clusters {
for _, match := range conditions {
if !match(cluster) {
continue clusters
}
}
filteredClusters = append(filteredClusters, cluster)
}
return filteredClusters
}
// GetCachedToolchainCluster returns a kube client for the cluster (with the given name) and info if the client exists
func GetCachedToolchainCluster(name string) (*CachedToolchainCluster, bool) {
return clusterCache.getCachedToolchainCluster(name, true)
}
// GetHostClusterFunc a func that returns the Host cluster from the cache,
// along with a bool to indicate if there was a match or not
type GetHostClusterFunc func() (*CachedToolchainCluster, bool)
// HostCluster the func to retrieve the host cluster
var HostCluster GetHostClusterFunc = GetHostCluster
// GetHostCluster returns the kube client for the host cluster from the cache of the clusters
// and info if such a client exists
func GetHostCluster() (*CachedToolchainCluster, bool) {
clusters := clusterCache.getCachedToolchainClusters()
if len(clusters) == 0 {
if clusterCache.refreshCache != nil {
clusterCache.refreshCache()
}
clusters = clusterCache.getCachedToolchainClusters()
if len(clusters) == 0 {
return nil, false
}
}
return clusters[0], true
}
// GetMemberClustersFunc a func that returns the member clusters from the cache
type GetMemberClustersFunc func(conditions ...Condition) []*CachedToolchainCluster
// MemberClusters the func to retrieve the member clusters
var MemberClusters GetMemberClustersFunc = GetMemberClusters
// GetMemberClusters returns the kube clients for the host clusters from the cache of the clusters
func GetMemberClusters(conditions ...Condition) []*CachedToolchainCluster {
clusters := clusterCache.getCachedToolchainClusters(conditions...)
if len(clusters) == 0 {
if clusterCache.refreshCache != nil {
clusterCache.refreshCache()
}
clusters = clusterCache.getCachedToolchainClusters(conditions...)
}
return clusters
}
// Role defines the role of the cluster.
// Each type of cluster can have multiple roles (tenant for specific APIs, user workloads, others ... )
type Role string
const (
Tenant Role = "tenant"
)