blob: dc42ff5cda7355386680abdf7ce5a22e292a10a1 [file] [log] [blame]
// Copyright Istio Authors
//
// Licensed 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.
package mesh_test
import (
"fmt"
"testing"
)
import (
"github.com/google/go-cmp/cmp"
"google.golang.org/protobuf/testing/protocmp"
"google.golang.org/protobuf/types/known/wrapperspb"
meshconfig "istio.io/api/mesh/v1alpha1"
)
import (
"github.com/apache/dubbo-go-pixiu/pkg/config/mesh"
"github.com/apache/dubbo-go-pixiu/pkg/config/validation"
"github.com/apache/dubbo-go-pixiu/pkg/test/util/assert"
"github.com/apache/dubbo-go-pixiu/pkg/util/protomarshal"
)
func TestApplyProxyConfig(t *testing.T) {
config := mesh.DefaultMeshConfig()
defaultDiscovery := config.DefaultConfig.DiscoveryAddress
t.Run("apply single", func(t *testing.T) {
mc, err := mesh.ApplyProxyConfig("discoveryAddress: foo", config)
if err != nil {
t.Fatal(err)
}
if mc.DefaultConfig.DiscoveryAddress != "foo" {
t.Fatalf("expected discoveryAddress: foo, got %q", mc.DefaultConfig.DiscoveryAddress)
}
})
t.Run("apply again", func(t *testing.T) {
mc, err := mesh.ApplyProxyConfig("drainDuration: 5s", config)
if err != nil {
t.Fatal(err)
}
// Ensure we didn't modify the passed in mesh config
if mc.DefaultConfig.DiscoveryAddress != defaultDiscovery {
t.Fatalf("expected discoveryAddress: %q, got %q", defaultDiscovery, mc.DefaultConfig.DiscoveryAddress)
}
if mc.DefaultConfig.DrainDuration.Seconds != 5 {
t.Fatalf("expected drainDuration: 5s, got %q", mc.DefaultConfig.DrainDuration.Seconds)
}
})
t.Run("apply proxy metadata", func(t *testing.T) {
config := mesh.DefaultMeshConfig()
config.DefaultConfig.ProxyMetadata = map[string]string{
"merged": "original",
"default": "foo",
}
mc, err := mesh.ApplyProxyConfig(`proxyMetadata: {"merged":"override","override":"bar"}`, config)
assert.NoError(t, err)
// Ensure we didn't modify the passed in mesh config
assert.Equal(t, mc.DefaultConfig.ProxyMetadata, map[string]string{
"merged": "override",
"default": "foo",
"override": "bar",
}, "unexpected proxy metadata")
})
t.Run("apply proxy metadata to mesh config", func(t *testing.T) {
config := mesh.DefaultMeshConfig()
config.DefaultConfig.ProxyMetadata = map[string]string{
"merged": "original",
"default": "foo",
}
mc, err := mesh.ApplyMeshConfig(`defaultConfig:
proxyMetadata: {"merged":"override","override":"bar"}`, config)
if err != nil {
t.Fatal(err)
}
// Ensure we didn't modify the passed in mesh config
assert.Equal(t, mc.DefaultConfig.ProxyMetadata, map[string]string{
"merged": "override",
"default": "foo",
"override": "bar",
}, "unexpected proxy metadata")
})
t.Run("apply should not modify", func(t *testing.T) {
config := mesh.DefaultMeshConfig()
config.DefaultConfig.ProxyMetadata = map[string]string{
"foo": "bar",
}
orig, err := protomarshal.ToYAML(config)
if err != nil {
t.Fatal(err)
}
if _, err := mesh.ApplyProxyConfig(`proxyMetadata: {"merged":"override","override":"bar"}`, config); err != nil {
t.Fatal(err)
}
after, err := protomarshal.ToYAML(config)
if err != nil {
t.Fatal(err)
}
if orig != after {
t.Fatalf("Changed before and after. Expected %v, got %v", orig, after)
}
})
}
func TestDefaultProxyConfig(t *testing.T) {
if err := validation.ValidateMeshConfigProxyConfig(mesh.DefaultProxyConfig()); err != nil {
t.Errorf("validation of default proxy config failed with %v", err)
}
}
func TestDefaultMeshConfig(t *testing.T) {
if err := validation.ValidateMeshConfig(mesh.DefaultMeshConfig()); err != nil {
t.Errorf("validation of default mesh config failed with %v", err)
}
}
func TestApplyMeshConfigDefaults(t *testing.T) {
configPath := "/test/config/patch"
yaml := fmt.Sprintf(`
defaultConfig:
configPath: %s
`, configPath)
want := mesh.DefaultMeshConfig()
want.DefaultConfig.ConfigPath = configPath
got, err := mesh.ApplyMeshConfigDefaults(yaml)
if err != nil {
t.Fatalf("ApplyMeshConfigDefaults() failed: %v", err)
}
assert.Equal(t, got, want)
// Verify overrides
got, err = mesh.ApplyMeshConfigDefaults(`
serviceSettings:
- settings:
clusterLocal: true
host:
- "*.myns.svc.cluster.local"
ingressClass: foo
enableTracing: false
trustDomainAliases: ["default", "both"]
defaultServiceExportTo:
- "foo"
outboundTrafficPolicy:
mode: REGISTRY_ONLY
clusterLocalNamespaces:
- "foons"
defaultProviders:
tracing: [foo]
extensionProviders:
- name: sd
stackdriver: {}
defaultConfig:
tracing: {}
concurrency: 4`)
if err != nil {
t.Fatal(err)
}
if got.DefaultConfig.Tracing.GetZipkin() != nil {
t.Error("Failed to override tracing")
}
if len(got.DefaultProviders.GetMetrics()) != 0 {
t.Errorf("default providers deep merge failed, got %v", got.DefaultProviders.GetMetrics())
}
if !cmp.Equal(getExtensionProviders(got.ExtensionProviders), []string{"prometheus", "stackdriver", "envoy", "sd"}, protocmp.Transform()) {
t.Errorf("extension providers deep merge failed, got %v", getExtensionProviders(got.ExtensionProviders))
}
if len(got.TrustDomainAliases) != 2 {
t.Errorf("trust domain aliases deep merge failed")
}
gotY, err := protomarshal.ToYAML(got)
t.Log("Result: \n", gotY, err)
}
func getExtensionProviders(eps []*meshconfig.MeshConfig_ExtensionProvider) []string {
got := []string{}
for _, ep := range eps {
got = append(got, ep.Name)
}
return got
}
func TestDeepMerge(t *testing.T) {
cases := []struct {
name string
in string
out string
}{
{
name: "set other default provider",
in: `
defaultProviders:
tracing: [foo]`,
out: `defaultProviders:
metrics:
- stackdriver
tracing:
- foo
extensionProviders:
- name: stackdriver
stackdriver:
maxNumberOfAttributes: 3
trustDomainAliases: ["both", "default"]
`,
},
{
name: "override default provider",
in: `
defaultProviders:
metrics: [foo]`,
out: `defaultProviders:
metrics:
- foo
extensionProviders:
- name: stackdriver
stackdriver:
maxNumberOfAttributes: 3
trustDomainAliases: ["both", "default"]
`,
},
{
name: "replace builtin provider",
in: `
extensionProviders:
- name: stackdriver
stackdriver:
maxNumberOfAnnotations: 5`,
out: `defaultProviders:
metrics:
- stackdriver
extensionProviders:
- name: stackdriver
stackdriver:
maxNumberOfAnnotations: 5
trustDomainAliases: ["both", "default"]
`,
},
{
name: "add provider with existing type",
in: `
extensionProviders:
- name: stackdriver-annotations
stackdriver:
maxNumberOfAnnotations: 5`,
out: `defaultProviders:
metrics:
- stackdriver
extensionProviders:
- name: stackdriver
stackdriver:
maxNumberOfAttributes: 3
- name: stackdriver-annotations
stackdriver:
maxNumberOfAnnotations: 5
trustDomainAliases: ["both", "default"]
`,
},
{
name: "add provider",
in: `
extensionProviders:
- name: prometheus
prometheus: {}`,
out: `defaultProviders:
metrics:
- stackdriver
extensionProviders:
- name: stackdriver
stackdriver:
maxNumberOfAttributes: 3
- name: prometheus
prometheus: {}
trustDomainAliases: ["both", "default"]
`,
},
{
name: "add trust domain aliases",
in: `
trustDomainAliases: ["added", "both"]`,
out: `defaultProviders:
metrics:
- stackdriver
extensionProviders:
- name: stackdriver
stackdriver:
maxNumberOfAttributes: 3
trustDomainAliases:
- added
- both
- default
`,
},
}
for _, tt := range cases {
t.Run(tt.name, func(t *testing.T) {
mc := mesh.DefaultMeshConfig()
mc.DefaultProviders = &meshconfig.MeshConfig_DefaultProviders{
Metrics: []string{"stackdriver"},
}
mc.ExtensionProviders = []*meshconfig.MeshConfig_ExtensionProvider{{
Name: "stackdriver",
Provider: &meshconfig.MeshConfig_ExtensionProvider_Stackdriver{
Stackdriver: &meshconfig.MeshConfig_ExtensionProvider_StackdriverProvider{
MaxNumberOfAttributes: &wrapperspb.Int64Value{Value: 3},
},
},
}}
mc.TrustDomainAliases = []string{"default", "both"}
res, err := mesh.ApplyMeshConfig(tt.in, mc)
if err != nil {
t.Fatal(err)
}
// Just extract fields we are testing
minimal := &meshconfig.MeshConfig{}
minimal.DefaultProviders = res.DefaultProviders
minimal.ExtensionProviders = res.ExtensionProviders
minimal.TrustDomainAliases = res.TrustDomainAliases
want := &meshconfig.MeshConfig{}
protomarshal.ApplyYAML(tt.out, want)
if d := cmp.Diff(want, minimal, protocmp.Transform()); d != "" {
t.Fatalf("got diff %v", d)
}
})
}
}
func TestApplyMeshNetworksDefaults(t *testing.T) {
yml := `
networks:
network1:
endpoints:
- fromCidr: "192.168.0.1/24"
gateways:
- address: 1.1.1.1
port: 80
network2:
endpoints:
- fromRegistry: reg1
gateways:
- registryServiceName: reg1
port: 443
`
want := mesh.EmptyMeshNetworks()
want.Networks = map[string]*meshconfig.Network{
"network1": {
Endpoints: []*meshconfig.Network_NetworkEndpoints{
{
Ne: &meshconfig.Network_NetworkEndpoints_FromCidr{
FromCidr: "192.168.0.1/24",
},
},
},
Gateways: []*meshconfig.Network_IstioNetworkGateway{
{
Gw: &meshconfig.Network_IstioNetworkGateway_Address{
Address: "1.1.1.1",
},
Port: 80,
},
},
},
"network2": {
Endpoints: []*meshconfig.Network_NetworkEndpoints{
{
Ne: &meshconfig.Network_NetworkEndpoints_FromRegistry{
FromRegistry: "reg1",
},
},
},
Gateways: []*meshconfig.Network_IstioNetworkGateway{
{
Gw: &meshconfig.Network_IstioNetworkGateway_RegistryServiceName{
RegistryServiceName: "reg1",
},
Port: 443,
},
},
},
}
got, err := mesh.ParseMeshNetworks(yml)
if err != nil {
t.Fatalf("ApplyMeshNetworksDefaults() failed: %v", err)
}
assert.Equal(t, got, &want)
}