diff --git a/api/v1/component_types.go b/api/v1/component_types.go index 37f0cb74f..bde6bda9d 100644 --- a/api/v1/component_types.go +++ b/api/v1/component_types.go @@ -16,14 +16,15 @@ type Component struct { } type ComponentSpec struct { - Name string `json:"name,omitempty"` - Namespace string `json:"namespace,omitempty"` - Tooltip string `json:"tooltip,omitempty"` - Icon string `json:"icon,omitempty"` - Owner string `json:"owner,omitempty"` - Id *Template `json:"id,omitempty"` //nolint - Order int `json:"order,omitempty"` - Labels map[string]string `json:"labels,omitempty"` + Name string `json:"name,omitempty"` + Namespace string `json:"namespace,omitempty"` + Tooltip string `json:"tooltip,omitempty"` + Icon string `json:"icon,omitempty"` + Owner string `json:"owner,omitempty"` + ExternalID string `json:"externalID,omitempty"` + Id *Template `json:"id,omitempty"` //nolint + Order int `json:"order,omitempty"` + Labels map[string]string `json:"labels,omitempty"` // If set to true, do not display in UI Hidden bool `json:"hidden,omitempty"` // The type of component, e.g. service, API, website, library, database, etc. @@ -92,9 +93,10 @@ func (f *ForEach) String() string { } type ParentLookup struct { - Name string `json:"name,omitempty"` - Namespace string `json:"namespace,omitempty"` - Type string `json:"type,omitempty"` + Name string `json:"name,omitempty"` + Namespace string `json:"namespace,omitempty"` + Type string `json:"type,omitempty"` + ExternalID string `json:"externalID,omitempty"` } type ComponentStatus struct { diff --git a/config/deploy/crd.yaml b/config/deploy/crd.yaml index 9f0b788fe..0e173b242 100644 --- a/config/deploy/crd.yaml +++ b/config/deploy/crd.yaml @@ -7161,6 +7161,8 @@ spec: type: array type: object type: array + externalID: + type: string forEach: description: |- Only applies when using lookup, when specified the components and properties @@ -7223,6 +7225,8 @@ spec: parentLookup: description: Reference to populate parent_id properties: + externalID: + type: string name: type: string namespace: @@ -7609,6 +7613,8 @@ spec: type: array type: object type: array + externalID: + type: string forEach: description: |- Only applies when using lookup, when specified the components and properties @@ -7671,6 +7677,8 @@ spec: parentLookup: description: Reference to populate parent_id properties: + externalID: + type: string name: type: string namespace: diff --git a/config/deploy/manifests.yaml b/config/deploy/manifests.yaml index eb9663446..5fbd502d1 100644 --- a/config/deploy/manifests.yaml +++ b/config/deploy/manifests.yaml @@ -7429,6 +7429,8 @@ spec: type: array type: object type: array + externalID: + type: string forEach: description: |- Only applies when using lookup, when specified the components and properties @@ -7491,6 +7493,8 @@ spec: parentLookup: description: Reference to populate parent_id properties: + externalID: + type: string name: type: string namespace: @@ -7877,6 +7881,8 @@ spec: type: array type: object type: array + externalID: + type: string forEach: description: |- Only applies when using lookup, when specified the components and properties @@ -7939,6 +7945,8 @@ spec: parentLookup: description: Reference to populate parent_id properties: + externalID: + type: string name: type: string namespace: diff --git a/config/schemas/component.schema.json b/config/schemas/component.schema.json index 72a24d5d9..4b9a9c0a6 100644 --- a/config/schemas/component.schema.json +++ b/config/schemas/component.schema.json @@ -853,6 +853,9 @@ "owner": { "type": "string" }, + "externalID": { + "type": "string" + }, "id": { "$ref": "#/$defs/Template" }, @@ -939,6 +942,9 @@ "owner": { "type": "string" }, + "externalID": { + "type": "string" + }, "id": { "$ref": "#/$defs/Template" }, @@ -3457,6 +3463,9 @@ }, "type": { "type": "string" + }, + "externalID": { + "type": "string" } }, "additionalProperties": false, diff --git a/config/schemas/topology.schema.json b/config/schemas/topology.schema.json index ae87ffc54..347a380e5 100644 --- a/config/schemas/topology.schema.json +++ b/config/schemas/topology.schema.json @@ -832,6 +832,9 @@ "owner": { "type": "string" }, + "externalID": { + "type": "string" + }, "id": { "$ref": "#/$defs/Template" }, @@ -918,6 +921,9 @@ "owner": { "type": "string" }, + "externalID": { + "type": "string" + }, "id": { "$ref": "#/$defs/Template" }, @@ -3427,6 +3433,9 @@ }, "type": { "type": "string" + }, + "externalID": { + "type": "string" } }, "additionalProperties": false, diff --git a/fixtures/topology/component-with-parent-lookup.yml b/fixtures/topology/component-with-parent-lookup.yml index 1f6bd6f64..83197b90b 100644 --- a/fixtures/topology/component-with-parent-lookup.yml +++ b/fixtures/topology/component-with-parent-lookup.yml @@ -25,7 +25,11 @@ spec: components: - name: Child-2A - name: Child-2B + - name: Child-2C + parentLookup: + externalID: parent-3-external-id - name: Parent-3 type: Type3 namespace: parent3-namespace + externalID: parent-3-external-id diff --git a/pkg/system_api.go b/pkg/system_api.go index d38ec921a..517af5aa1 100644 --- a/pkg/system_api.go +++ b/pkg/system_api.go @@ -277,6 +277,7 @@ func NewComponent(c v1.ComponentSpec) *Component { Namespace: c.Namespace, Owner: c.Owner, Type: c.Type, + ExternalId: c.ExternalID, Order: c.Order, Hidden: c.Hidden, Lifecycle: c.Lifecycle, diff --git a/pkg/topology/run.go b/pkg/topology/run.go index c8d015de4..b626322ba 100644 --- a/pkg/topology/run.go +++ b/pkg/topology/run.go @@ -373,11 +373,25 @@ func mergeComponentProperties(components pkg.Components, propertiesRaw []byte) e func populateParentRefMap(c *pkg.Component, parentRefMap map[string]*pkg.Component) { parentRefMap[genParentKey(c.Name, c.Type, c.Namespace)] = c + if c.ExternalId != "" { + parentRefMap[c.ExternalId] = c + } for _, child := range c.Components { populateParentRefMap(child, parentRefMap) } } +func lookupParent(parentRefMap map[string]*pkg.Component, genKey, parentExternalID string) (*pkg.Component, bool) { + // Check External ID first + if parentExternalID != "" { + c, ok := parentRefMap[parentExternalID] + return c, ok + } + + c, ok := parentRefMap[genKey] + return c, ok +} + func changeComponentParents(c *pkg.Component, parentRefMap map[string]*pkg.Component) { var children pkg.Components for _, child := range c.Components { @@ -387,7 +401,7 @@ func changeComponentParents(c *pkg.Component, parentRefMap map[string]*pkg.Compo } key := genParentKey(child.ParentLookup.Name, child.ParentLookup.Type, child.ParentLookup.Namespace) - if parentComp, exists := parentRefMap[key]; exists { + if parentComp, exists := lookupParent(parentRefMap, key, child.ParentLookup.ExternalID); exists { // Set nil to prevent processing again child.ParentLookup = nil parentComp.Components = append(parentComp.Components, child) diff --git a/pkg/topology/run_test.go b/pkg/topology/run_test.go index fd9838180..93d548e13 100644 --- a/pkg/topology/run_test.go +++ b/pkg/topology/run_test.go @@ -116,7 +116,7 @@ var _ = ginkgo.Describe("Topology run", ginkgo.Ordered, func() { Expect(len(parent1.Components)).To(Equal(2)) Expect(len(parent2.Components)).To(Equal(3)) - Expect(len(parent3.Components)).To(Equal(1)) + Expect(len(parent3.Components)).To(Equal(2)) Expect(parent1.Components[0].Name).To(Equal("Child-1A")) Expect(parent1.Components[1].Name).To(Equal("Child-1B")) @@ -126,6 +126,7 @@ var _ = ginkgo.Describe("Topology run", ginkgo.Ordered, func() { Expect(parent2.Components[2].Name).To(Equal("Child-1C")) Expect(parent3.Components[0].Name).To(Equal("Child-1D")) + Expect(parent3.Components[1].Name).To(Equal("Child-2C")) }) }) diff --git a/pkg/topology/utils.go b/pkg/topology/utils.go index 936ebe90a..b688daea8 100644 --- a/pkg/topology/utils.go +++ b/pkg/topology/utils.go @@ -37,5 +37,5 @@ func isComponentList(data []byte) bool { } func genParentKey(name, _type, namespace string) string { - return strings.Join([]string{name, _type, namespace}, "/") + return strings.Join([]string{"parent.key", name, _type, namespace}, "/") }