zrhoffman commented on a change in pull request #4790:
URL: https://github.com/apache/trafficcontrol/pull/4790#discussion_r465618519
##########
File path: lib/go-atscfg/atscfg.go
##########
@@ -139,24 +140,109 @@ func GetConfigFile(prefix string, xmlId string) string {
// topologyIncludesServer returns whether the given topology includes the
given server
func topologyIncludesServer(topology tc.Topology, server tc.Server) bool {
- _, inTopology := serverTopologyTier(server, topology)
- return inTopology
+ for _, node := range topology.Nodes {
+ if node.Cachegroup == server.Cachegroup {
+ return true
+ }
+ }
+ return false
}
-// serverTopologyTier returns whether the server is the last tier in the
topology, and whether the server is in the topology at all.
-func serverTopologyTier(server tc.Server, topology tc.Topology) (bool, bool) {
+// TopologyCacheTier is the position of a cache in the topology.
+// Note this is the cache tier itself, notwithstanding MSO. So for an MSO
service,
+// Caches immediately before the origin are the TopologyCacheTierLast, even
for MSO.
+type TopologyCacheTier string
+
+const (
+ TopologyCacheTierFirst = TopologyCacheTier("first")
+ TopologyCacheTierInner = TopologyCacheTier("inner")
+ TopologyCacheTierLast = TopologyCacheTier("last")
+ TopologyCacheTierInvalid = TopologyCacheTier("")
+)
+
+// TopologyPlacement contains data about the placement of a server in a
topology.
+type TopologyPlacement struct {
+ // InTopology is whether the server is in the topology at all.
+ InTopology bool
+ // IsLastTier is whether the server is the last tier in the topology.
+ // Note this is different for MSO vs non-MSO. For MSO, the last tier is
the Origin. For non-MSO, the last tier is the last cache tier.
+ IsLastTier bool
+ // CacheTier is the position of the cache in the topology.
+ // Note this is whether the cache is the last cache, even if it has
parents in the topology who are origins (MSO).
+ // Thus, it's possible for a server to be CacheTierLast and not
IsLastTier.
+ CacheTier TopologyCacheTier
+}
+
+// getTopologyPlacement returns information about the cachegroup's placement
in the topology.
+// - Whether the cachegroup is the last tier in the topology.
+// - Whether the cachegroup is in the topology at all.
+// - Whether it's the first, inner, or last cache tier before the Origin.
+func getTopologyPlacement(cacheGroup tc.CacheGroupName, topology tc.Topology,
cacheGroups map[tc.CacheGroupName]tc.CacheGroupNullable) TopologyPlacement {
serverNode := tc.TopologyNode{}
- for _, node := range topology.Nodes {
- if node.Cachegroup == server.Cachegroup {
+ serverNodeIndex := -1
+ for nodeI, node := range topology.Nodes {
+ if node.Cachegroup == string(cacheGroup) {
serverNode = node
+ serverNodeIndex = nodeI
break
}
}
if serverNode.Cachegroup == "" {
- return false, false
+ return TopologyPlacement{InTopology: false}
}
- return len(serverNode.Parents) == 0, true
+ topologyHasChildren := false
+ for _, node := range topology.Nodes {
+ for _, parent := range node.Parents {
+ if parent == serverNodeIndex {
+ topologyHasChildren = true
+ break
+ }
+ }
+ }
Review comment:
Should break out of the outer loop if `topologyHasChildren` is true
##########
File path: lib/go-atscfg/atscfg.go
##########
@@ -139,24 +140,109 @@ func GetConfigFile(prefix string, xmlId string) string {
// topologyIncludesServer returns whether the given topology includes the
given server
func topologyIncludesServer(topology tc.Topology, server tc.Server) bool {
- _, inTopology := serverTopologyTier(server, topology)
- return inTopology
+ for _, node := range topology.Nodes {
+ if node.Cachegroup == server.Cachegroup {
+ return true
+ }
+ }
+ return false
}
-// serverTopologyTier returns whether the server is the last tier in the
topology, and whether the server is in the topology at all.
-func serverTopologyTier(server tc.Server, topology tc.Topology) (bool, bool) {
+// TopologyCacheTier is the position of a cache in the topology.
+// Note this is the cache tier itself, notwithstanding MSO. So for an MSO
service,
+// Caches immediately before the origin are the TopologyCacheTierLast, even
for MSO.
+type TopologyCacheTier string
+
+const (
+ TopologyCacheTierFirst = TopologyCacheTier("first")
+ TopologyCacheTierInner = TopologyCacheTier("inner")
+ TopologyCacheTierLast = TopologyCacheTier("last")
+ TopologyCacheTierInvalid = TopologyCacheTier("")
+)
+
+// TopologyPlacement contains data about the placement of a server in a
topology.
+type TopologyPlacement struct {
+ // InTopology is whether the server is in the topology at all.
+ InTopology bool
+ // IsLastTier is whether the server is the last tier in the topology.
+ // Note this is different for MSO vs non-MSO. For MSO, the last tier is
the Origin. For non-MSO, the last tier is the last cache tier.
+ IsLastTier bool
+ // CacheTier is the position of the cache in the topology.
+ // Note this is whether the cache is the last cache, even if it has
parents in the topology who are origins (MSO).
+ // Thus, it's possible for a server to be CacheTierLast and not
IsLastTier.
+ CacheTier TopologyCacheTier
+}
+
+// getTopologyPlacement returns information about the cachegroup's placement
in the topology.
+// - Whether the cachegroup is the last tier in the topology.
+// - Whether the cachegroup is in the topology at all.
+// - Whether it's the first, inner, or last cache tier before the Origin.
+func getTopologyPlacement(cacheGroup tc.CacheGroupName, topology tc.Topology,
cacheGroups map[tc.CacheGroupName]tc.CacheGroupNullable) TopologyPlacement {
serverNode := tc.TopologyNode{}
- for _, node := range topology.Nodes {
- if node.Cachegroup == server.Cachegroup {
+ serverNodeIndex := -1
+ for nodeI, node := range topology.Nodes {
+ if node.Cachegroup == string(cacheGroup) {
serverNode = node
+ serverNodeIndex = nodeI
break
}
}
if serverNode.Cachegroup == "" {
- return false, false
+ return TopologyPlacement{InTopology: false}
}
- return len(serverNode.Parents) == 0, true
+ topologyHasChildren := false
Review comment:
A name like `topologyNodeHasChildren` or `nodeHasChildren` might make
more sense here
##########
File path: lib/go-atscfg/topologyheaderrewritedotconfig.go
##########
@@ -0,0 +1,140 @@
+package atscfg
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import (
+ "math"
+ "strconv"
+
+ "github.com/apache/trafficcontrol/lib/go-log"
+ "github.com/apache/trafficcontrol/lib/go-tc"
+)
+
+const HeaderRewriteFirstPrefix = HeaderRewritePrefix + "first_"
+const HeaderRewriteInnerPrefix = HeaderRewritePrefix + "inner_"
+const HeaderRewriteLastPrefix = HeaderRewritePrefix + "last_"
+
+func FirstHeaderRewriteConfigFileName(dsName string) string {
+ return HeaderRewriteFirstPrefix + dsName + ConfigSuffix
+}
+
+func InnerHeaderRewriteConfigFileName(dsName string) string {
+ return HeaderRewriteInnerPrefix + dsName + ConfigSuffix
+}
+
+func LastHeaderRewriteConfigFileName(dsName string) string {
+ return HeaderRewriteLastPrefix + dsName + ConfigSuffix
+}
+
+func MakeTopologyHeaderRewriteDotConfig(
+ server tc.Server,
+ toToolName string, // tm.toolname global parameter (TODO: cache itself?)
+ toURL string, // tm.url global parameter (TODO: cache itself?)
+ ds tc.DeliveryServiceNullable,
+ topologies []tc.Topology,
+ cacheGroupArr []tc.CacheGroupNullable,
+ servers []tc.Server,
+ serverCapabilities map[int]map[ServerCapability]struct{},
+ dsRequiredCapabilities map[ServerCapability]struct{},
+) string {
+ text := GenericHeaderComment(server.HostName, toToolName, toURL)
+
+ cacheGroups := MakeCGMap(cacheGroupArr)
+
+ if ds.Topology == nil || *ds.Topology == "" {
+ log.Errorln("Config generation: Topology Header Rewrite called
for DS '" + *ds.XMLID + "' with no Topology! This should never be called, a DS
with no topology should never have a First, Inner, or Last Header Rewrite
config in the list of config files! Returning blank config!")
+ return text
+ }
+
+ topology := tc.Topology{}
+ for _, to := range topologies {
+ if to.Name == *ds.Topology {
+ topology = to
+ break
+ }
+ }
Review comment:
Another place where a *topologies by DS name* map would be useful
(though it doesn't make sense to build it here).
##########
File path: traffic_ops_ort/atstccfg/config/config.go
##########
@@ -297,4 +297,8 @@ type TOData struct {
// SSLKeys must be all the ssl keys for the server's cdn.
SSLKeys []tc.CDNSSLKeys
+
+ // Topologies must be all the topologies for the server's cdn.
+ // May incude topologies of other cdns.
+ Topologies []tc.Topology
Review comment:
Is there any advantage to having topologies not assigned to any DS? If
not, including a *topologies by DS name* map in `TOData` instead of a topology
array might make more sense here, since there are several places where we need
to get a topology, given a certain DS.
##########
File path: lib/go-atscfg/meta.go
##########
@@ -146,24 +151,64 @@ func AddMetaObjConfigDir(
log.Errorln("meta config generation got Delivery
Service with nil XMLID - not considering!")
continue
}
+
err := error(nil)
// Note we log errors, but don't return them.
// If an individual DS has an error, we don't want to break the
rest of the CDN.
- if (ds.EdgeHeaderRewrite != nil || ds.MaxOriginConnections !=
nil) &&
- strings.HasPrefix(server.Type, tc.EdgeTypePrefix) {
- fileName := "hdr_rw_" + *ds.XMLID + ".config"
- scope := tc.ATSConfigMetaDataConfigFileScopeCDNs
- if configFilesM, err = ensureConfigFile(configFilesM,
fileName, configDir, scope); err != nil {
- log.Errorln("meta config generation: " +
err.Error())
+ if ds.Topology != nil && *ds.Topology != "" {
+ topology := tc.Topology{}
+ for _, to := range topologies {
+ if to.Name == *ds.Topology {
+ topology = to
+ break
+ }
}
Review comment:
We have a `tc.DeliveryServiceNullable` array and a `tc.Topology` array
in this scope, consider calling `atscfg.hostingMakeDSTopologies()` to get a
*topologies by DS name* map so that running time is *number of DSes + number of
Topologies* instead of *number of DSes \* number of Topologies* like it
currently is.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]