diff --git a/pkg/iris/mapping.go b/pkg/iris/mapping.go index 859dff3..5e0e195 100644 --- a/pkg/iris/mapping.go +++ b/pkg/iris/mapping.go @@ -1,20 +1,22 @@ package iris import ( + "reflect" + "strconv" + "strings" + "time" + "github.com/leanix/leanix-k8s-connector/pkg/iris/models" "github.com/leanix/leanix-k8s-connector/pkg/kubernetes" "github.com/leanix/leanix-k8s-connector/pkg/set" appsv1 "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" - "reflect" - "strconv" - "strings" - "time" ) type Mapper interface { MapCluster(clusterName string, nodes *v1.NodeList) (ClusterDTO, error) MapDeployments(deployments *appsv1.DeploymentList, services *v1.ServiceList) ([]models.Deployment, error) + MapDeploymentsEcst(deployments *appsv1.DeploymentList, services *v1.ServiceList) ([]models.DeploymentEcst, error) } type mapper struct { @@ -87,12 +89,43 @@ func (m *mapper) MapDeployments(deployments *appsv1.DeploymentList, services *v1 return allDeployments, nil } +func (m *mapper) MapDeploymentsEcst(deployments *appsv1.DeploymentList, services *v1.ServiceList) ([]models.DeploymentEcst, error) { + var allDeployments []models.DeploymentEcst + + for _, deployment := range deployments.Items { + deploymentService := "" + // Check if any service has the exact same selector labels and use this as the service related to the deployment + deploymentService = ResolveK8sServiceForK8sDeployment(services, deployment) + allDeployments = append(allDeployments, m.CreateDeploymentEcst(deploymentService, deployment)) + } + + return allDeployments, nil +} + func (m *mapper) CreateDeployment(deploymentService string, deployment appsv1.Deployment) models.Deployment { + + mappedDeployment := models.Deployment{ + Service: &models.Service{Name: deploymentService}, + Image: deployment.Spec.Template.Spec.Containers[0].Image, + DeploymentName: deployment.Name, + Labels: deployment.ObjectMeta.Labels, + Timestamp: deployment.CreationTimestamp.UTC().Format(time.RFC3339), + Properties: models.DeploymentProperties{ + UpdateStrategy: string(deployment.Spec.Strategy.Type), + Replicas: strconv.FormatInt(int64(deployment.Status.Replicas), 10), + K8sLimits: CreateK8sResources(deployment.Spec.Template.Spec.Containers[0].Resources.Limits), + K8sRequests: CreateK8sResources(deployment.Spec.Template.Spec.Containers[0].Resources.Requests), + }, + } + return mappedDeployment +} + +func (m *mapper) CreateDeploymentEcst(deploymentService string, deployment appsv1.Deployment) models.DeploymentEcst { var service = "" if deploymentService != "" { service = deploymentService } - mappedDeployment := models.Deployment{ + mappedDeployment := models.DeploymentEcst{ ServiceName: service, Image: deployment.Spec.Template.Spec.Containers[0].Image, DeploymentName: deployment.Name, diff --git a/pkg/iris/mapping_test.go b/pkg/iris/mapping_test.go index fc5cb51..8c26f83 100644 --- a/pkg/iris/mapping_test.go +++ b/pkg/iris/mapping_test.go @@ -1,14 +1,15 @@ package iris import ( + "testing" + "time" + "github.com/leanix/leanix-k8s-connector/pkg/kubernetes" "github.com/stretchr/testify/assert" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "testing" - "time" ) func TestMapDeployments(t *testing.T) { @@ -115,17 +116,29 @@ func TestMapDeployments(t *testing.T) { } mapper := NewMapper(&kubernetes.API{}, "cluster-test", "workspace-test", make([]string, 0), "test-runid") result, err := mapper.MapDeployments(&dummyDeployments, &dummyServices) + resultEcst, err := mapper.MapDeploymentsEcst(&dummyDeployments, &dummyServices) + assert.NoError(t, err) assert.NotEmpty(t, result) - assert.Equal(t, "test-deployment-2", result[0].DeploymentName) - assert.Equal(t, "test-service-2", result[0].ServiceName) - assert.Equal(t, "100", result[0].DeploymentProperties.K8sRequests.Cpu) - assert.Equal(t, "50", result[0].DeploymentProperties.K8sRequests.Memory) - assert.Equal(t, "", result[0].DeploymentProperties.K8sLimits.Cpu) - assert.Equal(t, "", result[0].DeploymentProperties.K8sLimits.Memory) - assert.Equal(t, "1", result[0].DeploymentProperties.Replicas) + assert.Equal(t, "test-service-2", result[0].Service.Name) + assert.Equal(t, "100", result[0].Properties.K8sRequests.Cpu) + assert.Equal(t, "50", result[0].Properties.K8sRequests.Memory) + assert.Equal(t, "", result[0].Properties.K8sLimits.Cpu) + assert.Equal(t, "", result[0].Properties.K8sLimits.Memory) + assert.Equal(t, "1", result[0].Properties.Replicas) assert.Equal(t, "testImage", result[0].Image) + + assert.NoError(t, err) + assert.NotEmpty(t, resultEcst) + assert.Equal(t, "test-deployment-2", resultEcst[0].DeploymentName) + assert.Equal(t, "test-service-2", resultEcst[0].ServiceName) + assert.Equal(t, "100", resultEcst[0].DeploymentProperties.K8sRequests.Cpu) + assert.Equal(t, "50", resultEcst[0].DeploymentProperties.K8sRequests.Memory) + assert.Equal(t, "", resultEcst[0].DeploymentProperties.K8sLimits.Cpu) + assert.Equal(t, "", resultEcst[0].DeploymentProperties.K8sLimits.Memory) + assert.Equal(t, "1", resultEcst[0].DeploymentProperties.Replicas) + assert.Equal(t, "testImage", resultEcst[0].Image) } func TestMapDeployments_NoService(t *testing.T) { @@ -206,17 +219,30 @@ func TestMapDeployments_NoService(t *testing.T) { } mapper := NewMapper(&kubernetes.API{}, "cluster-test", "workspace-test", make([]string, 0), "test-runid") result, err := mapper.MapDeployments(&dummyDeployments, &dummyServices) + resultEcst, err := mapper.MapDeploymentsEcst(&dummyDeployments, &dummyServices) assert.NoError(t, err) assert.NotEmpty(t, result) assert.Equal(t, "test-deployment-2", result[0].DeploymentName) - assert.Empty(t, result[0].ServiceName) - assert.Equal(t, "100", result[0].DeploymentProperties.K8sRequests.Cpu) - assert.Equal(t, "50", result[0].DeploymentProperties.K8sRequests.Memory) - assert.Equal(t, "", result[0].DeploymentProperties.K8sLimits.Cpu) - assert.Equal(t, "", result[0].DeploymentProperties.K8sLimits.Memory) - assert.Equal(t, "1", result[0].DeploymentProperties.Replicas) + assert.Empty(t, result[0].Service.Name) + assert.Equal(t, "100", result[0].Properties.K8sRequests.Cpu) + assert.Equal(t, "50", result[0].Properties.K8sRequests.Memory) + assert.Equal(t, "", result[0].Properties.K8sLimits.Cpu) + assert.Equal(t, "", result[0].Properties.K8sLimits.Memory) + assert.Equal(t, "1", result[0].Properties.Replicas) assert.Equal(t, "testImage", result[0].Image) + + assert.NoError(t, err) + assert.NotEmpty(t, resultEcst) + + assert.Equal(t, "test-deployment-2", resultEcst[0].DeploymentName) + assert.Empty(t, resultEcst[0].ServiceName) + assert.Equal(t, "100", resultEcst[0].DeploymentProperties.K8sRequests.Cpu) + assert.Equal(t, "50", resultEcst[0].DeploymentProperties.K8sRequests.Memory) + assert.Equal(t, "", resultEcst[0].DeploymentProperties.K8sLimits.Cpu) + assert.Equal(t, "", resultEcst[0].DeploymentProperties.K8sLimits.Memory) + assert.Equal(t, "1", resultEcst[0].DeploymentProperties.Replicas) + assert.Equal(t, "testImage", resultEcst[0].Image) } func TestGetCluster(t *testing.T) { diff --git a/pkg/iris/models/clusterEcst.go b/pkg/iris/models/clusterEcst.go index 1f4a20e..6d0ca2f 100644 --- a/pkg/iris/models/clusterEcst.go +++ b/pkg/iris/models/clusterEcst.go @@ -1,12 +1,12 @@ package models type ClusterEcst struct { - Namespace string `json:"namespaceName"` - Deployments []Deployment `json:"deployments"` - Name string `json:"clusterName"` - Os string `json:"os"` - K8sVersion string `json:"k8sVersion"` - NoOfNodes string `json:"noOfNodes"` + Namespace string `json:"namespaceName"` + Deployments []DeploymentEcst `json:"deployments"` + Name string `json:"clusterName"` + Os string `json:"os"` + K8sVersion string `json:"k8sVersion"` + NoOfNodes string `json:"noOfNodes"` } //Interface functions can go here diff --git a/pkg/iris/models/workloads.go b/pkg/iris/models/workloads.go index ec95ebf..30b3700 100644 --- a/pkg/iris/models/workloads.go +++ b/pkg/iris/models/workloads.go @@ -3,6 +3,19 @@ package models // workloads type Deployment struct { + Service *Service `json:"service"` + Image string `json:"image"` + DeploymentName string `json:"deploymentName"` + Labels interface{} `json:"labels"` + Timestamp string `json:"time"` + Properties DeploymentProperties `json:"properties"` +} + +type Service struct { + Name string `json:"name"` +} + +type DeploymentEcst struct { ServiceName string `json:"serviceName"` Image string `json:"image"` DeploymentName string `json:"deploymentName"` diff --git a/pkg/iris/scan.go b/pkg/iris/scan.go index 3812fbd..79eeaa7 100644 --- a/pkg/iris/scan.go +++ b/pkg/iris/scan.go @@ -6,15 +6,16 @@ import ( "encoding/hex" "encoding/json" "fmt" + "net/http" + "strconv" + time2 "time" + "github.com/leanix/leanix-k8s-connector/pkg/iris/models" "github.com/leanix/leanix-k8s-connector/pkg/kubernetes" "github.com/leanix/leanix-k8s-connector/pkg/logger" "github.com/leanix/leanix-k8s-connector/pkg/storage" corev1 "k8s.io/api/core/v1" "k8s.io/client-go/rest" - "net/http" - "strconv" - time2 "time" ) type Scanner interface { @@ -162,12 +163,17 @@ func (s scanner) ScanNamespace(k8sApi *kubernetes.API, mapper Mapper, namespaces return nil, nil, err } + mappedDeploymentsEcst, err := mapper.MapDeploymentsEcst(deployments, services) + if err != nil { + return nil, nil, err + } + // create OLD disovery item oldDiscoveryEvent := s.CreateDiscoveryItem(namespace, mappedDeployments, &cluster, source, scope) oldEvents = append(oldEvents, oldDiscoveryEvent) // create ECST discovery item for namespace - ecstDiscoveryEvent := s.CreateEcstDiscoveryEvent(namespace, mappedDeployments, &cluster, ecstSource, ecstScope) + ecstDiscoveryEvent := s.CreateEcstDiscoveryEvent(namespace, mappedDeploymentsEcst, &cluster, ecstSource, ecstScope) ecstEvents = append(ecstEvents, ecstDiscoveryEvent) } endReplay := s.CreateEndReplay(workspaceId, config) @@ -222,7 +228,7 @@ func (s *scanner) CreateDiscoveryItem(namespace corev1.Namespace, deployments [] } // ECST Discovery Items -func (s *scanner) CreateEcstDiscoveryEvent(namespace corev1.Namespace, deployments []models.Deployment, clusterDTO *ClusterDTO, source string, scope string) models.DiscoveryEvent { +func (s *scanner) CreateEcstDiscoveryEvent(namespace corev1.Namespace, deployments []models.DeploymentEcst, clusterDTO *ClusterDTO, source string, scope string) models.DiscoveryEvent { result := models.ClusterEcst{ Namespace: namespace.Name, Deployments: deployments,