From 3257afd20b7b2a1060fd524e82ed13474f764310 Mon Sep 17 00:00:00 2001 From: Rawlin Peters Date: Thu, 17 Dec 2020 19:00:30 -0700 Subject: [PATCH] Fix parent.config generation for MSO with required capabilities Server capabilities do not apply to ORG servers (origins), so don't check for them. --- CHANGELOG.md | 1 + lib/go-atscfg/parentdotconfig.go | 20 +- lib/go-atscfg/parentdotconfig_test.go | 268 ++++++++++++++++++++++++++ 3 files changed, 274 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 859c23b04c..09dab7a8f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - [#5195](https://github.com/apache/trafficcontrol/issues/5195) - Correctly show CDN ID in Changelog during Snap - Fixed Traffic Router logging unnecessary warnings for IPv6-only caches - Fixed parent.config generation for topology-based delivery services (inline comments not supported) +- Fixed parent.config generation for MSO delivery services with required capabilities - [#5294](https://github.com/apache/trafficcontrol/issues/5294) - TP ag grid tables now properly persist column filters on page refresh. - [#5295](https://github.com/apache/trafficcontrol/issues/5295) - TP types/servers table now clears all filters instead diff --git a/lib/go-atscfg/parentdotconfig.go b/lib/go-atscfg/parentdotconfig.go index 56deb3d5bd..082e1a7400 100644 --- a/lib/go-atscfg/parentdotconfig.go +++ b/lib/go-atscfg/parentdotconfig.go @@ -236,7 +236,7 @@ func MakeParentDotConfig( parentServerDSes[*dss.Server][*dss.DeliveryService] = struct{}{} } - originServers, profileCaches, orgProfWarns, err := getOriginServersAndProfileCaches(cgServers, parentServerDSes, profileParentConfigParams, dses, serverCapabilities, dsRequiredCapabilities) + originServers, profileCaches, orgProfWarns, err := getOriginServersAndProfileCaches(cgServers, parentServerDSes, profileParentConfigParams, dses, serverCapabilities) warnings = append(warnings, orgProfWarns...) if err != nil { return Cfg{}, makeErr(warnings, "getting origin servers and profile caches: "+err.Error()) @@ -341,7 +341,7 @@ func MakeParentDotConfig( warnings = append(warnings, "delivery service "+*ds.XMLID+" has no parent servers") } - parents, secondaryParents, parentWarns := getMSOParentStrs(&ds, parentInfos[OriginHost(orgURI.Hostname())], atsMajorVer, dsRequiredCapabilities, dsParams.Algorithm, dsParams.TryAllPrimariesBeforeSecondary) + parents, secondaryParents, parentWarns := getMSOParentStrs(&ds, parentInfos[OriginHost(orgURI.Hostname())], atsMajorVer, dsParams.Algorithm, dsParams.TryAllPrimariesBeforeSecondary) warnings = append(warnings, parentWarns...) textLine += parents + secondaryParents + ` round_robin=` + dsParams.Algorithm + ` qstring=` + parentQStr + ` go_direct=false parent_is_proxy=false` textLine += getParentRetryStr(true, atsMajorVer, dsParams.ParentRetry, dsParams.UnavailableServerRetryResponses, dsParams.MaxSimpleRetries, dsParams.MaxUnavailableServerRetries) @@ -1029,7 +1029,7 @@ func getTopologyParents( continue } - if !hasRequiredCapabilities(serverCapabilities[*sv.ID], dsRequiredCapabilities[*ds.ID]) { + if sv.Type != tc.OriginTypeName && !hasRequiredCapabilities(serverCapabilities[*sv.ID], dsRequiredCapabilities[*ds.ID]) { continue } if *sv.Cachegroup == parentCG { @@ -1136,7 +1136,6 @@ func getMSOParentStrs( ds *DeliveryService, parentInfos []parentInfo, atsMajorVer int, - dsRequiredCapabilities map[int]map[ServerCapability]struct{}, msoAlgorithm string, tryAllPrimariesBeforeSecondary bool, ) (string, string, []string) { @@ -1150,10 +1149,6 @@ func getMSOParentStrs( secondaryParentInfo := []string{} nullParentInfo := []string{} for _, parent := range ([]parentInfo)(rankedParents) { - if !hasRequiredCapabilities(parent.Capabilities, dsRequiredCapabilities[*ds.ID]) { - continue - } - if parent.PrimaryParent { parentInfoTxt = append(parentInfoTxt, parent.Format()) } else if parent.SecondaryParent { @@ -1263,7 +1258,6 @@ func getOriginServersAndProfileCaches( profileParentConfigParams map[string]map[string]string, // map[profileName][paramName]paramVal dses []DeliveryService, serverCapabilities map[int]map[ServerCapability]struct{}, - dsRequiredCapabilities map[int]map[ServerCapability]struct{}, ) (map[OriginHost][]cgServer, map[ProfileID]profileCache, []string, error) { warnings := []string{} originServers := map[OriginHost][]cgServer{} // "deliveryServices" in Perl @@ -1363,12 +1357,8 @@ func getOriginServersAndProfileCaches( // warnings = append(warnings, fmt.Sprintf(("ds %v has no origins! Skipping!\n", dsID) // TODO determine if this is normal continue } - if hasRequiredCapabilities(serverCapabilities[*cgSv.ID], dsRequiredCapabilities[dsID]) { - orgHost := OriginHost(orgURI.Host) - originServers[orgHost] = append(originServers[orgHost], realCGServer) - } else { - warnings = append(warnings, fmt.Sprintf("ds %v server %v missing required caps, skipping!\n", dsID, orgURI.Host)) - } + orgHost := OriginHost(orgURI.Host) + originServers[orgHost] = append(originServers[orgHost], realCGServer) } } else { originServers[deliveryServicesAllParentsKey] = append(originServers[deliveryServicesAllParentsKey], realCGServer) diff --git a/lib/go-atscfg/parentdotconfig_test.go b/lib/go-atscfg/parentdotconfig_test.go index be3443be41..2c2b342379 100644 --- a/lib/go-atscfg/parentdotconfig_test.go +++ b/lib/go-atscfg/parentdotconfig_test.go @@ -1253,6 +1253,274 @@ func TestMakeParentDotConfigTopologiesMSO(t *testing.T) { } } +func TestMakeParentDotConfigTopologiesMSOWithCapabilities(t *testing.T) { + hdr := "myHeaderComment" + + ds1 := makeParentDS() + ds1.ID = util.IntPtr(43) + ds1Type := tc.DSTypeDNS + ds1.Type = &ds1Type + ds1.QStringIgnore = util.IntPtr(int(tc.QStringIgnoreDrop)) + ds1.OrgServerFQDN = util.StrPtr("http://ds1.example.net") + ds1.Topology = util.StrPtr("t0") + ds1.MultiSiteOrigin = util.BoolPtr(true) + + dses := []DeliveryService{*ds1} + + parentConfigParams := []tc.Parameter{ + tc.Parameter{ + Name: ParentConfigParamQStringHandling, + ConfigFile: "parent.config", + Value: "myQStringHandlingParam", + Profiles: []byte(`["serverprofile"]`), + }, + tc.Parameter{ + Name: ParentConfigParamAlgorithm, + ConfigFile: "parent.config", + Value: tc.AlgorithmConsistentHash, + Profiles: []byte(`["serverprofile"]`), + }, + tc.Parameter{ + Name: ParentConfigParamQString, + ConfigFile: "parent.config", + Value: "myQstringParam", + Profiles: []byte(`["serverprofile"]`), + }, + } + + serverParams := []tc.Parameter{ + tc.Parameter{ + Name: "trafficserver", + ConfigFile: "package", + Value: "7", + Profiles: []byte(`["global"]`), + }, + } + + server := makeTestParentServer() + server.Cachegroup = util.StrPtr("edgeCG") + server.CachegroupID = util.IntPtr(400) + server.ID = util.IntPtr(44) + + origin0 := makeTestParentServer() + origin0.Cachegroup = util.StrPtr("originCG") + origin0.CachegroupID = util.IntPtr(500) + origin0.HostName = util.StrPtr("myorigin0") + origin0.ID = util.IntPtr(45) + setIP(origin0, "192.168.2.2") + origin0.Type = tc.OriginTypeName + origin0.TypeID = util.IntPtr(991) + + origin1 := makeTestParentServer() + origin1.Cachegroup = util.StrPtr("originCG") + origin1.CachegroupID = util.IntPtr(500) + origin1.HostName = util.StrPtr("myorigin1") + origin1.ID = util.IntPtr(46) + setIP(origin1, "192.168.2.3") + origin1.Type = tc.OriginTypeName + origin1.TypeID = util.IntPtr(991) + + servers := []Server{*server, *origin0, *origin1} + + topologies := []tc.Topology{ + tc.Topology{ + Name: "t0", + Nodes: []tc.TopologyNode{ + tc.TopologyNode{ + Cachegroup: "edgeCG", + Parents: []int{1}, + }, + tc.TopologyNode{ + Cachegroup: "originCG", + }, + }, + }, + } + + serverCapabilities := map[int]map[ServerCapability]struct{}{ + *server.ID: { + ServerCapability("FOO"): struct{}{}, + }, + } + dsRequiredCapabilities := map[int]map[ServerCapability]struct{}{ + *ds1.ID: { + ServerCapability("FOO"): struct{}{}, + }, + } + + eCG := &tc.CacheGroupNullable{} + eCG.Name = server.Cachegroup + eCG.ID = server.CachegroupID + eCG.ParentName = origin0.Cachegroup + eCG.ParentCachegroupID = origin0.CachegroupID + eCGType := tc.CacheGroupEdgeTypeName + eCG.Type = &eCGType + + oCG := &tc.CacheGroupNullable{} + oCG.Name = origin0.Cachegroup + oCG.ID = origin0.CachegroupID + oCGType := tc.CacheGroupOriginTypeName + oCG.Type = &oCGType + + cgs := []tc.CacheGroupNullable{*eCG, *oCG} + + dss := []tc.DeliveryServiceServer{ + tc.DeliveryServiceServer{ + Server: util.IntPtr(*origin0.ID), + DeliveryService: util.IntPtr(*ds1.ID), + }, + } + cdn := &tc.CDN{ + DomainName: "cdndomain.example", + Name: "my-cdn-name", + } + + cfg, err := MakeParentDotConfig(dses, server, servers, topologies, serverParams, parentConfigParams, serverCapabilities, dsRequiredCapabilities, cgs, dss, cdn, hdr) + if err != nil { + t.Fatal(err) + } + txt := cfg.Text + + testComment(t, txt, hdr) + + if !strings.Contains(txt, "dest_domain=ds1.example.net") { + t.Errorf("expected parent 'dest_domain=ds1.example.net', actual: '%v'", txt) + } + if !strings.Contains(txt, "myorigin0") { + t.Errorf("expected origin0 with DeliveryServiceServer assigned to this DS, actual: '%v'", txt) + } + if strings.Contains(txt, "myorigin1") { + t.Errorf("expected no origin1 without DeliveryServiceServer assigned to this DS, actual: '%v'", txt) + } +} + +func TestMakeParentDotConfigMSOWithCapabilities(t *testing.T) { + hdr := "myHeaderComment" + + ds1 := makeParentDS() + ds1.ID = util.IntPtr(43) + ds1Type := tc.DSTypeDNS + ds1.Type = &ds1Type + ds1.QStringIgnore = util.IntPtr(int(tc.QStringIgnoreDrop)) + ds1.OrgServerFQDN = util.StrPtr("http://ds1.example.net") + ds1.MultiSiteOrigin = util.BoolPtr(true) + + dses := []DeliveryService{*ds1} + + parentConfigParams := []tc.Parameter{ + tc.Parameter{ + Name: ParentConfigParamQStringHandling, + ConfigFile: "parent.config", + Value: "myQStringHandlingParam", + Profiles: []byte(`["serverprofile"]`), + }, + tc.Parameter{ + Name: ParentConfigParamAlgorithm, + ConfigFile: "parent.config", + Value: tc.AlgorithmConsistentHash, + Profiles: []byte(`["serverprofile"]`), + }, + tc.Parameter{ + Name: ParentConfigParamQString, + ConfigFile: "parent.config", + Value: "myQstringParam", + Profiles: []byte(`["serverprofile"]`), + }, + } + + serverParams := []tc.Parameter{ + tc.Parameter{ + Name: "trafficserver", + ConfigFile: "package", + Value: "7", + Profiles: []byte(`["global"]`), + }, + } + + server := makeTestParentServer() + server.Cachegroup = util.StrPtr("midCG") + server.Type = "MID" + server.CachegroupID = util.IntPtr(400) + server.ID = util.IntPtr(44) + + origin0 := makeTestParentServer() + origin0.Cachegroup = util.StrPtr("originCG") + origin0.CachegroupID = util.IntPtr(500) + origin0.HostName = util.StrPtr("myorigin0") + origin0.ID = util.IntPtr(45) + setIP(origin0, "192.168.2.2") + origin0.Type = tc.OriginTypeName + origin0.TypeID = util.IntPtr(991) + + origin1 := makeTestParentServer() + origin1.Cachegroup = util.StrPtr("originCG") + origin1.CachegroupID = util.IntPtr(500) + origin1.HostName = util.StrPtr("myorigin1") + origin1.ID = util.IntPtr(46) + setIP(origin1, "192.168.2.3") + origin1.Type = tc.OriginTypeName + origin1.TypeID = util.IntPtr(991) + + servers := []Server{*server, *origin0, *origin1} + + serverCapabilities := map[int]map[ServerCapability]struct{}{ + *server.ID: { + ServerCapability("FOO"): struct{}{}, + }, + } + dsRequiredCapabilities := map[int]map[ServerCapability]struct{}{ + *ds1.ID: { + ServerCapability("FOO"): struct{}{}, + }, + } + + midCG := &tc.CacheGroupNullable{} + midCG.Name = server.Cachegroup + midCG.ID = server.CachegroupID + midCG.ParentName = origin0.Cachegroup + midCG.ParentCachegroupID = origin0.CachegroupID + midCGType := tc.CacheGroupMidTypeName + midCG.Type = &midCGType + + oCG := &tc.CacheGroupNullable{} + oCG.Name = origin0.Cachegroup + oCG.ID = origin0.CachegroupID + oCGType := tc.CacheGroupOriginTypeName + oCG.Type = &oCGType + + cgs := []tc.CacheGroupNullable{*midCG, *oCG} + + dss := []tc.DeliveryServiceServer{ + tc.DeliveryServiceServer{ + Server: util.IntPtr(*origin0.ID), + DeliveryService: util.IntPtr(*ds1.ID), + }, + } + cdn := &tc.CDN{ + DomainName: "cdndomain.example", + Name: "my-cdn-name", + } + topologies := []tc.Topology{} + + cfg, err := MakeParentDotConfig(dses, server, servers, topologies, serverParams, parentConfigParams, serverCapabilities, dsRequiredCapabilities, cgs, dss, cdn, hdr) + if err != nil { + t.Fatal(err) + } + txt := cfg.Text + + testComment(t, txt, hdr) + + if !strings.Contains(txt, "dest_domain=ds1.example.net") { + t.Errorf("expected parent 'dest_domain=ds1.example.net', actual: '%v'", txt) + } + if !strings.Contains(txt, "myorigin0") { + t.Errorf("expected origin0 with DeliveryServiceServer assigned to this DS, actual: '%v'", txt) + } + if strings.Contains(txt, "myorigin1") { + t.Errorf("expected no origin1 without DeliveryServiceServer assigned to this DS, actual: '%v'", txt) + } +} + func TestMakeParentDotConfigTopologiesMSOParams(t *testing.T) { hdr := "myHeaderComment"