diff --git a/resources/clusterResources.go b/resources/clusterResources.go index c2af502..2699921 100644 --- a/resources/clusterResources.go +++ b/resources/clusterResources.go @@ -216,30 +216,33 @@ func GetClusterRoleBinding(clusterRoleBindingName string) (relatedClusterRoleBin // GetClusterRelatedResources retrieves all related resources for a given resource kind, name and namespace. func GetClusterRelatedResources(resourceKind string, resourceName string, namespace string) (relatedClusterServices common.RelatedClusterServices) { - // - log.Printf("[DEBUG] Attemping to parse Resource: %s of kind: %s related cluster services.\n", resourceName, resourceKind) common.CreateClusterClient() - switch resourceKind { - case "ConfigMap": - relatedClusterServices = ConfigMapRelatedWorkloads(resourceName) - case "Secret": - relatedClusterServices = SecretRelatedWorkloads(resourceName) - case "ClusterRoleBinding": - relatedClusterServices = ClusterRoleBindingRelatedWorkloads(resourceName) - case "ServiceAccount": - relatedClusterServices = ServiceAccountRelatedWorkloads(resourceName) - case "ClusterRole": - relatedClusterServices = ClusterRoleRelatedWorkloads(resourceName) - case "Deployment": - relatedClusterServices = DeploymentRelatedResources(resourceName, namespace) - case "DaemonSet": - relatedClusterServices = DaemonSetRelatedResources(resourceName, namespace) - case "StatefulSet": - relatedClusterServices = StatefulSetRelatedResources(resourceName, namespace) - default: - log.Printf("[ERROR] Unknown resource kind %s", resourceKind) + if common.K8sClient != nil { + switch resourceKind { + case "ConfigMap": + relatedClusterServices = ConfigMapRelatedWorkloads(resourceName) + case "Secret": + relatedClusterServices = SecretRelatedWorkloads(resourceName) + case "ClusterRoleBinding": + relatedClusterServices = ClusterRoleBindingRelatedWorkloads(resourceName) + case "ServiceAccount": + relatedClusterServices = ServiceAccountRelatedWorkloads(resourceName) + case "ClusterRole": + relatedClusterServices = ClusterRoleRelatedWorkloads(resourceName) + case "Deployment": + relatedClusterServices = DeploymentRelatedResources(resourceName, namespace) + case "DaemonSet": + relatedClusterServices = DaemonSetRelatedResources(resourceName, namespace) + case "StatefulSet": + relatedClusterServices = StatefulSetRelatedResources(resourceName, namespace) + default: + log.Printf("[ERROR] Unknown resource kind %s", resourceKind) + } + + } else { + log.Printf("Failed to parse Resource: %s of kind: %s related cluster services, couldn't create a K8S client.\n", resourceName, resourceKind) } return relatedClusterServices diff --git a/resources/resourceInformer.go b/resources/resourceInformer.go index 6ab3da9..34df6e6 100644 --- a/resources/resourceInformer.go +++ b/resources/resourceInformer.go @@ -15,6 +15,7 @@ import ( "main.go/common" "os" "os/signal" + "reflect" "sync" ) @@ -195,29 +196,19 @@ func EventObject(rawObj map[string]interface{}, isNew bool) (resourceObject comm return resourceObject } - // Check if the newObject field of rawObj is nil, if it is required - if isNew && rawObj["newObject"] == nil { - log.Println("[ERROR] rawObj does not have required field: newObject.") - // Return an empty KubernetesEvent object if the raw object is invalid - return resourceObject - } - - // Check if the oldObject field of rawObj is nil, if it is required - if !isNew && rawObj["oldObject"] == nil { - log.Println("[ERROR] rawObj does not have required field: oldObject.") - // Return an empty KubernetesEvent object if the raw object is invalid - return resourceObject - } - // Initialize an empty unstructured object rawUnstructuredObj := unstructured.Unstructured{} // Initialize a buffer to store the JSON-encoded raw object var buffer bytes.Buffer // Encode the raw object into JSON and write it to the buffer - json.NewEncoder(&buffer).Encode(rawObj) + err := json.NewEncoder(&buffer).Encode(rawObj) + if err != nil { + log.Printf("Failed to encode unstructed resource object bytes:\n%v\nError:\n%v", rawObj, err) + + } // Unmarshal the JSON-encoded raw object into a KubernetesEvent object - err := json.Unmarshal(buffer.Bytes(), &resourceObject) + err = json.Unmarshal(buffer.Bytes(), &resourceObject) if err != nil { log.Printf("Failed to unmarshal resource object:\n%v\nError:\n%v", rawObj, err) } else { @@ -236,12 +227,17 @@ func EventObject(rawObj map[string]interface{}, isNew bool) (resourceObject comm // StructResourceLog receives an event and logs it in a structured format. func StructResourceLog(event map[string]interface{}) (isStructured bool, marshaledEvent []byte) { - // Check if event is nil if event == nil { log.Println("[ERROR] Event is nil") return false, nil } + // Check if the newObject field of rawObj is nil, if it is required + if event["newObject"] == nil { + log.Println("[ERROR] rawObj does not have required field: newObject.") + // Return an empty KubernetesEvent object if the raw object is invalid + return + } // Assert that event["eventType"] is a string eventType, ok := event["eventType"].(string) @@ -286,7 +282,10 @@ func StructResourceLog(event map[string]interface{}) (isStructured bool, marshal } // Get the related cluster services for the resource - event["relatedClusterServices"] = GetClusterRelatedResources(resourceKind, resourceName, resourceNamespace) + relatedClusterServices := GetClusterRelatedResources(resourceKind, resourceName, resourceNamespace) + if !reflect.ValueOf(relatedClusterServices).IsZero() { + event["relatedClusterServices"] = relatedClusterServices + } event["message"] = msg // Marshal the event to a string @@ -296,6 +295,7 @@ func StructResourceLog(event map[string]interface{}) (isStructured bool, marshal } // Mark the goroutine as done + wg.Add(1) defer wg.Done() // Return true indicating the log is structured diff --git a/resources/resourceInformer_test.go b/resources/resourceInformer_test.go index 561567c..0325d76 100644 --- a/resources/resourceInformer_test.go +++ b/resources/resourceInformer_test.go @@ -2,7 +2,6 @@ package resources import ( "encoding/json" - "fmt" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -11,7 +10,6 @@ import ( "k8s.io/client-go/tools/cache" "log" "main.go/common" - "sigs.k8s.io/yaml" "testing" ) @@ -41,23 +39,26 @@ func TestCreateResourceInformer(t *testing.T) { // TestEventObject tests the creation of an event object from a map func TestEventObject(t *testing.T) { testDeployment := GetTestDeployment() - // Marshal the struct to JSON - jsonData, err := yaml.Marshal(testDeployment) + jsonData, err := json.Marshal(testDeployment) if err != nil { - fmt.Printf("error: %s", err) - return + t.Fatalf("Failed to marshal test deployment: %s", err) } - // Unmarshal the JSON to a map var deploymentMap map[string]interface{} - err = yaml.Unmarshal(jsonData, &deploymentMap) - if err != nil { - fmt.Printf("error: %s", err) - return + if err = json.Unmarshal(jsonData, &deploymentMap); err != nil { + t.Fatalf("Failed to unmarshal deployment map: %s", err) + } + + // Deep copy of the map + mapBytes, _ := json.Marshal(deploymentMap) + var newObject map[string]interface{} + if err = json.Unmarshal(mapBytes, &newObject); err != nil { + t.Fatalf("Failed to unmarshal new object: %s", err) } + deploymentMap["eventType"] = common.EventTypeAdded deploymentMap["kind"] = "Deployment" - deploymentMap["newObject"] = &deploymentMap + deploymentMap["newObject"] = newObject eventObject := EventObject(deploymentMap, true) if eventObject.Kind != "Deployment" { @@ -75,24 +76,29 @@ func TestEventObject(t *testing.T) { // TestStructResourceLog tests the creation of a structured resource log func TestStructResourceLog(t *testing.T) { - var deploymentMap map[string]interface{} testDeployment := GetTestDeployment() - jsonDeployment, err := json.Marshal(testDeployment) + jsonData, err := json.Marshal(testDeployment) if err != nil { - t.Errorf("Failed to marshal test deployment.\nError:\n %v", err) + t.Fatalf("Failed to marshal test deployment: %s", err) } - err = json.Unmarshal(jsonDeployment, &deploymentMap) - if err != nil { - t.Errorf("Failed to unmarshal test deployment.\nError:\n %v", err) + var deploymentMap map[string]interface{} + if err = json.Unmarshal(jsonData, &deploymentMap); err != nil { + t.Fatalf("Failed to unmarshal deployment map: %s", err) } - deploymentEventMap := map[string]interface{}{ - "eventType": common.EventTypeAdded, - "kind": "Deployment", - "newObject": deploymentMap, + // Deep copy of the map + mapBytes, _ := json.Marshal(deploymentMap) + var newObject map[string]interface{} + if err = json.Unmarshal(mapBytes, &newObject); err != nil { + t.Fatalf("Failed to unmarshal new object: %s", err) } - isStructured, _ := StructResourceLog(deploymentEventMap) + + deploymentMap["eventType"] = common.EventTypeAdded + deploymentMap["kind"] = "Deployment" + deploymentMap["newObject"] = newObject + + isStructured, _ := StructResourceLog(deploymentMap) if !isStructured { t.Errorf("Failed to structure resource log")