@@ -18,15 +18,24 @@ import (
18
18
"fmt"
19
19
20
20
networking "istio.io/api/networking/v1alpha3"
21
+
22
+ "istio.io/istio/pkg/config/visibility"
21
23
)
22
24
23
25
// This function merges one or more destination rules for a given host string
24
26
// into a single destination rule. Note that it does not perform inheritance style merging.
25
27
// IOW, given three dest rules (*.foo.com, *.foo.com, *.com), calling this function for
26
28
// each config will result in a final dest rule set (*.foo.com, and *.com).
27
- func (ps * PushContext ) mergeDestinationRule (p * processedDestRules , destRuleConfig Config ) {
29
+ //
30
+ // The following is the merge logic:
31
+ // 1. Unique subsets (based on subset name) are concatenated to the original rule's list of subsets
32
+ // 2. If the original rule did not have any top level traffic policy, traffic policies from the new rule will be
33
+ // used.
34
+ // 3. If the original rule did not have any exportTo, exportTo settings from the new rule will be used.
35
+ func (ps * PushContext ) mergeDestinationRule (p * processedDestRules , destRuleConfig Config , exportToMap map [visibility.Instance ]bool ) {
28
36
rule := destRuleConfig .Spec .(* networking.DestinationRule )
29
37
resolvedHost := ResolveShortnameToFQDN (rule .Host , destRuleConfig .ConfigMeta )
38
+
30
39
if mdr , exists := p .destRule [resolvedHost ]; exists {
31
40
// Deep copy destination rule, to prevent mutate it later when merge with a new one.
32
41
// This can happen when there are more than one destination rule of same host in one namespace.
@@ -39,6 +48,8 @@ func (ps *PushContext) mergeDestinationRule(p *processedDestRules, destRuleConfi
39
48
}
40
49
// we have an another destination rule for same host.
41
50
// concatenate both of them -- essentially add subsets from one to other.
51
+ // Note: we only add the subsets and do not overwrite anything else like exportTo or top level
52
+ // traffic policies if they already exist
42
53
for _ , subset := range rule .Subsets {
43
54
if _ , ok := existingSubset [subset .Name ]; ! ok {
44
55
// if not duplicated, append
@@ -56,10 +67,18 @@ func (ps *PushContext) mergeDestinationRule(p *processedDestRules, destRuleConfi
56
67
if mergedRule .TrafficPolicy == nil && rule .TrafficPolicy != nil {
57
68
mergedRule .TrafficPolicy = rule .TrafficPolicy
58
69
}
70
+
71
+ // If there is no exportTo in the existing rule and
72
+ // the incoming rule has an explicit exportTo, use the
73
+ // one from the incoming rule.
74
+ if len (p .exportTo [resolvedHost ]) == 0 && len (exportToMap ) > 0 {
75
+ p .exportTo [resolvedHost ] = exportToMap
76
+ }
59
77
return
60
78
}
61
79
62
80
// DestinationRule does not exist for the resolved host so add it
63
81
p .hosts = append (p .hosts , resolvedHost )
64
82
p .destRule [resolvedHost ] = & destRuleConfig
83
+ p .exportTo [resolvedHost ] = exportToMap
65
84
}
0 commit comments