Skip to content
This repository was archived by the owner on Jun 8, 2024. It is now read-only.

Commit 8938460

Browse files
authored
Merge pull request #35 from kthcloud/dev
Update to fetch kubeconfigs locally
2 parents 9328144 + c8c80a8 commit 8938460

File tree

9 files changed

+120
-181
lines changed

9 files changed

+120
-181
lines changed

.gitignore

+4-1
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,7 @@ dist
130130
.pnp.*
131131

132132

133-
.idea/
133+
.idea/
134+
135+
# KubeConfig directory
136+
kube/

dto/body/capacities.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,18 @@ type TimestampedCapacities struct {
1111
}
1212

1313
type Capacities struct {
14-
RAM RamCapacities `json:"ram" bson:"ram"`
1514
CpuCore CpuCoreCapacities `json:"cpuCore" bson:"cpuCore"`
15+
RAM RamCapacities `json:"ram" bson:"ram"`
1616
GPU GpuCapacities `json:"gpu" bson:"gpu"`
1717
Hosts []HostCapacities `json:"hosts" bson:"hosts"`
1818
}
1919

20+
type ClusterCapacities struct {
21+
Name string `json:"cluster" bson:"cluster"`
22+
RAM RamCapacities
23+
CpuCore CpuCoreCapacities
24+
}
25+
2026
type HostGpuCapacities struct {
2127
Count int `json:"count" bson:"count"`
2228
}
@@ -31,12 +37,10 @@ type HostCapacities struct {
3137
}
3238

3339
type RamCapacities struct {
34-
Used int `json:"used" bson:"used"`
3540
Total int `json:"total" bson:"total"`
3641
}
3742

3843
type CpuCoreCapacities struct {
39-
Used int `json:"used" bson:"used"`
4044
Total int `json:"total" bson:"total"`
4145
}
4246

models/config.go

+2-5
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,8 @@ type ConfigType struct {
2121
} `yaml:"keycloak"`
2222

2323
K8s struct {
24-
Clusters []struct {
25-
Name string `yaml:"name"`
26-
URL string `yaml:"url"`
27-
} `yaml:"clusters"`
28-
Clients map[string]kubernetes.Clientset
24+
ConfigDir string `yaml:"configDir"`
25+
Clients map[string]kubernetes.Clientset
2926
} `yaml:"k8s"`
3027

3128
CS struct {

pkg/config/config.go

+18-131
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
11
package config
22

33
import (
4-
"errors"
54
"fmt"
65
"gopkg.in/yaml.v3"
76
"k8s.io/client-go/kubernetes"
87
"k8s.io/client-go/tools/clientcmd"
9-
"log"
108
"os"
11-
"regexp"
129
"strings"
1310
"sys-api/models"
14-
"sys-api/pkg/imp/cloudstack"
15-
"sys-api/pkg/repository"
16-
"sys-api/pkg/subsystems/cs"
1711
)
1812

1913
func Setup() error {
@@ -36,153 +30,46 @@ func Setup() error {
3630
return makeError(err)
3731
}
3832

39-
csClient := cloudstack.NewAsyncClient(
40-
models.Config.CS.URL,
41-
models.Config.CS.ApiKey,
42-
models.Config.CS.Secret,
43-
true,
44-
)
45-
46-
// Load Kubernetes clusters from cloudstack
47-
listClusterParams := csClient.Kubernetes.NewListKubernetesClustersParams()
48-
listClusterParams.SetListall(true)
49-
clusters, err := csClient.Kubernetes.ListKubernetesClusters(listClusterParams)
33+
models.Config.K8s.Clients = make(map[string]kubernetes.Clientset)
34+
35+
// Load config from models.Config.K8s.ConfigDir
36+
// Filename without an extension is used as the cluster name
37+
files, err := os.ReadDir(models.Config.K8s.ConfigDir)
5038
if err != nil {
5139
return makeError(err)
5240
}
5341

54-
fetchConfig := func(name string, publicUrl string) string {
55-
clusterIdx := -1
56-
for idx, cluster := range clusters.KubernetesClusters {
57-
if cluster.Name == name {
58-
clusterIdx = idx
59-
break
60-
}
61-
}
62-
63-
if clusterIdx == -1 {
64-
fmt.Println("cluster", name, "not found")
65-
return ""
66-
}
67-
68-
params := csClient.Kubernetes.NewGetKubernetesClusterConfigParams()
69-
params.SetId(clusters.KubernetesClusters[clusterIdx].Id)
70-
71-
k8sConfig, err := csClient.Kubernetes.GetKubernetesClusterConfig(params)
72-
if err != nil {
73-
log.Println("failed to fetch config for cluster", name, ". details:", err)
74-
return ""
75-
}
76-
77-
// use regex to replace the private ip in config.ConffigData 172.31.1.* with the public ip
78-
regex := regexp.MustCompile(`https://172.31.1.[0-9]+:6443`)
79-
80-
k8sConfig.ClusterConfig.Configdata = regex.ReplaceAllString(k8sConfig.ClusterConfig.Configdata, publicUrl)
81-
82-
return k8sConfig.ClusterConfig.Configdata
83-
}
84-
85-
models.Config.K8s.Clients = make(map[string]kubernetes.Clientset)
86-
87-
for _, cluster := range models.Config.K8s.Clusters {
88-
// get the public ip of the cluster
89-
publicURL := cluster.URL
90-
91-
// get the config data from cloudstack
92-
configData := fetchConfig(cluster.Name, publicURL)
93-
if configData == "" {
42+
for _, file := range files {
43+
if file.IsDir() {
9444
continue
9545
}
9646

97-
// create the k8s client
98-
client, err := createK8sClient([]byte(configData))
47+
clusterName := strings.TrimSuffix(file.Name(), filepath[strings.LastIndex(filepath, "."):])
48+
configData, err := os.ReadFile(models.Config.K8s.ConfigDir + "/" + file.Name())
9949
if err != nil {
100-
fmt.Println(makeError(errors.New("failed to connect to k8s cluster " + cluster.Name + ". details: " + err.Error())))
50+
fmt.Println(makeError(err))
10151
continue
10252
}
10353

104-
if client == nil {
105-
fmt.Println(makeError(errors.New("failed to connect to k8s cluster " + cluster.Name + ", client is nil")))
106-
continue
107-
}
108-
109-
models.Config.K8s.Clients[cluster.Name] = *client
110-
}
111-
112-
clusterNames := make([]string, len(models.Config.K8s.Clients))
113-
i := 0
114-
for name := range models.Config.K8s.Clients {
115-
clusterNames[i] = name
116-
i++
117-
}
118-
119-
if len(clusterNames) > 0 {
120-
fmt.Println("successfully connected to k8s clusters:", strings.Join(clusterNames, ", "))
121-
} else {
122-
fmt.Println("failed to connect to any k8s clusters")
123-
}
124-
125-
return nil
126-
}
127-
128-
func SyncCloudStackHosts() error {
129-
// Register hosts
130-
hosts, err := cs.NewClient(cs.ClientConfig{
131-
URL: models.Config.CS.URL,
132-
ApiKey: models.Config.CS.ApiKey,
133-
Secret: models.Config.CS.Secret,
134-
}).ListHosts()
135-
136-
if err != nil {
137-
return fmt.Errorf("failed to fetch hosts from cloudstack. details: %s", err)
138-
}
139-
140-
if len(hosts) == 0 {
141-
return fmt.Errorf("no hosts found in cloudstack. this is likely due to no hosts being available")
142-
}
143-
144-
zones := make(map[string]models.Zone)
145-
for _, host := range hosts {
146-
convertedName := convertCloudStackZone(host.Zone)
147-
if convertedName == nil {
148-
log.Printf("zone %s not found in cloudstack zone name conversion map. this is likely a unoffical zone\n", host.Zone)
54+
client, err := createK8sClient(configData)
55+
if err != nil {
56+
fmt.Println(makeError(err))
14957
continue
15058
}
15159

152-
newHost := models.NewHost(host.Name, host.DisplayName, *convertedName, host.IP, host.Port, host.Enabled)
153-
if err = repository.NewClient().RegisterHost(newHost); err != nil {
154-
return err
155-
}
60+
models.Config.K8s.Clients[clusterName] = *client
15661

157-
if _, exists := zones[host.Zone]; !exists {
158-
zones[host.Zone] = models.Zone{Name: *convertedName}
159-
}
62+
fmt.Println("Successfully connected to k8s cluster:", clusterName)
16063
}
16164

162-
// Register zones
163-
for _, zone := range zones {
164-
if err := repository.NewClient().RegisterZone(&zone); err != nil {
165-
return err
166-
}
65+
if len(models.Config.K8s.Clients) == 0 {
66+
fmt.Println("No k8s clusters found. Please check your config file and ensure that the k8s config directory is correct")
16767
}
16868

16969
return nil
17070
}
17171

172-
// convertCloudStackZone converts a cloudstack zone
173-
// It is a temporary solution since CloudStack does not use the same zone names as other systems
174-
func convertCloudStackZone(zoneName string) *string {
175-
switch zoneName {
176-
case "Flemingsberg":
177-
s := "se-flem"
178-
return &s
179-
case "Kista":
180-
s := "se-kista"
181-
return &s
182-
}
183-
return nil
184-
}
185-
72+
// createK8sClient creates a k8s client from the text content of a kubeconfig file
18673
func createK8sClient(configData []byte) (*kubernetes.Clientset, error) {
18774
makeError := func(err error) error {
18875
return fmt.Errorf("failed to create k8s client. details: %s", err)

pkg/subsystems/k8s/model.go

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package k8s
2+
3+
type Node struct {
4+
Name string `json:"name"`
5+
CPU struct {
6+
Total int `json:"total"`
7+
} `json:"cpu"`
8+
RAM struct {
9+
Total int `json:"total"`
10+
} `json:"ram"`
11+
}

pkg/subsystems/k8s/nodes.go

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package k8s
2+
3+
import (
4+
"context"
5+
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
6+
)
7+
8+
func (c *Client) GetNodes() ([]Node, error) {
9+
nodes, err := c.K8sClient.CoreV1().Nodes().List(context.TODO(), v1.ListOptions{})
10+
if err != nil {
11+
return nil, err
12+
}
13+
14+
var ret []Node
15+
for _, node := range nodes.Items {
16+
ret = append(ret, Node{
17+
Name: node.Name,
18+
CPU: struct {
19+
Total int `json:"total"`
20+
}{
21+
Total: int(node.Status.Capacity.Cpu().MilliValue()) / 1000,
22+
},
23+
RAM: struct {
24+
Total int `json:"total"`
25+
}{
26+
Total: int(float64(node.Status.Capacity.Memory().Value() / 1024 / 1024 / 1024)),
27+
},
28+
})
29+
}
30+
31+
return ret, nil
32+
}

0 commit comments

Comments
 (0)