Skip to content
This repository was archived by the owner on Nov 24, 2025. It is now read-only.
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
- Fixed searching of the ds parameter merge_parent_groups slice.
- Fixed TO API `PUT /servers/:id/status` to only queue updates on the same CDN as the updated server
- t3c-generate fix for combining remapconfig and cachekeyconfig parameters for MakeRemapDotConfig call.
- [#6780](https://github.com/apache/trafficcontrol/issues/6780) Fixed t3c to use secondary parents when there are no primary parents available.

### Removed
- Remove traffic\_portal dependencies to mitigate `npm audit` issues, specifically `grunt-concurrent`, `grunt-contrib-concat`, `grunt-contrib-cssmin`, `grunt-contrib-jsmin`, `grunt-contrib-uglify`, `grunt-contrib-htmlmin`, `grunt-newer`, and `grunt-wiredep`
Expand Down
8 changes: 7 additions & 1 deletion lib/go-atscfg/parentdotconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -970,7 +970,13 @@ func getTopologyParentConfigLine(
return nil, warnings, errors.New("getting topology parents for '" + *ds.XMLID + "': skipping! " + err.Error())
}
if len(parents) == 0 {
return nil, warnings, errors.New("getting topology parents for '" + *ds.XMLID + "': no parents found! skipping! (Does your Topology have a CacheGroup with no servers in it?)")
if len(secondaryParents) > 0 {
warnings = append(warnings, "getting topology parents for '"+*ds.XMLID+"': no parents found! using secondary parents")
parents = secondaryParents
secondaryParents = nil
} else {
return nil, warnings, errors.New("getting topology parents for '" + *ds.XMLID + "': no parents found! skipping! (Does your Topology have a CacheGroup with no servers in it?)")
}
}

txt.Parents = parents
Expand Down
263 changes: 263 additions & 0 deletions lib/go-atscfg/parentdotconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,122 @@ func TestMakeParentDotConfigMSOSecondaryParent(t *testing.T) {
}
}

func TestMakeParentDotConfigMSONoPrimaryParent(t *testing.T) {
hdr := &ParentConfigOpts{AddComments: false, HdrComment: "myHeaderComment"}

ds0 := makeParentDS()
ds0Type := tc.DSTypeHTTP
ds0.Type = &ds0Type
ds0.QStringIgnore = util.IntPtr(int(tc.QStringIgnoreUseInCacheKeyAndPassUp))
ds0.OrgServerFQDN = util.StrPtr("http://ds0.example.net")
ds0.MultiSiteOrigin = util.BoolPtr(true)
dses := []DeliveryService{*ds0}

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()

mid0 := makeTestParentServer()
mid0.Cachegroup = util.StrPtr("midCG0")
mid0.CachegroupID = util.IntPtr(500)
mid0.HostName = util.StrPtr("my-parent-0")
mid0.DomainName = util.StrPtr("my-parent-0-domain")
mid0.Status = util.StrPtr(string(tc.CacheStatusAdminDown))
mid0.ID = util.IntPtr(45)
setIP(mid0, "192.168.2.2")

mid1 := makeTestParentServer()
mid1.Cachegroup = util.StrPtr("midCG1")
mid1.CachegroupID = util.IntPtr(501)
mid1.HostName = util.StrPtr("my-parent-1")
mid1.DomainName = util.StrPtr("my-parent-1-domain")
mid1.ID = util.IntPtr(46)
setIP(mid1, "192.168.2.3")

servers := []Server{*server, *mid0, *mid1}

topologies := []tc.Topology{}
serverCapabilities := map[int]map[ServerCapability]struct{}{}
dsRequiredCapabilities := map[int]map[ServerCapability]struct{}{}

eCG := &tc.CacheGroupNullable{}
eCG.Name = server.Cachegroup
eCG.ID = server.CachegroupID
eCG.ParentName = mid0.Cachegroup
eCG.ParentCachegroupID = mid0.CachegroupID
eCG.SecondaryParentName = mid1.Cachegroup
eCG.SecondaryParentCachegroupID = mid1.CachegroupID
eCGType := tc.CacheGroupEdgeTypeName
eCG.Type = &eCGType

mCG := &tc.CacheGroupNullable{}
mCG.Name = mid0.Cachegroup
mCG.ID = mid0.CachegroupID
mCGType := tc.CacheGroupMidTypeName
mCG.Type = &mCGType

mCG1 := &tc.CacheGroupNullable{}
mCG1.Name = mid1.Cachegroup
mCG1.ID = mid1.CachegroupID
mCGType1 := tc.CacheGroupMidTypeName
mCG1.Type = &mCGType1

cgs := []tc.CacheGroupNullable{*eCG, *mCG, *mCG1}

dss := []DeliveryServiceServer{
DeliveryServiceServer{
Server: *server.ID,
DeliveryService: *ds0.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.HdrComment)

txtx := strings.Replace(txt, " ", "", -1)

if !strings.Contains(txtx, `parent="my-parent-1.my-parent-1-domain:80|0.999`) {
t.Errorf("expected primary parent 'my-parent-1.my-parent-1-domain', actual: '%v'", txt)
}
}

func TestMakeParentDotConfigTopologies(t *testing.T) {
hdr := &ParentConfigOpts{AddComments: false, HdrComment: "myHeaderComment"}

Expand Down Expand Up @@ -2932,6 +3048,153 @@ func TestMakeParentDotConfigHTTPSOriginTopology(t *testing.T) {
}
}

func TestMakeParentDotConfigHTTPSOriginTopologyNoPrimaryParent(t *testing.T) {
hdr := &ParentConfigOpts{AddComments: true, HdrComment: "myHeaderComment"}

ds0 := makeParentDS()
ds0Type := tc.DSTypeHTTP
ds0.Type = &ds0Type
ds0.QStringIgnore = util.IntPtr(int(tc.QStringIgnoreUseInCacheKeyAndPassUp))
ds0.OrgServerFQDN = util.StrPtr("https://ds0.example.net")
ds0.ProfileID = util.IntPtr(311)
ds0.ProfileName = util.StrPtr("ds0Profile")

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.ProfileID = util.IntPtr(312)
ds1.ProfileName = util.StrPtr("ds1Profile")

dses := []DeliveryService{*ds0, *ds1}

parentConfigParams := []tc.Parameter{
{
Name: ParentConfigParamQStringHandling,
ConfigFile: "parent.config",
Value: "myQStringHandlingParam",
Profiles: []byte(`["serverprofile"]`),
},
{
Name: ParentConfigParamAlgorithm,
ConfigFile: "parent.config",
Value: tc.AlgorithmConsistentHash,
Profiles: []byte(`["serverprofile"]`),
},
{
Name: ParentConfigParamQString,
ConfigFile: "parent.config",
Value: "myQstringParam",
Profiles: []byte(`["serverprofile"]`),
},
}

serverParams := []tc.Parameter{
{
Name: "trafficserver",
ConfigFile: "package",
Value: "8",
Profiles: []byte(`["global"]`),
},
}

server := makeTestParentServer()
server.Cachegroup = util.StrPtr("edgeCG")
server.CachegroupID = util.IntPtr(400)

mid0 := makeTestParentServer()
mid0.Cachegroup = util.StrPtr("midCG")
mid0.CachegroupID = util.IntPtr(500)
mid0.HostName = util.StrPtr("mymid")
mid0.ID = util.IntPtr(45)
mid0.Status = util.StrPtr(string(tc.CacheStatusAdminDown))
setIP(mid0, "192.168.2.2")

mid1 := makeTestParentServer()
mid1.Cachegroup = util.StrPtr("midCG2")
mid1.CachegroupID = util.IntPtr(501)
mid1.HostName = util.StrPtr("mymid1")
mid1.ID = util.IntPtr(46)
setIP(mid1, "192.168.2.3")

servers := []Server{*server, *mid0, *mid1}

topologies := []tc.Topology{
{
Name: "t0",
Nodes: []tc.TopologyNode{
{
Cachegroup: "edgeCG",
Parents: []int{1, 2},
},
{
Cachegroup: "midCG",
},
{
Cachegroup: "midCG2",
},
},
},
}

serverCapabilities := map[int]map[ServerCapability]struct{}{}
dsRequiredCapabilities := map[int]map[ServerCapability]struct{}{}

eCG := &tc.CacheGroupNullable{}
eCG.Name = server.Cachegroup
eCG.ID = server.CachegroupID
eCG.ParentName = mid0.Cachegroup
eCG.ParentCachegroupID = mid0.CachegroupID
eCG.SecondaryParentName = mid1.Cachegroup
eCG.SecondaryParentCachegroupID = mid1.CachegroupID
eCGType := tc.CacheGroupEdgeTypeName
eCG.Type = &eCGType

mCG := &tc.CacheGroupNullable{}
mCG.Name = mid0.Cachegroup
mCG.ID = mid0.CachegroupID
mCGType := tc.CacheGroupMidTypeName
mCG.Type = &mCGType

mCG2 := &tc.CacheGroupNullable{}
mCG2.Name = mid1.Cachegroup
mCG2.ID = mid1.CachegroupID
mCGType2 := tc.CacheGroupMidTypeName
mCG2.Type = &mCGType2

cgs := []tc.CacheGroupNullable{*eCG, *mCG, *mCG2}

dss := []DeliveryServiceServer{
{
Server: *server.ID,
DeliveryService: *ds0.ID,
},
{
Server: *server.ID,
DeliveryService: *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.HdrComment)

if !strings.Contains(txt, `parent="mymid1.mydomain.example.net:80|0.999"`) {
t.Errorf("expected topology parent.config withparent=\"mymid1.mydomain.example.net:80|0.999\", actual: '%v'", txt)
}
}

func TestMakeParentDotConfigMergeParentGroupTopology(t *testing.T) {
hdr := &ParentConfigOpts{AddComments: true, HdrComment: "myHeaderComment"}

Expand Down