diff --git a/fixtures/dummy/common.go b/fixtures/dummy/common.go new file mode 100644 index 00000000..34d152af --- /dev/null +++ b/fixtures/dummy/common.go @@ -0,0 +1,5 @@ +package dummy + +import "time" + +var DummyCreatedAt = time.Date(2022, time.December, 31, 23, 59, 0, 0, time.UTC) diff --git a/fixtures/dummy/component_relationships.go b/fixtures/dummy/component_relationships.go new file mode 100644 index 00000000..02109bdb --- /dev/null +++ b/fixtures/dummy/component_relationships.go @@ -0,0 +1,26 @@ +package dummy + +import ( + "github.com/flanksource/duty/models" +) + +var LogisticsAPIPodNodeAComponentRelationship = models.ComponentRelationship{ + ComponentID: LogisticsAPIPod.ID, + RelationshipID: NodeA.ID, +} + +var LogisticsUIPodNodeAComponentRelationship = models.ComponentRelationship{ + ComponentID: LogisticsUIPod.ID, + RelationshipID: NodeA.ID, +} + +var LogisticsWorkerPodNodeBComponentRelationship = models.ComponentRelationship{ + ComponentID: LogisticsWorkerPod.ID, + RelationshipID: NodeB.ID, +} + +var AllDummyComponentRelationships = []models.ComponentRelationship{ + LogisticsAPIPodNodeAComponentRelationship, + LogisticsUIPodNodeAComponentRelationship, + LogisticsWorkerPodNodeBComponentRelationship, +} diff --git a/fixtures/dummy/components.go b/fixtures/dummy/components.go index 9fcbeb30..f59b9d47 100644 --- a/fixtures/dummy/components.go +++ b/fixtures/dummy/components.go @@ -2,104 +2,141 @@ package dummy import ( "github.com/flanksource/duty/models" + "github.com/flanksource/duty/types" "github.com/google/uuid" ) var Logistics = models.Component{ - ID: uuid.New(), + ID: uuid.MustParse("018681fc-e54f-bd4f-42be-068a9a69eeb5"), Name: "logistics", Type: "Entity", ExternalId: "dummy/logistics", + Labels: types.JSONStringMap{"telemetry": "enabled"}, + Owner: "logistics-team", + CreatedAt: models.LocalTime(DummyCreatedAt), Status: models.ComponentStatusHealthy, } var LogisticsAPI = models.Component{ - ID: uuid.New(), + ID: uuid.MustParse("018681fd-5770-336f-227c-259435D7fc6b"), Name: "logistics-api", ExternalId: "dummy/logistics-api", Type: "Application", Status: models.ComponentStatusHealthy, + Labels: types.JSONStringMap{"telemetry": "enabled"}, + Owner: "logistics-team", ParentId: &Logistics.ID, + CreatedAt: models.LocalTime(DummyCreatedAt), } var LogisticsUI = models.Component{ - ID: uuid.New(), + ID: uuid.MustParse("018681FD-C1FF-16EE-DFF0-8C8796E4263E"), Name: "logistics-ui", Type: "Application", ExternalId: "dummy/logistics-ui", Status: models.ComponentStatusHealthy, + Owner: "logistics-team", ParentId: &Logistics.ID, + CreatedAt: models.LocalTime(DummyCreatedAt), } var LogisticsWorker = models.Component{ - ID: uuid.New(), + ID: uuid.MustParse("018681FE-010A-6647-74AD-58B3A136DFE4"), Name: "logistics-worker", ExternalId: "dummy/logistics-worker", Type: "Application", Status: models.ComponentStatusHealthy, ParentId: &LogisticsAPI.ID, + CreatedAt: models.LocalTime(DummyCreatedAt), } var LogisticsDB = models.Component{ - ID: uuid.New(), + ID: uuid.MustParse("018681FE-4529-C50F-26FD-530FA9C57319"), Name: "logistics-db", ExternalId: "dummy/logistics-db", Type: "Database", Status: models.ComponentStatusUnhealthy, ParentId: &LogisticsAPI.ID, + CreatedAt: models.LocalTime(DummyCreatedAt), } var ClusterComponent = models.Component{ - ID: uuid.New(), + ID: uuid.MustParse("018681FE-8156-4B91-D178-CAF8B3C2818C"), Name: "cluster", ExternalId: "dummy/cluster", Type: "KubernetesCluster", Status: models.ComponentStatusHealthy, + CreatedAt: models.LocalTime(DummyCreatedAt), +} + +var NodesComponent = models.Component{ + ID: uuid.MustParse("018681FE-B27E-7627-72C2-AD18E93F72F4"), + Name: "Nodes", + ExternalId: "dummy/nodes", + Type: "KubernetesNodes", + Status: models.ComponentStatusHealthy, + ParentId: &ClusterComponent.ID, + CreatedAt: models.LocalTime(DummyCreatedAt), } var NodeA = models.Component{ - ID: uuid.New(), + ID: uuid.MustParse("018681FE-F5AA-37E9-83F7-47B5B0232D5E"), Name: "node-a", ExternalId: "dummy/node-a", Type: "KubernetesNode", Status: models.ComponentStatusHealthy, - ParentId: &ClusterComponent.ID, + ParentId: &NodesComponent.ID, + CreatedAt: models.LocalTime(DummyCreatedAt), } var NodeB = models.Component{ - ID: uuid.New(), + ID: uuid.MustParse("018681FF-227E-4D71-B38E-0693CC862213"), Name: "node-b", ExternalId: "dummy/node-b", Type: "KubernetesNode", Status: models.ComponentStatusHealthy, + ParentId: &NodesComponent.ID, + CreatedAt: models.LocalTime(DummyCreatedAt), +} + +var PodsComponent = models.Component{ + ID: uuid.MustParse("018681FF-559F-7183-19D1-7D898B4E1413"), + Name: "Pods", + ExternalId: "dummy/pods", + Type: "KubernetesPods", + Status: models.ComponentStatusHealthy, ParentId: &ClusterComponent.ID, + CreatedAt: models.LocalTime(DummyCreatedAt), } var LogisticsAPIPod = models.Component{ - ID: uuid.New(), + ID: uuid.MustParse("018681FF-80ED-D10D-21EF-C74F152B085B"), Name: "logistics-api-574dc95b5d-mp64w", ExternalId: "dummy/logistics-api-574dc95b5d-mp64w", Type: "KubernetesPod", Status: models.ComponentStatusHealthy, - ParentId: &NodeA.ID, + ParentId: &PodsComponent.ID, + CreatedAt: models.LocalTime(DummyCreatedAt), } var LogisticsUIPod = models.Component{ - ID: uuid.New(), + ID: uuid.MustParse("018681FF-B6C1-A14D-2FD4-8C7DAC94CDDD"), Name: "logistics-ui-676b85b87c-tjjcp", Type: "KubernetesPod", ExternalId: "dummy/logistics-ui-676b85b87c-tjjcp", Status: models.ComponentStatusHealthy, - ParentId: &NodeA.ID, + ParentId: &PodsComponent.ID, + CreatedAt: models.LocalTime(DummyCreatedAt), } var LogisticsWorkerPod = models.Component{ - ID: uuid.New(), + ID: uuid.MustParse("018681FF-E578-A926-E366-D2DC0646EAFA"), Name: "logistics-worker-79cb67d8f5-lr66n", ExternalId: "dummy/logistics-worker-79cb67d8f5-lr66n", Type: "KubernetesPod", Status: models.ComponentStatusHealthy, - ParentId: &NodeB.ID, + ParentId: &PodsComponent.ID, + CreatedAt: models.LocalTime(DummyCreatedAt), } // Order is important since ParentIDs refer to previous components @@ -110,6 +147,8 @@ var AllDummyComponents = []models.Component{ LogisticsWorker, LogisticsDB, ClusterComponent, + NodesComponent, + PodsComponent, NodeA, NodeB, LogisticsAPIPod, diff --git a/fixtures/dummy/config_component_relationships.go b/fixtures/dummy/config_component_relationships.go index e9e583cf..17d310ab 100644 --- a/fixtures/dummy/config_component_relationships.go +++ b/fixtures/dummy/config_component_relationships.go @@ -19,8 +19,14 @@ var LogisticsDBRDSLogisticsDBComponentRelationship = models.ConfigComponentRelat ComponentID: LogisticsDB.ID, } +var EC2InstanceBNodeBRelationship = models.ConfigComponentRelationship{ + ConfigID: EC2InstanceB.ID, + ComponentID: NodeB.ID, +} + var AllDummyConfigComponentRelationships = []models.ConfigComponentRelationship{ EKSClusterClusterComponentRelationship, KubernetesClusterClusterComponentRelationship, LogisticsDBRDSLogisticsDBComponentRelationship, + EC2InstanceBNodeBRelationship, } diff --git a/fixtures/dummy/evidences.go b/fixtures/dummy/evidences.go new file mode 100644 index 00000000..2b775a7a --- /dev/null +++ b/fixtures/dummy/evidences.go @@ -0,0 +1,17 @@ +package dummy + +import ( + "github.com/flanksource/duty/models" + "github.com/google/uuid" +) + +var LogisticsDBErrorEvidence = models.Evidence{ + ID: uuid.New(), + HypothesisID: LogisticsAPIDownHypothesis.ID, + ComponentID: &LogisticsDB.ID, + CreatedBy: JohnDoe.ID, + Description: "Logisctics DB attached component", + Type: "component", +} + +var AllDummyEvidences = []models.Evidence{LogisticsDBErrorEvidence} diff --git a/fixtures/dummy/hypotheses.go b/fixtures/dummy/hypotheses.go new file mode 100644 index 00000000..9746cf6c --- /dev/null +++ b/fixtures/dummy/hypotheses.go @@ -0,0 +1,17 @@ +package dummy + +import ( + "github.com/flanksource/duty/models" + "github.com/google/uuid" +) + +var LogisticsAPIDownHypothesis = models.Hypothesis{ + ID: uuid.New(), + IncidentID: LogisticsAPIDownIncident.ID, + Title: "Logistics DB database error hypothesis", + CreatedBy: JohnDoe.ID, + Type: "solution", + Status: "possible", +} + +var AllDummyHypotheses = []models.Hypothesis{LogisticsAPIDownHypothesis} diff --git a/fixtures/expectations/topology_child_tree.json b/fixtures/expectations/topology_child_tree.json new file mode 100644 index 00000000..0308404e --- /dev/null +++ b/fixtures/expectations/topology_child_tree.json @@ -0,0 +1,51 @@ +[ + { + "id": "018681fe-f5aa-37e9-83f7-47b5b0232d5e", + "external_id": "dummy/node-a", + "parent_id": "018681fe-b27e-7627-72c2-ad18e93f72f4", + "name": "node-a", + "status": "healthy", + "type": "KubernetesNode", + "configs": null, + "summary": { + "healthy": 2 + }, + "is_leaf": false, + "created_at": "2022-12-31T23:59:00", + "updated_at": "2022-12-31T23:59:00", + "components": [ + { + "id": "018681ff-80ed-d10d-21ef-c74f152b085b", + "external_id": "dummy/logistics-api-574dc95b5d-mp64w", + "parent_id": "018681ff-559f-7183-19d1-7d898b4e1413", + "name": "logistics-api-574dc95b5d-mp64w", + "status": "healthy", + "type": "KubernetesPod", + "configs": null, + "summary": { + "healthy": 1 + }, + "is_leaf": false, + "created_at": "2022-12-31T23:59:00", + "updated_at": "2022-12-31T23:59:00", + "relationship_id": "018681fe-f5aa-37e9-83f7-47b5b0232d5e" + }, + { + "id": "018681ff-b6c1-a14d-2fd4-8c7dac94cddd", + "external_id": "dummy/logistics-ui-676b85b87c-tjjcp", + "parent_id": "018681ff-559f-7183-19d1-7d898b4e1413", + "name": "logistics-ui-676b85b87c-tjjcp", + "status": "healthy", + "type": "KubernetesPod", + "configs": null, + "summary": { + "healthy": 1 + }, + "is_leaf": false, + "created_at": "2022-12-31T23:59:00", + "updated_at": "2022-12-31T23:59:00", + "relationship_id": "018681fe-f5aa-37e9-83f7-47b5b0232d5e" + } + ] + } + ] diff --git a/fixtures/expectations/topology_root_tree.json b/fixtures/expectations/topology_root_tree.json new file mode 100644 index 00000000..a067f91c --- /dev/null +++ b/fixtures/expectations/topology_root_tree.json @@ -0,0 +1,261 @@ +[ + { + "id": "018681fc-e54f-bd4f-42be-068a9a69eeb5", + "external_id": "dummy/logistics", + "name": "logistics", + "status": "warning", + "type": "Entity", + "owner": "logistics-team", + "labels": { + "telemetry": "enabled" + }, + "configs": null, + "summary": { + "healthy": 1, + "warning": 1, + "incidents": { + "availability": { + "Blocker": 1 + } + }, + "insights": { + "security": { + "critical": 1 + } + } + }, + "is_leaf": false, + "created_at": "2022-12-31T23:59:00", + "updated_at": "2022-12-31T23:59:00", + "components": [ + { + "id": "018681fd-5770-336f-227c-259435d7fc6b", + "external_id": "dummy/logistics-api", + "parent_id": "018681fc-e54f-bd4f-42be-068a9a69eeb5", + "name": "logistics-api", + "owner": "logistics-team", + "labels": { + "telemetry": "enabled" + }, + "status": "warning", + "type": "Application", + "configs": null, + "summary": { + "healthy": 1, + "unhealthy": 1, + "incidents": { + "availability": { + "Blocker": 1 + } + }, + "insights": { + "security": { + "critical": 1 + } + } + }, + "is_leaf": false, + "created_at": "2022-12-31T23:59:00", + "updated_at": "2022-12-31T23:59:00", + "components": [ + { + "id": "018681fe-010a-6647-74ad-58b3a136dfe4", + "external_id": "dummy/logistics-worker", + "parent_id": "018681fd-5770-336f-227c-259435d7fc6b", + "name": "logistics-worker", + "status": "healthy", + "type": "Application", + "configs": null, + "summary": { + "healthy": 1 + }, + "is_leaf": false, + "created_at": "2022-12-31T23:59:00", + "updated_at": "2022-12-31T23:59:00" + }, + { + "id": "018681fe-4529-c50f-26fd-530fa9c57319", + "external_id": "dummy/logistics-db", + "parent_id": "018681fd-5770-336f-227c-259435d7fc6b", + "name": "logistics-db", + "status": "unhealthy", + "type": "Database", + "configs": null, + "summary": { + "unhealthy": 1, + "incidents": { + "availability": { + "Blocker": 1 + } + }, + "insights": { + "security": { + "critical": 1 + } + } + }, + "is_leaf": false, + "created_at": "2022-12-31T23:59:00", + "updated_at": "2022-12-31T23:59:00" + } + ] + }, + { + "id": "018681fd-c1ff-16ee-dff0-8c8796e4263e", + "external_id": "dummy/logistics-ui", + "parent_id": "018681fc-e54f-bd4f-42be-068a9a69eeb5", + "name": "logistics-ui", + "owner": "logistics-team", + "status": "healthy", + "type": "Application", + "configs": null, + "summary": { + "healthy": 1 + }, + "is_leaf": false, + "created_at": "2022-12-31T23:59:00", + "updated_at": "2022-12-31T23:59:00" + } + ] + }, + { + "id": "018681fe-8156-4b91-d178-caf8b3c2818c", + "external_id": "dummy/cluster", + "name": "cluster", + "status": "healthy", + "type": "KubernetesCluster", + "configs": null, + "summary": { + "healthy": 2, + "insights": { + "security": { + "critical": 1 + } + } + }, + "is_leaf": false, + "created_at": "2022-12-31T23:59:00", + "updated_at": "2022-12-31T23:59:00", + "components": [ + { + "id": "018681fe-b27e-7627-72c2-ad18e93f72f4", + "external_id": "dummy/nodes", + "parent_id": "018681fe-8156-4b91-d178-caf8b3c2818c", + "name": "Nodes", + "status": "healthy", + "type": "KubernetesNodes", + "configs": null, + "summary": { + "healthy": 2, + "insights": { + "security": { + "critical": 1 + } + } + }, + "is_leaf": false, + "created_at": "2022-12-31T23:59:00", + "updated_at": "2022-12-31T23:59:00", + "components": [ + { + "id": "018681fe-f5aa-37e9-83f7-47b5b0232d5e", + "external_id": "dummy/node-a", + "parent_id": "018681fe-b27e-7627-72c2-ad18e93f72f4", + "name": "node-a", + "status": "healthy", + "type": "KubernetesNode", + "configs": null, + "summary": { + "healthy": 1 + }, + "is_leaf": false, + "created_at": "2022-12-31T23:59:00", + "updated_at": "2022-12-31T23:59:00" + }, + { + "id": "018681ff-227e-4d71-b38e-0693cc862213", + "external_id": "dummy/node-b", + "parent_id": "018681fe-b27e-7627-72c2-ad18e93f72f4", + "name": "node-b", + "status": "healthy", + "type": "KubernetesNode", + "configs": null, + "summary": { + "healthy": 1, + "insights": { + "security": { + "critical": 1 + } + } + }, + "is_leaf": false, + "created_at": "2022-12-31T23:59:00", + "updated_at": "2022-12-31T23:59:00" + } + ] + }, + { + "id": "018681ff-559f-7183-19d1-7d898b4e1413", + "external_id": "dummy/pods", + "parent_id": "018681fe-8156-4b91-d178-caf8b3c2818c", + "name": "Pods", + "status": "healthy", + "type": "KubernetesPods", + "configs": null, + "summary": { + "healthy": 3 + }, + "is_leaf": false, + "created_at": "2022-12-31T23:59:00", + "updated_at": "2022-12-31T23:59:00", + "components": [ + { + "id": "018681ff-80ed-d10d-21ef-c74f152b085b", + "external_id": "dummy/logistics-api-574dc95b5d-mp64w", + "parent_id": "018681ff-559f-7183-19d1-7d898b4e1413", + "name": "logistics-api-574dc95b5d-mp64w", + "status": "healthy", + "type": "KubernetesPod", + "configs": null, + "summary": { + "healthy": 1 + }, + "is_leaf": false, + "created_at": "2022-12-31T23:59:00", + "updated_at": "2022-12-31T23:59:00" + }, + { + "id": "018681ff-b6c1-a14d-2fd4-8c7dac94cddd", + "external_id": "dummy/logistics-ui-676b85b87c-tjjcp", + "parent_id": "018681ff-559f-7183-19d1-7d898b4e1413", + "name": "logistics-ui-676b85b87c-tjjcp", + "status": "healthy", + "type": "KubernetesPod", + "configs": null, + "summary": { + "healthy": 1 + }, + "is_leaf": false, + "created_at": "2022-12-31T23:59:00", + "updated_at": "2022-12-31T23:59:00" + }, + { + "id": "018681ff-e578-a926-e366-d2dc0646eafa", + "external_id": "dummy/logistics-worker-79cb67d8f5-lr66n", + "parent_id": "018681ff-559f-7183-19d1-7d898b4e1413", + "name": "logistics-worker-79cb67d8f5-lr66n", + "status": "healthy", + "type": "KubernetesPod", + "configs": null, + "summary": { + "healthy": 1 + }, + "is_leaf": false, + "created_at": "2022-12-31T23:59:00", + "updated_at": "2022-12-31T23:59:00" + } + ] + } + ] + } +]