diff --git a/db/models/config_item.go b/db/models/config_item.go index 2b31d5bf..a0d7a765 100644 --- a/db/models/config_item.go +++ b/db/models/config_item.go @@ -10,6 +10,7 @@ import ( "github.com/flanksource/duty/types" "github.com/google/uuid" "github.com/lib/pq" + "github.com/samber/lo" ) // ConfigItem represents the config item database table @@ -48,10 +49,10 @@ type ConfigItem struct { func (ci ConfigItem) String() string { if len(ci.ExternalID) == 0 { - return fmt.Sprintf("id=%s name=%s type=%s", ci.ID, *ci.Type, *ci.Name) + return fmt.Sprintf("id=%s type=%s name=%s ", ci.ID, lo.FromPtr(ci.Type), lo.FromPtr(ci.Name)) } - return fmt.Sprintf("id=%s name=%s type=%s external_id=%s", ci.ID, *ci.Type, *ci.Name, ci.ExternalID[0]) + return fmt.Sprintf("id=%s type=%s name=%s external_id=%s", ci.ID, lo.FromPtr(ci.Type), lo.FromPtr(ci.Name), ci.ExternalID[0]) } func (ci ConfigItem) ConfigJSONStringMap() (map[string]interface{}, error) { diff --git a/db/update.go b/db/update.go index 65fedb04..ee8ca64e 100644 --- a/db/update.go +++ b/db/update.go @@ -711,6 +711,10 @@ func extractConfigsAndChangesFromResults(ctx api.ScrapeContext, scrapeStartTime func setConfigParents(ctx api.ScrapeContext, parentTypeToConfigMap map[configExternalKey]string, allConfigs []*models.ConfigItem) error { for _, ci := range allConfigs { + if ci.ParentID != nil { + continue // existing item. Parent is already set. + } + if ci.ParentExternalID == "" || ci.ParentType == "" { continue } diff --git a/scrapers/kubernetes/kubernetes.go b/scrapers/kubernetes/kubernetes.go index 2dfcfef7..d226614d 100644 --- a/scrapers/kubernetes/kubernetes.go +++ b/scrapers/kubernetes/kubernetes.go @@ -439,7 +439,7 @@ func ExtractResults(ctx context.Context, config v1.Kubernetes, objs []*unstructu ID: string(obj.GetUID()), Labels: stripLabels(labels, "-hash"), Tags: tags, - Aliases: getKubernetesAlias(obj), + Aliases: []string{getKubernetesAlias(obj.GetKind(), obj.GetNamespace(), obj.GetName())}, ParentExternalID: parentExternalID, ParentType: ConfigTypePrefix + parentType, RelationshipResults: relationships, @@ -492,17 +492,25 @@ func getKubernetesParent(obj *unstructured.Unstructured, exclusions v1.Kubernete if obj.GetNamespace() != "" { parentConfigType = "Namespace" parentExternalID = resourceIDMap[""]["Namespace"][obj.GetNamespace()] + + if parentExternalID == "" { + // An incremental scraper maynot have the Namespace object. + // We can instead use the alias as the external id. + parentExternalID = getKubernetesAlias("Namespace", "", obj.GetNamespace()) + } + return parentConfigType, parentExternalID } // Everything which is not namespaced should be mapped to cluster parentConfigType = "Cluster" parentExternalID = resourceIDMap[""]["Cluster"]["selfRef"] + return parentConfigType, parentExternalID } -func getKubernetesAlias(obj *unstructured.Unstructured) []string { - return []string{strings.Join([]string{"Kubernetes", obj.GetKind(), obj.GetNamespace(), obj.GetName()}, "/")} +func getKubernetesAlias(kind, namespace, name string) string { + return strings.Join([]string{"Kubernetes", kind, namespace, name}, "/") } func updateOptions(ctx context.Context, opts *options.KetallOptions, config v1.Kubernetes) (*options.KetallOptions, error) {