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]


Reply via email to