in pilot/pkg/model/push_context.go [1732:1825]
func (ps *PushContext) SetDestinationRules(configs []config.Config) {
// Sort by time first. So if two destination rule have top level traffic policies
// we take the first one.
sortConfigByCreationTime(configs)
namespaceLocalDestRules := make(map[string]*consolidatedDestRules)
exportedDestRulesByNamespace := make(map[string]*consolidatedDestRules)
rootNamespaceLocalDestRules := newConsolidatedDestRules()
inheritedConfigs := make(map[string]*consolidatedDestRule)
for i := range configs {
rule := configs[i].Spec.(*networking.DestinationRule)
if features.EnableDestinationRuleInheritance && rule.Host == "" {
if t, ok := inheritedConfigs[configs[i].Namespace]; ok {
log.Warnf("Namespace/mesh-level DestinationRule is already defined for %q at time %v."+
" Ignore %q which was created at time %v",
configs[i].Namespace, t.rule.CreationTimestamp, configs[i].Name, configs[i].CreationTimestamp)
continue
}
inheritedConfigs[configs[i].Namespace] = convertConsolidatedDestRule(&configs[i])
}
rule.Host = string(ResolveShortnameToFQDN(rule.Host, configs[i].Meta))
exportToMap := make(map[visibility.Instance]bool)
// destination rules with workloadSelector should not be exported to other namespaces
if rule.GetWorkloadSelector() == nil {
for _, e := range rule.ExportTo {
exportToMap[visibility.Instance(e)] = true
}
} else {
exportToMap[visibility.Private] = true
}
// add only if the dest rule is exported with . or * or explicit exportTo containing this namespace
// The global exportTo doesn't matter here (its either . or * - both of which are applicable here)
if len(exportToMap) == 0 || exportToMap[visibility.Public] || exportToMap[visibility.Private] ||
exportToMap[visibility.Instance(configs[i].Namespace)] {
// Store in an index for the config's namespace
// a proxy from this namespace will first look here for the destination rule for a given service
// This pool consists of both public/private destination rules.
if _, exist := namespaceLocalDestRules[configs[i].Namespace]; !exist {
namespaceLocalDestRules[configs[i].Namespace] = newConsolidatedDestRules()
}
// Merge this destination rule with any public/private dest rules for same host in the same namespace
// If there are no duplicates, the dest rule will be added to the list
ps.mergeDestinationRule(namespaceLocalDestRules[configs[i].Namespace], configs[i], exportToMap)
}
isPrivateOnly := false
// No exportTo in destinationRule. Use the global default
// We only honor . and *
if len(exportToMap) == 0 && ps.exportToDefaults.destinationRule[visibility.Private] {
isPrivateOnly = true
} else if len(exportToMap) == 1 && (exportToMap[visibility.Private] || exportToMap[visibility.Instance(configs[i].Namespace)]) {
isPrivateOnly = true
}
if !isPrivateOnly {
if _, exist := exportedDestRulesByNamespace[configs[i].Namespace]; !exist {
exportedDestRulesByNamespace[configs[i].Namespace] = newConsolidatedDestRules()
}
// Merge this destination rule with any other exported dest rule for the same host in the same namespace
// If there are no duplicates, the dest rule will be added to the list
ps.mergeDestinationRule(exportedDestRulesByNamespace[configs[i].Namespace], configs[i], exportToMap)
} else if configs[i].Namespace == ps.Mesh.RootNamespace {
// Keep track of private root namespace destination rules
ps.mergeDestinationRule(rootNamespaceLocalDestRules, configs[i], exportToMap)
}
}
// precompute DestinationRules with inherited fields
if features.EnableDestinationRuleInheritance {
globalRule := inheritedConfigs[ps.Mesh.RootNamespace]
for ns := range namespaceLocalDestRules {
nsRule := inheritedConfigs[ns]
inheritedRule := ps.inheritDestinationRule(globalRule, nsRule)
for hostname, cfgList := range namespaceLocalDestRules[ns].destRules {
for i, cfg := range cfgList {
namespaceLocalDestRules[ns].destRules[hostname][i] = ps.inheritDestinationRule(inheritedRule, cfg)
}
}
// update namespace rule after it has been merged with mesh rule
inheritedConfigs[ns] = inheritedRule
}
// can't precalculate exportedDestRulesByNamespace since we don't know all the client namespaces in advance
// inheritance is performed in getExportedDestinationRuleFromNamespace
}
ps.destinationRuleIndex.namespaceLocal = namespaceLocalDestRules
ps.destinationRuleIndex.exportedByNamespace = exportedDestRulesByNamespace
ps.destinationRuleIndex.rootNamespaceLocal = rootNamespaceLocalDestRules
ps.destinationRuleIndex.inheritedByNamespace = inheritedConfigs
}