-
Notifications
You must be signed in to change notification settings - Fork 41
/
lb_cluster.go
126 lines (114 loc) · 4.49 KB
/
lb_cluster.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
package utils
import (
"fmt"
"github.com/berops/claudie/internal/manifest"
"github.com/berops/claudie/internal/utils"
"github.com/berops/claudie/proto/pb"
)
const hostnameHashLength = 17
// CreateLBCluster reads the unmarshalled manifest and creates loadbalancer clusters based on it.
// Returns slice of *pb.LBcluster if successful, nil otherwise along with the error.
func CreateLBCluster(unmarshalledManifest *manifest.Manifest) ([]*pb.LBcluster, error) {
var lbClusters []*pb.LBcluster
for _, lbCluster := range unmarshalledManifest.LoadBalancer.Clusters {
dns, err := getDNS(lbCluster.DNS, unmarshalledManifest)
if err != nil {
return nil, fmt.Errorf("error while building desired state for LB %s : %w", lbCluster.Name, err)
}
attachedRoles := getRolesAttachedToLBCluster(unmarshalledManifest.LoadBalancer.Roles, lbCluster.Roles)
newLbCluster := &pb.LBcluster{
ClusterInfo: &pb.ClusterInfo{
Name: lbCluster.Name,
Hash: utils.CreateHash(utils.HashLength),
},
Roles: attachedRoles,
Dns: dns,
TargetedK8S: lbCluster.TargetedK8s,
}
nodes, err := unmarshalledManifest.CreateNodepools(lbCluster.Pools, false)
if err != nil {
return nil, fmt.Errorf("error while creating nodepools for %s : %w", lbCluster.Name, err)
}
newLbCluster.ClusterInfo.NodePools = nodes
lbClusters = append(lbClusters, newLbCluster)
}
return lbClusters, nil
}
// UpdateLBClusters updates the desired state of the loadbalancer clusters based on the current state
// returns error if failed, nil otherwise
func UpdateLBClusters(newConfig *pb.Config) error {
clusterLbDesired:
for _, clusterLbDesired := range newConfig.DesiredState.LoadBalancerClusters {
for _, clusterLbCurrent := range newConfig.CurrentState.LoadBalancerClusters {
// found current cluster with matching name
if clusterLbDesired.ClusterInfo.Name == clusterLbCurrent.ClusterInfo.Name {
updateClusterInfo(clusterLbDesired.ClusterInfo, clusterLbCurrent.ClusterInfo)
// copy hostname from current state if not specified in manifest
if clusterLbDesired.Dns.Hostname == "" {
clusterLbDesired.Dns.Hostname = clusterLbCurrent.Dns.Hostname
}
//skip the checks
continue clusterLbDesired
}
}
// no current cluster found with matching name, create keys
if clusterLbDesired.ClusterInfo.PublicKey == "" {
err := createSSHKeyPair(clusterLbDesired.ClusterInfo)
if err != nil {
return fmt.Errorf("error encountered while creating desired state for %s : %w", clusterLbDesired.ClusterInfo.Name, err)
}
}
// create hostname if its not set and not present in current state
if clusterLbDesired.Dns.Hostname == "" {
clusterLbDesired.Dns.Hostname = utils.CreateHash(hostnameHashLength)
}
}
return nil
}
// getDNS reads the unmarshalled manifest and returns *pb.DNS based on it.
// Return *pb.DNS if successful, error if provider has not been found.
func getDNS(lbDNS manifest.DNS, unmarshalledManifest *manifest.Manifest) (*pb.DNS, error) {
if lbDNS.DNSZone == "" {
return nil, fmt.Errorf("DNS zone not provided in manifest %s", unmarshalledManifest.Name)
} else {
provider, err := unmarshalledManifest.GetProvider(lbDNS.Provider)
if err != nil {
return nil, fmt.Errorf("provider %s was not found in manifest %s", lbDNS.Provider, unmarshalledManifest.Name)
}
return &pb.DNS{
DnsZone: lbDNS.DNSZone,
Provider: provider,
Hostname: lbDNS.Hostname,
}, nil
}
}
// getRolesAttachedToLBCluster will read roles attached to the LB cluster from the unmarshalled manifest and return them.
// Returns slice of *[]pb.Roles if successful, error if Target from manifest state not found
func getRolesAttachedToLBCluster(roles []manifest.Role, roleNames []string) []*pb.Role {
var matchingRoles []*pb.Role
for _, roleName := range roleNames {
for _, role := range roles {
if role.Name == roleName {
var roleType pb.RoleType
// The manifest validation is handling the check if the target nodepools of the
// role are control nodepools and thus can be used as a valid API loadbalancer.
// Given this invariant we can simply check for the port.
if role.TargetPort == manifest.APIServerPort {
roleType = pb.RoleType_ApiServer
} else {
roleType = pb.RoleType_Ingress
}
newRole := &pb.Role{
Name: role.Name,
Protocol: role.Protocol,
Port: role.Port,
TargetPort: role.TargetPort,
TargetPools: role.TargetPools,
RoleType: roleType,
}
matchingRoles = append(matchingRoles, newRole)
}
}
}
return matchingRoles
}