Skip to content

Commit

Permalink
Merge branch 'main' into 10-task-exporting-cluster-diagrams
Browse files Browse the repository at this point in the history
  • Loading branch information
EliasDeHondt authored Feb 27, 2025
2 parents 34e3b3f + 197c6f3 commit 87028ba
Show file tree
Hide file tree
Showing 24 changed files with 751 additions and 245 deletions.
214 changes: 214 additions & 0 deletions App/Backend/cmd/kubernetes/Client.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ type IClient interface {
CreateService(service *cv1.Service) (Service, error)
CreateConfigMap(configMap *cv1.ConfigMap) (ConfigMap, error)
CreateSecret(secret *cv1.Secret) (Secret, error)
GetFilteredPods(namespace string, nodeName string, pageSize int, continueToken string) (*[]cv1.Pod, string, error)
GetFilteredServices(namespace string, nodeName string, pageSize int, continueToken string) (*[]cv1.Service, string, error)
GetFilteredDeployments(namespace string, nodeName string, pageSize int, continueToken string) (*[]av1.Deployment, string, error)
}

type FakeClient struct {
Expand Down Expand Up @@ -431,3 +434,214 @@ func (client *Client) CreateSecret(secret *cv1.Secret) (Secret, error) {

return NewSecret(*secret), err
}

func (client *FakeClient) GetFilteredPods(namespace string, nodeName string, pageSize int, continueToken string) (*[]cv1.Pod, string, error) {
ct, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

var filteredPods []cv1.Pod
var newContinueToken string

list, err := client.Client.CoreV1().Pods(namespace).List(ct, metav1.ListOptions{
Limit: int64(pageSize),
Continue: continueToken,
})
if err != nil {
return nil, "", err
}

for _, pod := range list.Items {
if nodeName == "" || pod.Spec.NodeName == nodeName {
filteredPods = append(filteredPods, pod)
}
}
newContinueToken = list.Continue
return &filteredPods, newContinueToken, nil
}

func (client *Client) GetFilteredPods(namespace string, nodeName string, pageSize int, continueToken string) (*[]cv1.Pod, string, error) {
ct, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

var filteredPods []cv1.Pod
var newContinueToken string

fieldSelector := ""
if nodeName != "" {
fieldSelector = "spec.nodeName=" + nodeName
}

list, err := client.GetPods(namespace).List(ct, metav1.ListOptions{
Limit: int64(pageSize),
Continue: continueToken,
FieldSelector: fieldSelector,
})
if err != nil {
return nil, "", err
}

filteredPods = list.Items
newContinueToken = list.Continue
return &filteredPods, newContinueToken, nil
}

func (client *FakeClient) GetFilteredServices(namespace string, nodeName string, pageSize int, continueToken string) (*[]cv1.Service, string, error) {
ct, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

var filteredServices []cv1.Service
var newContinueToken string

services, err := client.GetServices(namespace).List(ct, metav1.ListOptions{
Limit: int64(pageSize),
Continue: continueToken,
})
if err != nil {
return nil, "", err
}

if nodeName != "" {
pods, _, err := client.GetFilteredPods(namespace, nodeName, 0, "")
if err != nil {
return nil, "", err
}
for _, pod := range *pods {
for _, svc := range services.Items {
if isPodMatchingService(pod, svc) {
filteredServices = append(filteredServices, svc)
}
}
}
} else {
filteredServices = services.Items
}

return &filteredServices, newContinueToken, nil
}

func (client *Client) GetFilteredServices(namespace string, nodeName string, pageSize int, continueToken string) (*[]cv1.Service, string, error) {
_, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

ct, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

var filteredServices []cv1.Service
var newContinueToken string

services, err := client.GetServices(namespace).List(ct, metav1.ListOptions{
Limit: int64(pageSize),
Continue: continueToken,
})
if err != nil {
return nil, "", err
}

if nodeName != "" {
pods, _, err := client.GetFilteredPods(namespace, nodeName, 0, "")
if err != nil {
return nil, "", err
}
for _, pod := range *pods {
for _, svc := range services.Items {
if isPodMatchingService(pod, svc) {
filteredServices = append(filteredServices, svc)
}
}
}
} else {
filteredServices = services.Items
}

return &filteredServices, newContinueToken, nil
}

func (client *FakeClient) GetFilteredDeployments(namespace string, nodeName string, pageSize int, continueToken string) (*[]av1.Deployment, string, error) {
ct, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

var filteredDeployments []av1.Deployment
var newContinueToken string

if nodeName != "" {
pods, _, err := client.GetFilteredPods(namespace, nodeName, 0, "")
if err != nil {
return nil, "", err
}
for _, pod := range *pods {
for _, owner := range pod.OwnerReferences {
if owner.Kind == "ReplicaSet" {
rs, err := client.Client.AppsV1().ReplicaSets(namespace).Get(ct, owner.Name, metav1.GetOptions{})
if err != nil {
continue
}

for _, rsOwner := range rs.OwnerReferences {
if rsOwner.Kind == "Deployment" {
deployment, err := client.GetDeployments(namespace).Get(ct, rsOwner.Name, metav1.GetOptions{})
if err == nil {
filteredDeployments = append(filteredDeployments, *deployment)
}
}
}
}
}
}
} else {
deployments, err := client.GetDeployments(namespace).List(ct, metav1.ListOptions{
Limit: int64(pageSize),
Continue: continueToken,
})
if err != nil {
return nil, "", err
}
filteredDeployments = deployments.Items
}

return &filteredDeployments, newContinueToken, nil
}

func (client *Client) GetFilteredDeployments(namespace string, nodeName string, pageSize int, continueToken string) (*[]av1.Deployment, string, error) {
ct, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

var filteredDeployments []av1.Deployment
var newContinueToken string

if nodeName != "" {
pods, _, err := client.GetFilteredPods(namespace, nodeName, 0, "")
if err != nil {
return nil, "", err
}
for _, pod := range *pods {
for _, owner := range pod.OwnerReferences {
if owner.Kind == "ReplicaSet" {
rs, err := client.Client.AppsV1().ReplicaSets(namespace).Get(ct, owner.Name, metav1.GetOptions{})
if err != nil {
continue
}

for _, rsOwner := range rs.OwnerReferences {
if rsOwner.Kind == "Deployment" {
deployment, err := client.GetDeployments(namespace).Get(ct, rsOwner.Name, metav1.GetOptions{})
if err == nil {
filteredDeployments = append(filteredDeployments, *deployment)
}
}
}
}
}
}
} else {
deployments, err := client.GetDeployments(namespace).List(ct, metav1.ListOptions{
Limit: int64(pageSize),
Continue: continueToken,
})
if err != nil {
return nil, "", err
}
filteredDeployments = deployments.Items
}

return &filteredDeployments, newContinueToken, nil
}
4 changes: 1 addition & 3 deletions App/Backend/cmd/kubernetes/Pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ type Pod struct {
Age string
}

//TODO: remove fake clientset and use a real clientset

func NewPod(pod v1.Pod, clientset IClient) Pod {

runningServices, totalServices := getServiceHealthForPod(pod, clientset)
Expand Down Expand Up @@ -141,4 +139,4 @@ func calculatePodAge(pod v1.Pod) string {
age := time.Since(pod.CreationTimestamp.Time)

return fmt.Sprintf("%d:%d:%d", int(age.Hours()/24), int(age.Hours())%24, int(age.Minutes())%60)
}
}
14 changes: 13 additions & 1 deletion App/Backend/cmd/kubernetes/Setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,18 @@ func TestFakeClient() IClient {
clientset.GetNodes().Create(context.TODO(), node, metav1.CreateOptions{})
}

namespaces := []*corev1.Namespace{
{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
},
},
}

for _, namespace := range namespaces {
clientset.GetNamespaces().Create(context.TODO(), namespace, metav1.CreateOptions{})
}

pods := []*corev1.Pod{
{
ObjectMeta: metav1.ObjectMeta{
Expand Down Expand Up @@ -314,4 +326,4 @@ func TestFakeClient() IClient {
}

return clientset
}
}
4 changes: 2 additions & 2 deletions App/Backend/cmd/kubernetes/handlers/GetConfigMaps.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func transformConfigMaps(list *[]v1.ConfigMap) []kubernetes.ConfigMap {
wg.Add(1)
semaphore <- struct{}{}

go func(i int, node v1.ConfigMap) {
go func(i int, config v1.ConfigMap) {
defer wg.Done()
configList[i] = kubernetes.NewConfigMap(config)
<-semaphore
Expand All @@ -73,4 +73,4 @@ func transformConfigMaps(list *[]v1.ConfigMap) []kubernetes.ConfigMap {

wg.Wait()
return configList
}
}
30 changes: 9 additions & 21 deletions App/Backend/cmd/kubernetes/handlers/GetDeployments.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,22 @@
package handlers

import (
"context"
"github.com/eliasdehondt/K10s/App/Backend/cmd/kubernetes"
"github.com/gin-gonic/gin"
v1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"net/http"
"sync"
"time"
)

func GetDeploymentsHandler(ctx *gin.Context) {
namespace, ok := ctx.GetQuery("namespace")
namespace, _ := ctx.GetQuery("namespace")
nodeName, _ := ctx.GetQuery("node")
pageSize, pageToken := GetPageSizeAndPageToken(ctx)

var deploymentList *PaginatedResponse[[]kubernetes.Deployment]
var err error

if ok {
deploymentList, err = GetDeployments(c, namespace, pageSize, pageToken)
} else {
deploymentList, err = GetDeployments(c, "", pageSize, pageToken)
}
deploymentList, err = GetDeployments(c, namespace, nodeName, pageSize, pageToken)

if err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "An error has occurred or the request has been timed out."})
Expand All @@ -35,21 +29,15 @@ func GetDeploymentsHandler(ctx *gin.Context) {
ctx.JSON(http.StatusOK, deploymentList)
}

func GetDeployments(c kubernetes.IClient, namespace string, pageSize int, pageToken string) (*PaginatedResponse[[]kubernetes.Deployment], error) {
ct, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

list, err := c.GetDeployments(namespace).List(ct, metav1.ListOptions{
Limit: int64(pageSize),
Continue: pageToken,
})
func GetDeployments(c kubernetes.IClient, namespace string, nodeName string, pageSize int, pageToken string) (*PaginatedResponse[[]kubernetes.Deployment], error) {
list, token, err := c.GetFilteredDeployments(namespace, nodeName, pageSize, pageToken)
if err != nil {
return nil, err
}

return &PaginatedResponse[[]kubernetes.Deployment]{
Response: transformDeployments(&list.Items),
PageToken: list.Continue,
Response: transformDeployments(list),
PageToken: token,
}, nil
}

Expand All @@ -64,7 +52,7 @@ func transformDeployments(list *[]v1.Deployment) []kubernetes.Deployment {
wg.Add(1)
semaphore <- struct{}{}

go func(i int, node v1.Deployment) {
go func(i int, deployment v1.Deployment) {
defer wg.Done()
deploymentList[i] = kubernetes.NewDeployment(deployment)
<-semaphore
Expand All @@ -73,4 +61,4 @@ func transformDeployments(list *[]v1.Deployment) []kubernetes.Deployment {

wg.Wait()
return deploymentList
}
}
Loading

0 comments on commit 87028ba

Please sign in to comment.