mirror of https://github.com/linkerd/linkerd2.git
223 lines
7.5 KiB
Go
223 lines
7.5 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"strings"
|
|
|
|
"github.com/golang/protobuf/jsonpb"
|
|
"github.com/golang/protobuf/proto"
|
|
pb "github.com/linkerd/linkerd2/controller/gen/config"
|
|
l5dcharts "github.com/linkerd/linkerd2/pkg/charts/linkerd2"
|
|
log "github.com/sirupsen/logrus"
|
|
"sigs.k8s.io/yaml"
|
|
)
|
|
|
|
// Global returns the Global protobuf config from the linkerd-config ConfigMap
|
|
func Global(filepath string) (*pb.Global, error) {
|
|
config := &pb.Global{}
|
|
err := unmarshalFile(filepath, config)
|
|
return config, err
|
|
}
|
|
|
|
// Proxy returns the Proxy protobuf config from the linkerd-config ConfigMap
|
|
func Proxy(filepath string) (*pb.Proxy, error) {
|
|
config := &pb.Proxy{}
|
|
err := unmarshalFile(filepath, config)
|
|
return config, err
|
|
}
|
|
|
|
// Install returns the Install protobuf config from the linkerd-config ConfigMap
|
|
func Install(filepath string) (*pb.Install, error) {
|
|
config := &pb.Install{}
|
|
err := unmarshalFile(filepath, config)
|
|
return config, err
|
|
}
|
|
|
|
// Values returns the Value struct from the linkerd-config ConfigMap
|
|
func Values(filepath string) (*l5dcharts.Values, error) {
|
|
values := &l5dcharts.Values{}
|
|
configYaml, err := ioutil.ReadFile(filepath)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to read config file: %s", err)
|
|
}
|
|
|
|
log.Debugf("%s config YAML: %s", filepath, configYaml)
|
|
if err = yaml.Unmarshal(configYaml, values); err != nil {
|
|
return nil, fmt.Errorf("failed to unmarshal JSON from: %s: %s", filepath, err)
|
|
}
|
|
return values, err
|
|
}
|
|
|
|
func unmarshalFile(filepath string, msg proto.Message) error {
|
|
configJSON, err := ioutil.ReadFile(filepath)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to read config file: %s", err)
|
|
}
|
|
|
|
log.Debugf("%s config JSON: %s", filepath, configJSON)
|
|
if err = unmarshal(string(configJSON), msg); err != nil {
|
|
return fmt.Errorf("failed to unmarshal JSON from: %s: %s", filepath, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func unmarshal(json string, msg proto.Message) error {
|
|
// If a config is missing, then just leave the message as nil and return
|
|
// without an error.
|
|
if json == "" {
|
|
return nil
|
|
}
|
|
|
|
// If we're using older code to read a newer config, blowing up during decoding
|
|
// is not helpful. We should detect that through other means.
|
|
u := jsonpb.Unmarshaler{AllowUnknownFields: true}
|
|
return u.Unmarshal(strings.NewReader(json), msg)
|
|
}
|
|
|
|
// FromConfigMap builds a configuration by reading a map with the keys "global"
|
|
// and "proxy", each containing JSON values.
|
|
func FromConfigMap(configMap map[string]string) (*pb.All, error) {
|
|
c := &pb.All{Global: &pb.Global{}, Proxy: &pb.Proxy{}, Install: &pb.Install{}}
|
|
|
|
if err := unmarshal(configMap["global"], c.Global); err != nil {
|
|
return nil, fmt.Errorf("invalid global config: %s", err)
|
|
}
|
|
|
|
if err := unmarshal(configMap["proxy"], c.Proxy); err != nil {
|
|
return nil, fmt.Errorf("invalid proxy config: %s", err)
|
|
}
|
|
|
|
if err := unmarshal(configMap["install"], c.Install); err != nil {
|
|
return nil, fmt.Errorf("invalid install config: %s", err)
|
|
}
|
|
|
|
return c, nil
|
|
}
|
|
|
|
// ToJSON encode the configuration to JSON, i.e. to be stored in a ConfigMap.
|
|
func ToJSON(configs *pb.All) (global, proxy, install string, err error) {
|
|
m := jsonpb.Marshaler{EmitDefaults: true}
|
|
|
|
global, err = m.MarshalToString(configs.GetGlobal())
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
proxy, err = m.MarshalToString(configs.GetProxy())
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
install, err = m.MarshalToString(configs.GetInstall())
|
|
return
|
|
}
|
|
|
|
// ToValues converts configuration into a Values struct, i.e to be consumed by check
|
|
// TODO: Remove this once the newer configuration becomes the default i.e 2.10
|
|
func ToValues(configs *pb.All) *l5dcharts.Values {
|
|
|
|
// convert install flags into values
|
|
values := &l5dcharts.Values{
|
|
Global: &l5dcharts.Global{
|
|
CNIEnabled: configs.GetGlobal().GetCniEnabled(),
|
|
Namespace: configs.GetGlobal().GetLinkerdNamespace(),
|
|
IdentityTrustAnchorsPEM: configs.GetGlobal().GetIdentityContext().GetTrustAnchorsPem(),
|
|
IdentityTrustDomain: configs.GetGlobal().GetIdentityContext().GetTrustDomain(),
|
|
ClusterDomain: configs.GetGlobal().GetClusterDomain(),
|
|
ClusterNetworks: configs.GetProxy().GetDestinationGetNetworks(),
|
|
LinkerdVersion: configs.GetGlobal().GetVersion(),
|
|
Proxy: &l5dcharts.Proxy{
|
|
Image: &l5dcharts.Image{
|
|
Name: configs.GetProxy().GetProxyImage().GetImageName(),
|
|
PullPolicy: configs.GetProxy().GetProxyImage().GetPullPolicy(),
|
|
Version: configs.GetProxy().GetProxyVersion(),
|
|
},
|
|
Ports: &l5dcharts.Ports{
|
|
Control: int32(configs.GetProxy().GetControlPort().GetPort()),
|
|
Inbound: int32(configs.GetProxy().GetInboundPort().GetPort()),
|
|
Admin: int32(configs.GetProxy().GetAdminPort().GetPort()),
|
|
Outbound: int32(configs.GetProxy().GetOutboundPort().GetPort()),
|
|
},
|
|
Resources: &l5dcharts.Resources{
|
|
CPU: l5dcharts.Constraints{
|
|
Limit: configs.GetProxy().GetResource().GetLimitCpu(),
|
|
Request: configs.GetProxy().GetResource().GetRequestCpu(),
|
|
},
|
|
Memory: l5dcharts.Constraints{
|
|
Limit: configs.GetProxy().GetResource().GetLimitMemory(),
|
|
Request: configs.GetProxy().GetResource().GetRequestMemory(),
|
|
},
|
|
},
|
|
EnableExternalProfiles: !configs.Proxy.GetDisableExternalProfiles(),
|
|
LogFormat: configs.GetProxy().GetLogFormat(),
|
|
OutboundConnectTimeout: configs.GetProxy().GetOutboundConnectTimeout(),
|
|
InboundConnectTimeout: configs.GetProxy().GetInboundConnectTimeout(),
|
|
},
|
|
ProxyInit: &l5dcharts.ProxyInit{
|
|
IgnoreInboundPorts: toString(configs.GetProxy().GetIgnoreInboundPorts()),
|
|
IgnoreOutboundPorts: toString(configs.GetProxy().GetIgnoreOutboundPorts()),
|
|
Image: &l5dcharts.Image{
|
|
Name: configs.GetProxy().GetProxyInitImage().GetImageName(),
|
|
PullPolicy: configs.GetProxy().GetProxyInitImage().GetPullPolicy(),
|
|
Version: configs.GetProxy().GetProxyInitImageVersion(),
|
|
},
|
|
},
|
|
},
|
|
Identity: &l5dcharts.Identity{
|
|
Issuer: &l5dcharts.Issuer{
|
|
Scheme: configs.GetGlobal().GetIdentityContext().GetScheme(),
|
|
},
|
|
},
|
|
OmitWebhookSideEffects: configs.GetGlobal().GetOmitWebhookSideEffects(),
|
|
DebugContainer: &l5dcharts.DebugContainer{
|
|
Image: &l5dcharts.Image{
|
|
Name: configs.GetProxy().GetDebugImage().GetImageName(),
|
|
PullPolicy: configs.GetProxy().GetDebugImage().GetPullPolicy(),
|
|
Version: configs.GetProxy().GetDebugImageVersion(),
|
|
},
|
|
},
|
|
}
|
|
|
|
// for non-primitive types set only if they are not nil
|
|
if configs.GetGlobal().GetIdentityContext().GetIssuanceLifetime() != nil {
|
|
values.Identity.Issuer.IssuanceLifetime = configs.GetGlobal().GetIdentityContext().GetIssuanceLifetime().String()
|
|
}
|
|
if configs.GetGlobal().GetIdentityContext().GetClockSkewAllowance() != nil {
|
|
values.Identity.Issuer.ClockSkewAllowance = configs.GetGlobal().GetIdentityContext().GetClockSkewAllowance().String()
|
|
}
|
|
|
|
if configs.GetProxy().GetLogLevel() != nil {
|
|
values.Global.Proxy.LogLevel = configs.GetProxy().GetLogLevel().String()
|
|
|
|
}
|
|
|
|
// set HA, and Heartbeat flags as health-check needs them for old config installs
|
|
for _, flag := range configs.GetInstall().GetFlags() {
|
|
if flag.GetName() == "ha" && flag.GetValue() == "true" {
|
|
values.Global.HighAvailability = true
|
|
}
|
|
|
|
if flag.GetName() == "disable-heartbeat" && flag.GetValue() == "true" {
|
|
values.DisableHeartBeat = true
|
|
}
|
|
}
|
|
|
|
return values
|
|
}
|
|
|
|
func toString(portRanges []*pb.PortRange) string {
|
|
|
|
var portRangeString string
|
|
if len(portRanges) > 0 {
|
|
for i := 0; i < len(portRanges)-1; i++ {
|
|
portRangeString += portRanges[i].GetPortRange() + ","
|
|
}
|
|
|
|
portRangeString += portRanges[len(portRanges)-1].GetPortRange()
|
|
}
|
|
|
|
return portRangeString
|
|
}
|