Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
576 changes: 396 additions & 180 deletions pipelines/graph/graph.go

Large diffs are not rendered by default.

848 changes: 848 additions & 0 deletions pipelines/graph/graph_stamped_test.go

Large diffs are not rendered by default.

54 changes: 50 additions & 4 deletions pipelines/graph/graph_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ func TestForPipeline(t *testing.T) {
t.Fatalf("Failed to create graph for pipeline: %v", err)
}

compareGraph(t, ctx.Nodes, ctx.ServiceValidationSteps)
compareGraph(t, ctx)
}

func compareGraph(t *testing.T, nodes []Node, serviceValidationSteps map[Identifier]types.ValidationStep) {
func compareGraph(t *testing.T, g *Graph) {
t.Helper()

encoded, err := MarshalDOT(nodes, serviceValidationSteps)
encoded, err := MarshalDOT(g)
if err != nil {
t.Fatalf("Failed to marshal graph: %v", err)
}
Expand Down Expand Up @@ -84,7 +84,7 @@ func TestForEntrypoint(t *testing.T) {
t.Fatalf("Failed to create graph for entrypoint: %v", err)
}

compareGraph(t, ctx.Nodes, ctx.ServiceValidationSteps)
compareGraph(t, ctx)
}

func TestForEntrypointDuplicateResourceGroups(t *testing.T) {
Expand All @@ -105,6 +105,52 @@ func TestForEntrypointDuplicateResourceGroups(t *testing.T) {
}
}

func TestFindLeavesErrorsOnMissingChild(t *testing.T) {
parentID := Identifier{
ServiceGroup: "svc",
StepDependency: types.StepDependency{
ResourceGroup: "rg",
Step: "parent",
},
}
missingChildID := Identifier{
ServiceGroup: "svc",
StepDependency: types.StepDependency{
ResourceGroup: "rg",
Step: "missing",
},
}

g := &Graph{
Services: map[string]*topology.Service{
"svc": {ServiceGroup: "svc"},
},
ResourceGroups: map[ResourceGroupKey]*types.ResourceGroupMeta{
{Name: "rg"}: {Name: "rg"},
},
Steps: map[Identifier]types.Step{
parentID: &types.GenericStep{StepMeta: types.StepMeta{Name: "parent"}},
},
Nodes: []Node{
{
Identifier: parentID,
Children: []Identifier{missingChildID},
},
},
}

_, err := g.findLeaves(g.Nodes)
if err == nil {
t.Fatal("expected error for missing child lookup, got nil")
}
if !strings.Contains(err.Error(), "missing") {
t.Fatalf("expected error to mention missing child, got: %v", err)
}
if !strings.Contains(err.Error(), "parent") {
t.Fatalf("expected error to mention parent node, got: %v", err)
}
}

func loadTestdata(t *testing.T, topologyPath string) (*topology.Topology, *topology.Entrypoint, *topology.Service, map[string]*types.Pipeline) {
t.Helper()

Expand Down
98 changes: 49 additions & 49 deletions pipelines/graph/testdata/zz_fixture_TestForEntrypoint.dot
Original file line number Diff line number Diff line change
Expand Up @@ -2,146 +2,146 @@ digraph regexp {
fontname="Helvetica,Arial,sans-serif"
node [fontname="Helvetica,Arial,sans-serif"]
edge [fontname="Helvetica,Arial,sans-serif"]
"Grandparent_global_acrs" [label="Grandparent/global/acrs"];
"Grandparent_global_acrs" [label="Grandparent/global-rg/acrs"];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we pull this into a prior commit, so you can prove in the stamped commit that the existing tests are unaffected?

"Grandparent_global_acrs" -> "Grandparent_global_mirror-oc-mirror-image";
"Grandparent_global_certificates" [label="Grandparent/global/certificates"];
"Grandparent_global_certificates" [label="Grandparent/global-rg/certificates"];
"Grandparent_global_certificates" -> "Parent_global_output";
"Grandparent_global_certificates" -> "Uncle_global_output";
"Grandparent_global_cxChildZone" [label="Grandparent/global/cxChildZone"];
"Grandparent_global_cxChildZone" [label="Grandparent/global-rg/cxChildZone"];
"Grandparent_global_cxChildZone" -> "Parent_global_output";
"Grandparent_global_cxChildZone" -> "Uncle_global_output";
"Grandparent_global_decrypt-and-ingest-secrets" [label="Grandparent/global/decrypt-and-ingest-secrets"];
"Grandparent_global_decrypt-and-ingest-secrets" [label="Grandparent/global-rg/decrypt-and-ingest-secrets"];
"Grandparent_global_decrypt-and-ingest-secrets" -> "Grandparent_global_mirror-oc-mirror-image";
"Grandparent_global_grafana-dashboards" [label="Grandparent/global/grafana-dashboards"];
"Grandparent_global_housekeeping" [label="Grandparent/global/housekeeping"];
"Grandparent_global_grafana-dashboards" [label="Grandparent/global-rg/grafana-dashboards"];
"Grandparent_global_housekeeping" [label="Grandparent/global-rg/housekeeping"];
"Grandparent_global_housekeeping" -> "Grandparent_global_grafana-dashboards";
"Grandparent_global_housekeeping" -> "Parent_global_output";
"Grandparent_global_housekeeping" -> "Uncle_global_output";
"Grandparent_global_imagemirror" [label="Grandparent/global/imagemirror"];
"Grandparent_global_imagemirror" [label="Grandparent/global-rg/imagemirror"];
"Grandparent_global_imagemirror" -> "Parent_global_output";
"Grandparent_global_imagemirror" -> "Uncle_global_output";
"Grandparent_global_infra" [label="Grandparent/global/infra"];
"Grandparent_global_infra" [label="Grandparent/global-rg/infra"];
"Grandparent_global_infra" -> "Grandparent_global_acrs";
"Grandparent_global_infra" -> "Grandparent_global_cxChildZone";
"Grandparent_global_infra" -> "Grandparent_global_decrypt-and-ingest-secrets";
"Grandparent_global_infra" -> "Grandparent_global_grafana-dashboards";
"Grandparent_global_infra" -> "Grandparent_global_onecert-private-kv-issuer";
"Grandparent_global_infra" -> "Grandparent_global_output";
"Grandparent_global_infra" -> "Grandparent_global_svcChildZone";
"Grandparent_global_mirror-oc-mirror-image" [label="Grandparent/global/mirror-oc-mirror-image"];
"Grandparent_global_mirror-oc-mirror-image" [label="Grandparent/global-rg/mirror-oc-mirror-image"];
"Grandparent_global_mirror-oc-mirror-image" -> "Grandparent_global_imagemirror";
"Grandparent_global_onecert-private-kv-issuer" [label="Grandparent/global/onecert-private-kv-issuer"];
"Grandparent_global_onecert-private-kv-issuer" [label="Grandparent/global-rg/onecert-private-kv-issuer"];
"Grandparent_global_onecert-private-kv-issuer" -> "Grandparent_global_certificates";
"Grandparent_global_output" [label="Grandparent/global/output"];
"Grandparent_global_output" [label="Grandparent/global-rg/output"];
"Grandparent_global_output" -> "Grandparent_global_decrypt-and-ingest-secrets";
"Grandparent_global_output" -> "Grandparent_global_grafana-dashboards";
"Grandparent_global_output" -> "Grandparent_global_housekeeping";
"Grandparent_global_output" -> "Grandparent_global_mirror-oc-mirror-image";
"Grandparent_global_svcChildZone" [label="Grandparent/global/svcChildZone"];
"Grandparent_global_svcChildZone" [label="Grandparent/global-rg/svcChildZone"];
"Grandparent_global_svcChildZone" -> "Parent_global_output";
"Grandparent_global_svcChildZone" -> "Uncle_global_output";
"Parent_global_add-hcp-grafana-datasource" [label="Parent/global/add-hcp-grafana-datasource"];
"Parent_global_add-hcp-grafana-datasource" [label="Parent/global-rg/add-hcp-grafana-datasource"];
"Parent_global_add-hcp-grafana-datasource" -> "Child_global_output";
"Parent_global_add-hcp-grafana-datasource" -> "Child_regional_output";
"Parent_global_add-hcp-grafana-datasource" -> "Sibling_global_output";
"Parent_global_add-hcp-grafana-datasource" -> "Sibling_regional_output";
"Parent_global_add-hcp-grafana-datasource" -> "Sibling_service_output";
"Parent_global_add-svc-grafana-datasource" [label="Parent/global/add-svc-grafana-datasource"];
"Parent_global_add-svc-grafana-datasource" [label="Parent/global-rg/add-svc-grafana-datasource"];
"Parent_global_add-svc-grafana-datasource" -> "Parent_global_add-hcp-grafana-datasource";
"Parent_global_ocp-acr-replication" [label="Parent/global/ocp-acr-replication"];
"Parent_global_ocp-acr-replication" [label="Parent/global-rg/ocp-acr-replication"];
"Parent_global_ocp-acr-replication" -> "Parent_regional_rpRegistration";
"Parent_global_output" [label="Parent/global/output"];
"Parent_global_output" [label="Parent/global-rg/output"];
"Parent_global_output" -> "Parent_global_add-hcp-grafana-datasource";
"Parent_global_output" -> "Parent_global_add-svc-grafana-datasource";
"Parent_global_output" -> "Parent_global_ocp-acr-replication";
"Parent_global_output" -> "Parent_global_svc-acr-replication";
"Parent_global_output" -> "Parent_regional_region";
"Parent_global_output" -> "Parent_regional_rpRegistration";
"Parent_global_svc-acr-replication" [label="Parent/global/svc-acr-replication"];
"Parent_global_svc-acr-replication" [label="Parent/global-rg/svc-acr-replication"];
"Parent_global_svc-acr-replication" -> "Parent_regional_rpRegistration";
"Parent_regional_output" [label="Parent/regional/output"];
"Parent_regional_output" [label="Parent/regional-rg/output"];
"Parent_regional_output" -> "Parent_global_add-hcp-grafana-datasource";
"Parent_regional_output" -> "Parent_global_add-svc-grafana-datasource";
"Parent_regional_region" [label="Parent/regional/region"];
"Parent_regional_region" [label="Parent/regional-rg/region"];
"Parent_regional_region" -> "Parent_regional_output";
"Parent_regional_rpRegistration" [label="Parent/regional/rpRegistration"];
"Parent_regional_rpRegistration" [label="Parent/regional-rg/rpRegistration"];
"Parent_regional_rpRegistration" -> "Parent_regional_region";
"Child_global_output" [label="Child/global/output"];
"Child_global_output" [label="Child/global-rg/output"];
"Child_global_output" -> "Child_service_acrpull";
"Child_global_output" -> "Child_service_arobit";
"Child_global_output" -> "Child_service_infra";
"Child_global_output" -> "Child_service_istio-config";
"Child_global_output" -> "Child_service_istio-upgrade";
"Child_global_output" -> "Child_service_prometheus";
"Child_global_output" -> "Child_service_svc";
"Child_regional_output" [label="Child/regional/output"];
"Child_regional_output" [label="Child/regional-rg/output"];
"Child_regional_output" -> "Child_service_infra";
"Child_regional_output" -> "Child_service_svc";
"Child_service_acrpull" [label="Child/service/acrpull"];
"Child_service_arobit" [label="Child/service/arobit"];
"Child_service_infra" [label="Child/service/infra"];
"Child_service_acrpull" [label="Child/service-rg/acrpull"];
"Child_service_arobit" [label="Child/service-rg/arobit"];
"Child_service_infra" [label="Child/service-rg/infra"];
"Child_service_infra" -> "Child_service_svc-oncert-private-kv-issuer";
"Child_service_infra" -> "Child_service_svc-oncert-public-kv-issuer";
"Child_service_istio-config" [label="Child/service/istio-config"];
"Child_service_istio-config" [label="Child/service-rg/istio-config"];
"Child_service_istio-config" -> "Child_service_istio-upgrade";
"Child_service_istio-upgrade" [label="Child/service/istio-upgrade"];
"Child_service_prometheus" [label="Child/service/prometheus"];
"Child_service_istio-upgrade" [label="Child/service-rg/istio-upgrade"];
"Child_service_prometheus" [label="Child/service-rg/prometheus"];
"Child_service_prometheus" -> "Child_service_acrpull";
"Child_service_prometheus" -> "Child_service_istio-config";
"Child_service_svc" [label="Child/service/svc"];
"Child_service_svc" [label="Child/service-rg/svc"];
"Child_service_svc" -> "Child_service_arobit";
"Child_service_svc" -> "Child_service_prometheus";
"Child_service_svc-oncert-private-kv-issuer" [label="Child/service/svc-oncert-private-kv-issuer"];
"Child_service_svc-oncert-private-kv-issuer" [label="Child/service-rg/svc-oncert-private-kv-issuer"];
"Child_service_svc-oncert-private-kv-issuer" -> "Child_service_svc";
"Child_service_svc-oncert-public-kv-issuer" [label="Child/service/svc-oncert-public-kv-issuer"];
"Child_service_svc-oncert-public-kv-issuer" [label="Child/service-rg/svc-oncert-public-kv-issuer"];
"Child_service_svc-oncert-public-kv-issuer" -> "Child_service_svc";
"Sibling_global_output" [label="Sibling/global/output"];
"Sibling_global_output" [label="Sibling/global-rg/output"];
"Sibling_global_output" -> "Sibling_management_acrpull";
"Sibling_global_output" -> "Sibling_management_arobit";
"Sibling_global_output" -> "Sibling_management_mgmt-cluster";
"Sibling_global_output" -> "Sibling_management_mgmt-fixes";
"Sibling_global_output" -> "Sibling_management_mgmt-infra";
"Sibling_global_output" -> "Sibling_management_prometheus";
"Sibling_global_output" -> "Sibling_management_rpRegistration";
"Sibling_management_acrpull" [label="Sibling/management/acrpull"];
"Sibling_management_arobit" [label="Sibling/management/arobit"];
"Sibling_management_cx-oncert-public-kv-issuer" [label="Sibling/management/cx-oncert-public-kv-issuer"];
"Sibling_management_acrpull" [label="Sibling/management-rg/acrpull"];
"Sibling_management_arobit" [label="Sibling/management-rg/arobit"];
"Sibling_management_cx-oncert-public-kv-issuer" [label="Sibling/management-rg/cx-oncert-public-kv-issuer"];
"Sibling_management_cx-oncert-public-kv-issuer" -> "Sibling_management_mgmt-cluster";
"Sibling_management_mgmt-cluster" [label="Sibling/management/mgmt-cluster"];
"Sibling_management_mgmt-cluster" [label="Sibling/management-rg/mgmt-cluster"];
"Sibling_management_mgmt-cluster" -> "Sibling_management_arobit";
"Sibling_management_mgmt-cluster" -> "Sibling_management_mgmt-fixes";
"Sibling_management_mgmt-cluster" -> "Sibling_management_mgmt-nsp";
"Sibling_management_mgmt-cluster" -> "Sibling_management_prometheus";
"Sibling_management_mgmt-fixes" [label="Sibling/management/mgmt-fixes"];
"Sibling_management_mgmt-infra" [label="Sibling/management/mgmt-infra"];
"Sibling_management_mgmt-fixes" [label="Sibling/management-rg/mgmt-fixes"];
"Sibling_management_mgmt-infra" [label="Sibling/management-rg/mgmt-infra"];
"Sibling_management_mgmt-infra" -> "Sibling_management_cx-oncert-public-kv-issuer";
"Sibling_management_mgmt-infra" -> "Sibling_management_mgmt-nsp";
"Sibling_management_mgmt-infra" -> "Sibling_management_mgmt-oncert-private-kv-issuer";
"Sibling_management_mgmt-infra" -> "Sibling_management_mgmt-oncert-public-kv-issuer";
"Sibling_management_mgmt-nsp" [label="Sibling/management/mgmt-nsp"];
"Sibling_management_mgmt-oncert-private-kv-issuer" [label="Sibling/management/mgmt-oncert-private-kv-issuer"];
"Sibling_management_mgmt-nsp" [label="Sibling/management-rg/mgmt-nsp"];
"Sibling_management_mgmt-oncert-private-kv-issuer" [label="Sibling/management-rg/mgmt-oncert-private-kv-issuer"];
"Sibling_management_mgmt-oncert-private-kv-issuer" -> "Sibling_management_mgmt-cluster";
"Sibling_management_mgmt-oncert-public-kv-issuer" [label="Sibling/management/mgmt-oncert-public-kv-issuer"];
"Sibling_management_mgmt-oncert-public-kv-issuer" [label="Sibling/management-rg/mgmt-oncert-public-kv-issuer"];
"Sibling_management_mgmt-oncert-public-kv-issuer" -> "Sibling_management_mgmt-cluster";
"Sibling_management_prometheus" [label="Sibling/management/prometheus"];
"Sibling_management_prometheus" [label="Sibling/management-rg/prometheus"];
"Sibling_management_prometheus" -> "Sibling_management_acrpull";
"Sibling_management_rpRegistration" [label="Sibling/management/rpRegistration"];
"Sibling_management_rpRegistration" [label="Sibling/management-rg/rpRegistration"];
"Sibling_management_rpRegistration" -> "Sibling_management_mgmt-infra";
"Sibling_regional_output" [label="Sibling/regional/output"];
"Sibling_regional_output" [label="Sibling/regional-rg/output"];
"Sibling_regional_output" -> "Sibling_management_mgmt-cluster";
"Sibling_regional_output" -> "Sibling_management_mgmt-infra";
"Sibling_service_output" [label="Sibling/service/output"];
"Sibling_service_output" [label="Sibling/service-rg/output"];
"Sibling_service_output" -> "Sibling_management_mgmt-infra";
"Sibling_service_output" -> "Sibling_management_mgmt-nsp";
"Uncle_global_output" [label="Uncle/global/output"];
"Uncle_global_output" [label="Uncle/global-rg/output"];
"Uncle_global_output" -> "Sibling_management_mgmt-nsp";
"Uncle_global_output" -> "Uncle_global_rg-ownership";
"Uncle_global_output" -> "Uncle_regional_delete-region";
"Uncle_global_output" -> "Uncle_regional_rg-ownership";
"Uncle_global_rg-ownership" [label="Uncle/global/rg-ownership"];
"Uncle_global_rg-ownership" [label="Uncle/global-rg/rg-ownership"];
"Uncle_global_rg-ownership" -> "Uncle_regional_delete-region";
"Uncle_regional_delete-region" [label="Uncle/regional/delete-region"];
"Uncle_regional_rg-ownership" [label="Uncle/regional/rg-ownership"];
"Uncle_regional_delete-region" [label="Uncle/regional-rg/delete-region"];
"Uncle_regional_rg-ownership" [label="Uncle/regional-rg/rg-ownership"];
"Uncle_regional_rg-ownership" -> "Uncle_regional_delete-region";
"serviceValidation" -> "Child_service_validation";
}
24 changes: 12 additions & 12 deletions pipelines/graph/testdata/zz_fixture_TestForPipeline.dot
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,32 @@ digraph regexp {
fontname="Helvetica,Arial,sans-serif"
node [fontname="Helvetica,Arial,sans-serif"]
edge [fontname="Helvetica,Arial,sans-serif"]
"Grandparent_global_acrs" [label="Grandparent/global/acrs"];
"Grandparent_global_acrs" [label="Grandparent/global-rg/acrs"];
"Grandparent_global_acrs" -> "Grandparent_global_mirror-oc-mirror-image";
"Grandparent_global_certificates" [label="Grandparent/global/certificates"];
"Grandparent_global_cxChildZone" [label="Grandparent/global/cxChildZone"];
"Grandparent_global_decrypt-and-ingest-secrets" [label="Grandparent/global/decrypt-and-ingest-secrets"];
"Grandparent_global_certificates" [label="Grandparent/global-rg/certificates"];
"Grandparent_global_cxChildZone" [label="Grandparent/global-rg/cxChildZone"];
"Grandparent_global_decrypt-and-ingest-secrets" [label="Grandparent/global-rg/decrypt-and-ingest-secrets"];
"Grandparent_global_decrypt-and-ingest-secrets" -> "Grandparent_global_mirror-oc-mirror-image";
"Grandparent_global_grafana-dashboards" [label="Grandparent/global/grafana-dashboards"];
"Grandparent_global_housekeeping" [label="Grandparent/global/housekeeping"];
"Grandparent_global_grafana-dashboards" [label="Grandparent/global-rg/grafana-dashboards"];
"Grandparent_global_housekeeping" [label="Grandparent/global-rg/housekeeping"];
"Grandparent_global_housekeeping" -> "Grandparent_global_grafana-dashboards";
"Grandparent_global_imagemirror" [label="Grandparent/global/imagemirror"];
"Grandparent_global_infra" [label="Grandparent/global/infra"];
"Grandparent_global_imagemirror" [label="Grandparent/global-rg/imagemirror"];
"Grandparent_global_infra" [label="Grandparent/global-rg/infra"];
"Grandparent_global_infra" -> "Grandparent_global_acrs";
"Grandparent_global_infra" -> "Grandparent_global_cxChildZone";
"Grandparent_global_infra" -> "Grandparent_global_decrypt-and-ingest-secrets";
"Grandparent_global_infra" -> "Grandparent_global_grafana-dashboards";
"Grandparent_global_infra" -> "Grandparent_global_onecert-private-kv-issuer";
"Grandparent_global_infra" -> "Grandparent_global_output";
"Grandparent_global_infra" -> "Grandparent_global_svcChildZone";
"Grandparent_global_mirror-oc-mirror-image" [label="Grandparent/global/mirror-oc-mirror-image"];
"Grandparent_global_mirror-oc-mirror-image" [label="Grandparent/global-rg/mirror-oc-mirror-image"];
"Grandparent_global_mirror-oc-mirror-image" -> "Grandparent_global_imagemirror";
"Grandparent_global_onecert-private-kv-issuer" [label="Grandparent/global/onecert-private-kv-issuer"];
"Grandparent_global_onecert-private-kv-issuer" [label="Grandparent/global-rg/onecert-private-kv-issuer"];
"Grandparent_global_onecert-private-kv-issuer" -> "Grandparent_global_certificates";
"Grandparent_global_output" [label="Grandparent/global/output"];
"Grandparent_global_output" [label="Grandparent/global-rg/output"];
"Grandparent_global_output" -> "Grandparent_global_decrypt-and-ingest-secrets";
"Grandparent_global_output" -> "Grandparent_global_grafana-dashboards";
"Grandparent_global_output" -> "Grandparent_global_housekeeping";
"Grandparent_global_output" -> "Grandparent_global_mirror-oc-mirror-image";
"Grandparent_global_svcChildZone" [label="Grandparent/global/svcChildZone"];
"Grandparent_global_svcChildZone" [label="Grandparent/global-rg/svcChildZone"];
}
Loading
Loading