Skip to content

Commit a497e86

Browse files
authored
Fix private destination rules in root namespace (#25962)
* Fix private destination rules in root namespace Fixes #25253 * Move ordering * Fix inverted logic * Fix format
1 parent 59cf804 commit a497e86

File tree

2 files changed

+69
-25
lines changed

2 files changed

+69
-25
lines changed

pilot/pkg/model/push_context.go

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ type PushContext struct {
100100
// exportedDestRulesByNamespace: all dest rules pertaining to a service exported by a namespace
101101
namespaceLocalDestRules map[string]*processedDestRules
102102
exportedDestRulesByNamespace map[string]*processedDestRules
103+
rootNamespaceLocalDestRules *processedDestRules
103104

104105
// clusterLocalHosts extracted from the MeshConfig
105106
clusterLocalHosts host.Names
@@ -702,6 +703,14 @@ func (ps *PushContext) DestinationRule(proxy *Proxy, service *Service) *Config {
702703
return ps.namespaceLocalDestRules[proxy.ConfigNamespace].destRule[hostname]
703704
}
704705
}
706+
} else {
707+
// If this is a namespace local DR in the same namespace, this must be meant for this proxy, so we do not
708+
// need to worry about overriding other DRs with *.local type rules here. If we ignore this, then exportTo=. in
709+
// root namespace would always be ignored
710+
if hostname, ok := MostSpecificHostMatch(service.Hostname,
711+
ps.rootNamespaceLocalDestRules.hosts); ok {
712+
return ps.rootNamespaceLocalDestRules.destRule[hostname]
713+
}
705714
}
706715

707716
// 2. select destination rule from service namespace
@@ -729,7 +738,6 @@ func (ps *PushContext) DestinationRule(proxy *Proxy, service *Service) *Config {
729738

730739
// 4. if no public/private rule in calling proxy's namespace matched, and no public rule in the
731740
// target service's namespace matched, search for any exported destination rule in the config root namespace
732-
// NOTE: This does mean that we are effectively ignoring private dest rules in the config root namespace
733741
if out := ps.getExportedDestinationRuleFromNamespace(ps.Mesh.RootNamespace, service.Hostname, proxy.ConfigNamespace); out != nil {
734742
return out
735743
}
@@ -927,6 +935,7 @@ func (ps *PushContext) updateContext(
927935
} else {
928936
ps.namespaceLocalDestRules = oldPushContext.namespaceLocalDestRules
929937
ps.exportedDestRulesByNamespace = oldPushContext.exportedDestRulesByNamespace
938+
ps.rootNamespaceLocalDestRules = oldPushContext.rootNamespaceLocalDestRules
930939
}
931940

932941
if authnChanged {
@@ -1303,6 +1312,14 @@ func (ps *PushContext) initDestinationRules(env *Environment) error {
13031312
return nil
13041313
}
13051314

1315+
func newProcessedDestRules() *processedDestRules {
1316+
return &processedDestRules{
1317+
hosts: make([]host.Name, 0),
1318+
exportTo: map[host.Name]map[visibility.Instance]bool{},
1319+
destRule: map[host.Name]*Config{},
1320+
}
1321+
}
1322+
13061323
// SetDestinationRules is updates internal structures using a set of configs.
13071324
// Split out of DestinationRule expensive conversions, computed once per push.
13081325
// This also allows tests to inject a config without having the mock.
@@ -1313,6 +1330,7 @@ func (ps *PushContext) SetDestinationRules(configs []Config) {
13131330
sortConfigByCreationTime(configs)
13141331
namespaceLocalDestRules := make(map[string]*processedDestRules)
13151332
exportedDestRulesByNamespace := make(map[string]*processedDestRules)
1333+
rootNamespaceLocalDestRules := newProcessedDestRules()
13161334

13171335
for i := range configs {
13181336
rule := configs[i].Spec.(*networking.DestinationRule)
@@ -1329,11 +1347,7 @@ func (ps *PushContext) SetDestinationRules(configs []Config) {
13291347
// a proxy from this namespace will first look here for the destination rule for a given service
13301348
// This pool consists of both public/private destination rules.
13311349
if _, exist := namespaceLocalDestRules[configs[i].Namespace]; !exist {
1332-
namespaceLocalDestRules[configs[i].Namespace] = &processedDestRules{
1333-
hosts: make([]host.Name, 0),
1334-
exportTo: map[host.Name]map[visibility.Instance]bool{},
1335-
destRule: map[host.Name]*Config{},
1336-
}
1350+
namespaceLocalDestRules[configs[i].Namespace] = newProcessedDestRules()
13371351
}
13381352
// Merge this destination rule with any public/private dest rules for same host in the same namespace
13391353
// If there are no duplicates, the dest rule will be added to the list
@@ -1351,15 +1365,14 @@ func (ps *PushContext) SetDestinationRules(configs []Config) {
13511365

13521366
if !isPrivateOnly {
13531367
if _, exist := exportedDestRulesByNamespace[configs[i].Namespace]; !exist {
1354-
exportedDestRulesByNamespace[configs[i].Namespace] = &processedDestRules{
1355-
hosts: make([]host.Name, 0),
1356-
exportTo: map[host.Name]map[visibility.Instance]bool{},
1357-
destRule: map[host.Name]*Config{},
1358-
}
1368+
exportedDestRulesByNamespace[configs[i].Namespace] = newProcessedDestRules()
13591369
}
13601370
// Merge this destination rule with any other exported dest rule for the same host in the same namespace
13611371
// If there are no duplicates, the dest rule will be added to the list
13621372
ps.mergeDestinationRule(exportedDestRulesByNamespace[configs[i].Namespace], configs[i], exportToMap)
1373+
} else if configs[i].Namespace == ps.Mesh.RootNamespace {
1374+
// Keep track of private root namespace destination rules
1375+
ps.mergeDestinationRule(rootNamespaceLocalDestRules, configs[i], exportToMap)
13631376
}
13641377
}
13651378

@@ -1374,6 +1387,7 @@ func (ps *PushContext) SetDestinationRules(configs []Config) {
13741387

13751388
ps.namespaceLocalDestRules = namespaceLocalDestRules
13761389
ps.exportedDestRulesByNamespace = exportedDestRulesByNamespace
1390+
ps.rootNamespaceLocalDestRules = rootNamespaceLocalDestRules
13771391
}
13781392

13791393
func (ps *PushContext) initAuthorizationPolicies(env *Environment) error {

pilot/pkg/model/push_context_test.go

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -520,8 +520,26 @@ func TestSetDestinationRuleWithExportTo(t *testing.T) {
520520
},
521521
},
522522
}
523+
destinationRuleRootNamespaceLocal := Config{
524+
ConfigMeta: ConfigMeta{
525+
Name: "rule1",
526+
Namespace: "istio-system",
527+
},
528+
Spec: &networking.DestinationRule{
529+
Host: testhost,
530+
ExportTo: []string{"."},
531+
Subsets: []*networking.Subset{
532+
{
533+
Name: "subset9",
534+
},
535+
{
536+
Name: "subset10",
537+
},
538+
},
539+
},
540+
}
523541
ps.SetDestinationRules([]Config{destinationRuleNamespace1, destinationRuleNamespace2,
524-
destinationRuleNamespace3, destinationRuleRootNamespace})
542+
destinationRuleNamespace3, destinationRuleRootNamespace, destinationRuleRootNamespaceLocal})
525543
cases := []struct {
526544
proxyNs string
527545
serviceNs string
@@ -567,21 +585,33 @@ func TestSetDestinationRuleWithExportTo(t *testing.T) {
567585
serviceNs: "random",
568586
wantSubsets: []string{"subset5", "subset6"},
569587
},
588+
{
589+
proxyNs: "istio-system",
590+
serviceNs: "random",
591+
wantSubsets: []string{"subset9", "subset10"},
592+
},
593+
{
594+
proxyNs: "istio-system",
595+
serviceNs: "istio-system",
596+
wantSubsets: []string{"subset9", "subset10"},
597+
},
570598
}
571599
for _, tt := range cases {
572-
destRuleConfig := ps.DestinationRule(&Proxy{ConfigNamespace: tt.proxyNs},
573-
&Service{Hostname: host.Name(testhost), Attributes: ServiceAttributes{Namespace: tt.serviceNs}})
574-
if destRuleConfig == nil {
575-
t.Fatalf("proxy in %s namespace: dest rule is nil, expected subsets %+v", tt.proxyNs, tt.wantSubsets)
576-
}
577-
destRule := destRuleConfig.Spec.(*networking.DestinationRule)
578-
var gotSubsets []string
579-
for _, ss := range destRule.Subsets {
580-
gotSubsets = append(gotSubsets, ss.Name)
581-
}
582-
if !reflect.DeepEqual(gotSubsets, tt.wantSubsets) {
583-
t.Fatalf("proxy in %s namespace: want %+v, got %+v", tt.proxyNs, tt.wantSubsets, gotSubsets)
584-
}
600+
t.Run(fmt.Sprintf("%s-%s", tt.proxyNs, tt.serviceNs), func(t *testing.T) {
601+
destRuleConfig := ps.DestinationRule(&Proxy{ConfigNamespace: tt.proxyNs},
602+
&Service{Hostname: host.Name(testhost), Attributes: ServiceAttributes{Namespace: tt.serviceNs}})
603+
if destRuleConfig == nil {
604+
t.Fatalf("proxy in %s namespace: dest rule is nil, expected subsets %+v", tt.proxyNs, tt.wantSubsets)
605+
}
606+
destRule := destRuleConfig.Spec.(*networking.DestinationRule)
607+
var gotSubsets []string
608+
for _, ss := range destRule.Subsets {
609+
gotSubsets = append(gotSubsets, ss.Name)
610+
}
611+
if !reflect.DeepEqual(gotSubsets, tt.wantSubsets) {
612+
t.Fatalf("want %+v, got %+v", tt.wantSubsets, gotSubsets)
613+
}
614+
})
585615
}
586616
}
587617

0 commit comments

Comments
 (0)