blob: 17b65dce3df719b281cf8b50b4469a23b8dc4655 [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 config
import (
"fmt"
"os"
"strconv"
"strings"
)
import (
"google.golang.org/protobuf/types/known/wrapperspb"
"istio.io/api/annotation"
meshconfig "istio.io/api/mesh/v1alpha1"
"istio.io/pkg/log"
)
import (
"github.com/apache/dubbo-go-pixiu/pilot/pkg/model"
"github.com/apache/dubbo-go-pixiu/pilot/pkg/util/network"
"github.com/apache/dubbo-go-pixiu/pkg/bootstrap"
"github.com/apache/dubbo-go-pixiu/pkg/config/mesh"
"github.com/apache/dubbo-go-pixiu/pkg/config/validation"
)
// ConstructProxyConfig returns proxyConfig
func ConstructProxyConfig(meshConfigFile, serviceCluster, proxyConfigEnv string, concurrency int, role *model.Proxy) (*meshconfig.ProxyConfig, error) {
annotations, err := bootstrap.ReadPodAnnotations("")
if err != nil {
if os.IsNotExist(err) {
log.Debugf("failed to read pod annotations: %v", err)
} else {
log.Warnf("failed to read pod annotations: %v", err)
}
}
var fileMeshContents string
if fileExists(meshConfigFile) {
contents, err := os.ReadFile(meshConfigFile)
if err != nil {
return nil, fmt.Errorf("failed to read mesh config file %v: %v", meshConfigFile, err)
}
fileMeshContents = string(contents)
}
meshConfig, err := getMeshConfig(fileMeshContents, annotations[annotation.ProxyConfig.Name], proxyConfigEnv, role.Type == model.SidecarProxy)
if err != nil {
return nil, err
}
proxyConfig := mesh.DefaultProxyConfig()
if meshConfig.DefaultConfig != nil {
proxyConfig = meshConfig.DefaultConfig
}
if concurrency != 0 {
// If --concurrency is explicitly set, we will use that. Otherwise, use source determined by
// proxy config.
proxyConfig.Concurrency = &wrapperspb.Int32Value{Value: int32(concurrency)}
}
if x, ok := proxyConfig.GetClusterName().(*meshconfig.ProxyConfig_ServiceCluster); ok {
if x.ServiceCluster == "" {
proxyConfig.ClusterName = &meshconfig.ProxyConfig_ServiceCluster{ServiceCluster: serviceCluster}
}
}
// resolve statsd address
if proxyConfig.StatsdUdpAddress != "" {
addr, err := network.ResolveAddr(proxyConfig.StatsdUdpAddress)
if err != nil {
log.Warnf("resolve StatsdUdpAddress failed: %v", err)
proxyConfig.StatsdUdpAddress = ""
} else {
proxyConfig.StatsdUdpAddress = addr
}
}
if err := validation.ValidateMeshConfigProxyConfig(proxyConfig); err != nil {
return nil, err
}
return applyAnnotations(proxyConfig, annotations), nil
}
// getMeshConfig gets the mesh config to use for proxy configuration
// 1. First we take the default config
// 2. Then we apply any settings from file (this comes from gateway mounting configmap)
// 3. Then we apply settings from environment variable (this comes from sidecar injection sticking meshconfig here)
// 4. Then we apply overrides from annotation (this comes from annotation on gateway, passed through downward API)
//
// Merging is done by replacement. Any fields present in the overlay will replace those existing fields, while
// untouched fields will remain untouched. This means lists will be replaced, not appended to, for example.
func getMeshConfig(fileOverride, annotationOverride, proxyConfigEnv string, isSidecar bool) (*meshconfig.MeshConfig, error) {
mc := mesh.DefaultMeshConfig()
// Gateway default should be concurrency unset (ie listen on all threads)
if !isSidecar {
mc.DefaultConfig.Concurrency = nil
}
if fileOverride != "" {
log.Infof("Apply mesh config from file %v", fileOverride)
fileMesh, err := mesh.ApplyMeshConfig(fileOverride, mc)
if err != nil || fileMesh == nil {
return nil, fmt.Errorf("failed to unmarshal mesh config from file [%v]: %v", fileOverride, err)
}
mc = fileMesh
}
if proxyConfigEnv != "" {
log.Infof("Apply proxy config from env %v", proxyConfigEnv)
envMesh, err := mesh.ApplyProxyConfig(proxyConfigEnv, mc)
if err != nil || envMesh == nil {
return nil, fmt.Errorf("failed to unmarshal mesh config from environment [%v]: %v", proxyConfigEnv, err)
}
mc = envMesh
}
if annotationOverride != "" {
log.Infof("Apply proxy config from annotation %v", annotationOverride)
annotationMesh, err := mesh.ApplyProxyConfig(annotationOverride, mc)
if err != nil || annotationMesh == nil {
return nil, fmt.Errorf("failed to unmarshal mesh config from annotation [%v]: %v", annotationOverride, err)
}
mc = annotationMesh
}
return mc, nil
}
func fileExists(path string) bool {
if _, err := os.Stat(path); os.IsNotExist(err) {
return false
}
return true
}
// Apply any overrides to proxy config from annotations
func applyAnnotations(config *meshconfig.ProxyConfig, annos map[string]string) *meshconfig.ProxyConfig {
if v, f := annos[annotation.SidecarDiscoveryAddress.Name]; f {
config.DiscoveryAddress = v
}
if v, f := annos[annotation.SidecarStatusPort.Name]; f {
p, err := strconv.Atoi(v)
if err != nil {
log.Errorf("Invalid annotation %v=%v: %v", annotation.SidecarStatusPort.Name, v, err)
}
config.StatusPort = int32(p)
}
return config
}
func GetPilotSan(discoveryAddress string) string {
discHost := strings.Split(discoveryAddress, ":")[0]
// For local debugging - the discoveryAddress is set to localhost, but the cert issued for normal SA.
if discHost == "localhost" {
discHost = "istiod.dubbo-system.svc"
}
return discHost
}