blob: 5dc9d67dae1a6ff7e6bfdd8fc39a647c576ea481 [file] [log] [blame]
package mesh
import (
"fmt"
"github.com/apache/dubbo-kubernetes/pkg/config/constants"
"github.com/apache/dubbo-kubernetes/pkg/util/pointer"
"github.com/apache/dubbo-kubernetes/pkg/util/protomarshal"
"github.com/apache/dubbo-kubernetes/pkg/util/sets"
"github.com/hashicorp/go-multierror"
"google.golang.org/protobuf/types/known/durationpb"
wrappers "google.golang.org/protobuf/types/known/wrapperspb"
meshconfig "istio.io/api/mesh/v1alpha1"
"istio.io/api/networking/v1alpha3"
"os"
"sigs.k8s.io/yaml"
"time"
)
func DefaultProxyConfig() *meshconfig.ProxyConfig {
return &meshconfig.ProxyConfig{
ConfigPath: constants.ConfigPathDir,
ClusterName: &meshconfig.ProxyConfig_ServiceCluster{ServiceCluster: constants.ServiceClusterName},
DrainDuration: durationpb.New(45 * time.Second),
TerminationDrainDuration: durationpb.New(5 * time.Second),
ProxyAdminPort: 15000,
// TODO authpolicy
DiscoveryAddress: "dubbod.dubbo-system.svc:15012",
BinaryPath: constants.BinaryPathFilename,
StatNameLength: 189,
StatusPort: 15020,
}
}
func ReadMeshConfig(filename string) (*meshconfig.MeshConfig, error) {
yaml, err := os.ReadFile(filename)
if err != nil {
return nil, multierror.Prefix(err, "cannot read mesh config file")
}
return ApplyMeshConfigDefaults(string(yaml))
}
func ApplyMeshConfigDefaults(yaml string) (*meshconfig.MeshConfig, error) {
return ApplyMeshConfig(yaml, DefaultMeshConfig())
}
func ApplyMeshConfig(yaml string, defaultConfig *meshconfig.MeshConfig) (*meshconfig.MeshConfig, error) {
prevProxyConfig := defaultConfig.DefaultConfig
prevDefaultProvider := defaultConfig.DefaultProviders
prevExtensionProviders := defaultConfig.ExtensionProviders
prevTrustDomainAliases := defaultConfig.TrustDomainAliases
defaultConfig.DefaultConfig = DefaultProxyConfig()
if err := protomarshal.ApplyYAML(yaml, defaultConfig); err != nil {
return nil, multierror.Prefix(err, "failed to convert to proto.")
}
defaultConfig.DefaultConfig = prevProxyConfig
raw, err := toMap(yaml)
if err != nil {
return nil, err
}
pc, err := extractYamlField("defaultConfig", raw)
if err != nil {
return nil, multierror.Prefix(err, "failed to extract proxy config")
}
if pc != "" {
pc, err := MergeProxyConfig(pc, defaultConfig.DefaultConfig)
if err != nil {
return nil, err
}
defaultConfig.DefaultConfig = pc
}
defaultConfig.DefaultProviders = prevDefaultProvider
dp, err := extractYamlField("defaultProviders", raw)
if err != nil {
return nil, multierror.Prefix(err, "failed to extract default providers")
}
if dp != "" {
if err := protomarshal.ApplyYAML(dp, defaultConfig.DefaultProviders); err != nil {
return nil, fmt.Errorf("could not parse default providers: %v", err)
}
}
newExtensionProviders := defaultConfig.ExtensionProviders
defaultConfig.ExtensionProviders = prevExtensionProviders
for _, p := range newExtensionProviders {
found := false
for _, e := range defaultConfig.ExtensionProviders {
if p.Name == e.Name {
e.Provider = p.Provider
found = true
break
}
}
if !found {
defaultConfig.ExtensionProviders = append(defaultConfig.ExtensionProviders, p)
}
}
defaultConfig.TrustDomainAliases = sets.SortedList(sets.New(append(defaultConfig.TrustDomainAliases, prevTrustDomainAliases...)...))
// TODO ValidationMeshConfig
return defaultConfig, nil
}
func DefaultMeshConfig() *meshconfig.MeshConfig {
proxyConfig := DefaultProxyConfig()
return &meshconfig.MeshConfig{
EnableTracing: true,
AccessLogFile: "",
AccessLogEncoding: meshconfig.MeshConfig_TEXT,
AccessLogFormat: "",
EnableEnvoyAccessLogService: false,
ProtocolDetectionTimeout: durationpb.New(0),
TrustDomain: constants.DefaultClusterLocalDomain,
TrustDomainAliases: []string{},
EnableAutoMtls: wrappers.Bool(true),
OutboundTrafficPolicy: &meshconfig.MeshConfig_OutboundTrafficPolicy{Mode: meshconfig.MeshConfig_OutboundTrafficPolicy_ALLOW_ANY},
InboundTrafficPolicy: &meshconfig.MeshConfig_InboundTrafficPolicy{Mode: meshconfig.MeshConfig_InboundTrafficPolicy_PASSTHROUGH},
LocalityLbSetting: &v1alpha3.LocalityLoadBalancerSetting{
Enabled: wrappers.Bool(true),
},
Certificates: []*meshconfig.Certificate{},
DefaultConfig: proxyConfig,
RootNamespace: constants.DubboSystemNamespace,
ProxyListenPort: 15001,
ProxyInboundListenPort: 15006,
ConnectTimeout: durationpb.New(10 * time.Second),
DefaultServiceExportTo: []string{"*"},
DefaultVirtualServiceExportTo: []string{"*"},
DefaultDestinationRuleExportTo: []string{"*"},
DnsRefreshRate: durationpb.New(60 * time.Second),
DefaultProviders: &meshconfig.MeshConfig_DefaultProviders{},
}
}
func MergeProxyConfig(yaml string, proxyConfig *meshconfig.ProxyConfig) (*meshconfig.ProxyConfig, error) {
origMetadata := proxyConfig.ProxyMetadata
origProxyHeaders := proxyConfig.ProxyHeaders
if err := protomarshal.ApplyYAML(yaml, proxyConfig); err != nil {
return nil, fmt.Errorf("could not parse proxy config: %v", err)
}
newMetadata := proxyConfig.ProxyMetadata
proxyConfig.ProxyMetadata = mergeMap(origMetadata, newMetadata)
correctProxyHeaders(proxyConfig, origProxyHeaders)
return proxyConfig, nil
}
func correctProxyHeaders(proxyConfig *meshconfig.ProxyConfig, orig *meshconfig.ProxyConfig_ProxyHeaders) {
ph := proxyConfig.ProxyHeaders
if ph != nil && orig != nil {
ph.ForwardedClientCert = pointer.NonEmptyOrDefault(ph.ForwardedClientCert, orig.ForwardedClientCert)
ph.RequestId = pointer.NonEmptyOrDefault(ph.RequestId, orig.RequestId)
ph.AttemptCount = pointer.NonEmptyOrDefault(ph.AttemptCount, orig.AttemptCount)
ph.Server = pointer.NonEmptyOrDefault(ph.Server, orig.Server)
ph.EnvoyDebugHeaders = pointer.NonEmptyOrDefault(ph.EnvoyDebugHeaders, orig.EnvoyDebugHeaders)
}
}
func extractYamlField(key string, mp map[string]any) (string, error) {
proxyConfig := mp[key]
if proxyConfig == nil {
return "", nil
}
bytes, err := yaml.Marshal(proxyConfig)
if err != nil {
return "", err
}
return string(bytes), nil
}
func toMap(yamlText string) (map[string]any, error) {
mp := map[string]any{}
if err := yaml.Unmarshal([]byte(yamlText), &mp); err != nil {
return nil, err
}
return mp, nil
}
func mergeMap(original map[string]string, merger map[string]string) map[string]string {
if original == nil && merger == nil {
return nil
}
if original == nil {
original = map[string]string{}
}
for k, v := range merger {
original[k] = v
}
return original
}