Remove legacy upgrade and it's references (#7309)

With [linkerd2#5008](https://github.com/linkerd/linkerd2/issues/5008) and associated PRs, we changed the way configuration is handled by storing a helm values struct inside of the configmap.

Now that we have had one stable release with new configuration, were no longer use and need to maintain the legacy config. This commit removes all the associated logic, protobuf files, and references.

Changes Include:

- Removed [`proto/config/config.proto`](https://github.com/linkerd/linkerd2/blob/main/proto/config/config.proto)
- Changed [`bin/protoc-go.sh`](https://github.com/linkerd/linkerd2/blob/main/bin/protoc-go.sh) to not include `config.proto`
- Changed [`FetchLinkerdConfigMap()`](741fde679b/pkg/healthcheck/healthcheck.go (L1768)) in `healthcheck.go` to return only the configmap, with the pb type.
- Changed [`FetchCurrentConfiguration()`](741fde679b/pkg/healthcheck/healthcheck.go (L1647)) only unmarshal and use helm value struct from configmap (as a follow-up to the todo above; note that there's already a todo here to refactor the function once value struct is the default, which has already happened)
- Removed [`upgrade_legacy.go`](https://github.com/linkerd/linkerd2/blob/main/cli/cmd/upgrade_legacy.go)

Signed-off-by: Krzysztof Dryś <krzysztofdrys@gmail.com>
This commit is contained in:
Krzysztof Dryś 2021-11-29 15:38:58 +01:00 committed by GitHub
parent eb2f9e53be
commit f92e77f7f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 134 additions and 1999 deletions

View File

@ -11,7 +11,6 @@ rm -rf controller/gen/common controller/gen/config viz/metrics-api/gen viz/tap/g
mkdir -p controller/gen/common/net viz/metrics-api/gen/viz viz/tap/gen/tap mkdir -p controller/gen/common/net viz/metrics-api/gen/viz viz/tap/gen/tap
"$bindir"/protoc -I proto --go_out=paths=source_relative:controller/gen proto/common/net.proto "$bindir"/protoc -I proto --go_out=paths=source_relative:controller/gen proto/common/net.proto
"$bindir"/protoc -I proto --go_out=paths=source_relative:controller/gen proto/config/config.proto
"$bindir"/protoc -I proto -I viz/metrics-api/proto --go_out=paths=source_relative:viz/metrics-api/gen viz/metrics-api/proto/viz.proto "$bindir"/protoc -I proto -I viz/metrics-api/proto --go_out=paths=source_relative:viz/metrics-api/gen viz/metrics-api/proto/viz.proto
"$bindir"/protoc -I proto -I viz/metrics-api/proto --go-grpc_out=paths=source_relative:viz/metrics-api/gen/viz viz/metrics-api/proto/viz.proto "$bindir"/protoc -I proto -I viz/metrics-api/proto --go-grpc_out=paths=source_relative:viz/metrics-api/gen/viz viz/metrics-api/proto/viz.proto
"$bindir"/protoc -I proto -I viz/tap/proto -I viz/metrics-api/proto --go_out=paths=source_relative:viz/tap/gen viz/tap/proto/viz_tap.proto "$bindir"/protoc -I proto -I viz/tap/proto -I viz/metrics-api/proto --go_out=paths=source_relative:viz/tap/gen viz/tap/proto/viz_tap.proto

View File

@ -8,10 +8,13 @@ import (
"regexp" "regexp"
"time" "time"
"github.com/golang/protobuf/ptypes" corev1 "k8s.io/api/core/v1"
pb "github.com/linkerd/linkerd2/controller/gen/config" "k8s.io/client-go/kubernetes"
"github.com/linkerd/linkerd2/pkg/charts/linkerd2" "github.com/linkerd/linkerd2/pkg/charts/linkerd2"
charts "github.com/linkerd/linkerd2/pkg/charts/linkerd2"
"github.com/linkerd/linkerd2/pkg/healthcheck" "github.com/linkerd/linkerd2/pkg/healthcheck"
"github.com/linkerd/linkerd2/pkg/issuercerts"
"github.com/linkerd/linkerd2/pkg/k8s" "github.com/linkerd/linkerd2/pkg/k8s"
"github.com/linkerd/linkerd2/pkg/version" "github.com/linkerd/linkerd2/pkg/version"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -127,16 +130,16 @@ func repair(ctx context.Context, forced bool) error {
if err != nil { if err != nil {
return fmt.Errorf("Failed to parse IssuanceLifetime from linkerd-config: %s", err) return fmt.Errorf("Failed to parse IssuanceLifetime from linkerd-config: %s", err)
} }
idCtx := pb.IdentityContext{ idCtx := identityContext{
TrustAnchorsPem: values.IdentityTrustAnchorsPEM, trustAnchorsPem: values.IdentityTrustAnchorsPEM,
Scheme: values.Identity.Issuer.Scheme, scheme: values.Identity.Issuer.Scheme,
ClockSkewAllowance: ptypes.DurationProto(clockSkewDuration), clockSkewAllowance: clockSkewDuration,
IssuanceLifetime: ptypes.DurationProto(issuanceLifetime), issuanceLifetime: issuanceLifetime,
TrustDomain: values.IdentityTrustDomain, trustDomain: values.IdentityTrustDomain,
} }
// Populate identity values // Populate identity values
err = fetchIdentityValues(ctx, k8sAPI, &idCtx, &values) err = fetchIdentityValues(ctx, k8sAPI, idCtx, &values)
if err != nil { if err != nil {
return fmt.Errorf("Failed to load issuer credentials: %s", err) return fmt.Errorf("Failed to load issuer credentials: %s", err)
} }
@ -185,3 +188,68 @@ func resetVersion(values *linkerd2.Values) error {
values.LinkerdVersion = defaults.LinkerdVersion values.LinkerdVersion = defaults.LinkerdVersion
return nil return nil
} }
type identityContext struct {
trustAnchorsPem string
scheme string
clockSkewAllowance time.Duration
issuanceLifetime time.Duration
trustDomain string
}
// fetchIdentityValue checks the kubernetes API to fetch an existing
// linkerd identity configuration.
//
// This bypasses the public API so that we can access secrets and validate
// permissions.
func fetchIdentityValues(ctx context.Context, k kubernetes.Interface, idctx identityContext, values *charts.Values) error {
if idctx.scheme == "" {
// if this is empty, then we are upgrading from a version
// that did not support issuer schemes. Just default to the
// linkerd one.
idctx.scheme = k8s.IdentityIssuerSchemeLinkerd
}
var trustAnchorsPEM string
var issuerData *issuercerts.IssuerCertData
var err error
trustAnchorsPEM = idctx.trustAnchorsPem
issuerData, err = fetchIssuer(ctx, k, trustAnchorsPEM, idctx.scheme)
if err != nil {
return err
}
values.IdentityTrustAnchorsPEM = trustAnchorsPEM
values.Identity.Issuer.Scheme = idctx.scheme
values.Identity.Issuer.ClockSkewAllowance = idctx.clockSkewAllowance.String()
values.Identity.Issuer.IssuanceLifetime = idctx.issuanceLifetime.String()
values.Identity.Issuer.TLS.KeyPEM = issuerData.IssuerKey
values.Identity.Issuer.TLS.CrtPEM = issuerData.IssuerCrt
return nil
}
func fetchIssuer(ctx context.Context, k kubernetes.Interface, trustPEM string, scheme string) (*issuercerts.IssuerCertData, error) {
var (
issuerData *issuercerts.IssuerCertData
err error
)
switch scheme {
case string(corev1.SecretTypeTLS):
// Do not return external issuer certs as no need of storing them in config and upgrade secrets
// Also contradicts condition in https://github.com/linkerd/linkerd2/blob/main/cli/cmd/options.go#L550
return &issuercerts.IssuerCertData{}, nil
default:
issuerData, err = issuercerts.FetchIssuerData(ctx, k, trustPEM, controlPlaneNamespace)
if issuerData != nil && issuerData.TrustAnchors != trustPEM {
issuerData.TrustAnchors = trustPEM
}
}
if err != nil {
return nil, err
}
return issuerData, nil
}

View File

@ -265,19 +265,10 @@ func upgrade(ctx context.Context, k *k8s.KubernetesAPI, flags []flag.Flag, stage
if err != nil { if err != nil {
return bytes.Buffer{}, fmt.Errorf("failed to load stored values: %w", err) return bytes.Buffer{}, fmt.Errorf("failed to load stored values: %w", err)
} }
// If there is no linkerd-config-overrides secret, assume we are upgrading
// from a version of Linkerd prior to the introduction of this secret. In
// this case we load the values from the legacy linkerd-config configmap.
if values == nil {
values, err = loadStoredValuesLegacy(ctx, k)
if err != nil {
return bytes.Buffer{}, err
}
}
// If values is still nil, then neither the linkerd-config-overrides secret // If values is still nil, then the linkerd-config-overrides secret was not found.
// nor the legacy values were found. This means either means that Linkerd // This means either means that Linkerd was installed with Helm or that the installation
// was installed with Helm or that the installation needs to be repaired. // needs to be repaired.
if values == nil { if values == nil {
return bytes.Buffer{}, errors.New( return bytes.Buffer{}, errors.New(
`Could not find the Linkerd config. If Linkerd was installed with Helm, please `Could not find the Linkerd config. If Linkerd was installed with Helm, please

View File

@ -1,183 +0,0 @@
package cmd
import (
"context"
"fmt"
"strings"
"github.com/golang/protobuf/ptypes"
"github.com/linkerd/linkerd2/cli/flag"
pb "github.com/linkerd/linkerd2/controller/gen/config"
charts "github.com/linkerd/linkerd2/pkg/charts/linkerd2"
"github.com/linkerd/linkerd2/pkg/healthcheck"
"github.com/linkerd/linkerd2/pkg/issuercerts"
"github.com/linkerd/linkerd2/pkg/k8s"
"github.com/linkerd/linkerd2/pkg/version"
"github.com/spf13/pflag"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes"
)
func loadStoredValuesLegacy(ctx context.Context, k *k8s.KubernetesAPI) (*charts.Values, error) {
// We fetch the configs directly from kubernetes because we need to be able
// to upgrade/reinstall the control plane when the API is not available; and
// this also serves as a passive check that we have privileges to access this
// control plane.
_, configs, err := healthcheck.FetchLinkerdConfigMap(ctx, k, controlPlaneNamespace)
if err != nil {
return nil, fmt.Errorf("could not fetch configs from kubernetes: %s", err)
}
if configs == nil {
return nil, nil
}
repairConfigs(configs)
values, err := charts.NewValues()
if err != nil {
return nil, err
}
allStageFlags, allStageFlagSet := makeAllStageFlags(values)
installFlags, installFlagSet := makeInstallFlags(values)
upgradeFlags, installUpgradeFlagSet, err := makeInstallUpgradeFlags(values)
if err != nil {
return nil, err
}
proxyFlags, proxyFlagSet := makeProxyFlags(values)
flagSet := pflag.NewFlagSet("loaded_flags", pflag.ExitOnError)
flagSet.AddFlagSet(allStageFlagSet)
flagSet.AddFlagSet(installFlagSet)
flagSet.AddFlagSet(installUpgradeFlagSet)
flagSet.AddFlagSet(proxyFlagSet)
setFlagsFromInstall(flagSet, configs.GetInstall().GetFlags())
flags := flattenFlags(allStageFlags, installFlags, upgradeFlags, proxyFlags)
err = flag.ApplySetFlags(values, flags)
if err != nil {
return nil, err
}
idctx := configs.GetGlobal().GetIdentityContext()
if idctx.GetTrustDomain() != "" && idctx.GetTrustAnchorsPem() != "" {
err = fetchIdentityValues(ctx, k, idctx, values)
if err != nil {
return nil, err
}
}
return values, nil
}
func setFlagsFromInstall(flags *pflag.FlagSet, installFlags []*pb.Install_Flag) {
for _, i := range installFlags {
if f := flags.Lookup(i.GetName()); f != nil && !f.Changed {
// The function recordFlags() stores the string representation of flags in the ConfigMap
// so a stringSlice is stored e.g. as [a,b].
// To avoid having f.Value.Set() interpreting that as a string we need to remove
// the brackets
value := i.GetValue()
if f.Value.Type() == "stringSlice" {
value = strings.Trim(value, "[]")
}
f.Value.Set(value)
f.Changed = true
}
}
}
func repairConfigs(configs *pb.All) {
// Repair the "install" section; install flags are updated separately
if configs.Install == nil {
configs.Install = &pb.Install{}
}
// ALWAYS update the CLI version to the most recent.
configs.Install.CliVersion = version.Version
// Repair the "proxy" section
if configs.Proxy == nil {
configs.Proxy = &pb.Proxy{}
}
if configs.Proxy.DebugImage == nil {
configs.Proxy.DebugImage = &pb.Image{}
}
if configs.GetProxy().GetDebugImage().GetImageName() == "" {
configs.Proxy.DebugImage.ImageName = k8s.DebugSidecarImage
}
if configs.GetProxy().GetDebugImageVersion() == "" {
configs.Proxy.DebugImageVersion = version.Version
}
}
// fetchIdentityValue checks the kubernetes API to fetch an existing
// linkerd identity configuration.
//
// This bypasses the public API so that we can access secrets and validate
// permissions.
func fetchIdentityValues(ctx context.Context, k kubernetes.Interface, idctx *pb.IdentityContext, values *charts.Values) error {
if idctx == nil {
return nil
}
if idctx.Scheme == "" {
// if this is empty, then we are upgrading from a version
// that did not support issuer schemes. Just default to the
// linkerd one.
idctx.Scheme = k8s.IdentityIssuerSchemeLinkerd
}
var trustAnchorsPEM string
var issuerData *issuercerts.IssuerCertData
var err error
trustAnchorsPEM = idctx.GetTrustAnchorsPem()
issuerData, err = fetchIssuer(ctx, k, trustAnchorsPEM, idctx.Scheme)
if err != nil {
return err
}
clockSkewDuration, err := ptypes.Duration(idctx.GetClockSkewAllowance())
if err != nil {
return fmt.Errorf("could not convert clock skew protobuf Duration format into golang Duration: %s", err)
}
issuanceLifetimeDuration, err := ptypes.Duration(idctx.GetIssuanceLifetime())
if err != nil {
return fmt.Errorf("could not convert issuance Lifetime protobuf Duration format into golang Duration: %s", err)
}
values.IdentityTrustAnchorsPEM = trustAnchorsPEM
values.Identity.Issuer.Scheme = idctx.Scheme
values.Identity.Issuer.ClockSkewAllowance = clockSkewDuration.String()
values.Identity.Issuer.IssuanceLifetime = issuanceLifetimeDuration.String()
values.Identity.Issuer.TLS.KeyPEM = issuerData.IssuerKey
values.Identity.Issuer.TLS.CrtPEM = issuerData.IssuerCrt
return nil
}
func fetchIssuer(ctx context.Context, k kubernetes.Interface, trustPEM string, scheme string) (*issuercerts.IssuerCertData, error) {
var (
issuerData *issuercerts.IssuerCertData
err error
)
switch scheme {
case string(corev1.SecretTypeTLS):
// Do not return external issuer certs as no need of storing them in config and upgrade secrets
// Also contradicts condition in https://github.com/linkerd/linkerd2/blob/main/cli/cmd/options.go#L550
return &issuercerts.IssuerCertData{}, nil
default:
issuerData, err = issuercerts.FetchIssuerData(ctx, k, trustPEM, controlPlaneNamespace)
if issuerData != nil && issuerData.TrustAnchors != trustPEM {
issuerData.TrustAnchors = trustPEM
}
}
if err != nil {
return nil, err
}
return issuerData, nil
}

View File

@ -203,8 +203,7 @@ func getServiceOpaquePortsAnnotation(svc *corev1.Service) (map[uint32]struct{},
func parseServiceOpaquePorts(annotation string, sps []corev1.ServicePort) []string { func parseServiceOpaquePorts(annotation string, sps []corev1.ServicePort) []string {
portRanges := util.GetPortRanges(annotation) portRanges := util.GetPortRanges(annotation)
var values []string var values []string
for _, portRange := range portRanges { for _, pr := range portRanges {
pr := portRange.GetPortRange()
port, named := isNamed(pr, sps) port, named := isNamed(pr, sps)
if named { if named {
values = append(values, strconv.Itoa(int(port))) values = append(values, strconv.Itoa(int(port)))

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,7 @@ import (
"time" "time"
pkgK8s "github.com/linkerd/linkerd2/controller/k8s" pkgK8s "github.com/linkerd/linkerd2/controller/k8s"
"github.com/linkerd/linkerd2/pkg/healthcheck" "github.com/linkerd/linkerd2/pkg/config"
"github.com/linkerd/linkerd2/pkg/k8s" "github.com/linkerd/linkerd2/pkg/k8s"
"github.com/linkerd/linkerd2/pkg/version" "github.com/linkerd/linkerd2/pkg/version"
promv1 "github.com/prometheus/client_golang/api/prometheus/v1" promv1 "github.com/prometheus/client_golang/api/prometheus/v1"
@ -29,7 +29,7 @@ type containerMeta struct {
func K8sValues(ctx context.Context, kubeAPI *k8s.KubernetesAPI, controlPlaneNamespace string) url.Values { func K8sValues(ctx context.Context, kubeAPI *k8s.KubernetesAPI, controlPlaneNamespace string) url.Values {
v := url.Values{} v := url.Values{}
cm, _, err := healthcheck.FetchLinkerdConfigMap(ctx, kubeAPI, controlPlaneNamespace) cm, err := config.FetchLinkerdConfigMap(ctx, kubeAPI, controlPlaneNamespace)
if err != nil { if err != nil {
log.Errorf("Failed to fetch linkerd-config: %s", err) log.Errorf("Failed to fetch linkerd-config: %s", err)
} else { } else {

View File

@ -1,13 +1,15 @@
package config package config
import ( import (
"context"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"strings"
"github.com/golang/protobuf/jsonpb" "github.com/linkerd/linkerd2/pkg/k8s"
"github.com/golang/protobuf/proto" corev1 "k8s.io/api/core/v1"
pb "github.com/linkerd/linkerd2/controller/gen/config" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
l5dcharts "github.com/linkerd/linkerd2/pkg/charts/linkerd2" l5dcharts "github.com/linkerd/linkerd2/pkg/charts/linkerd2"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
@ -28,49 +30,6 @@ func Values(filepath string) (*l5dcharts.Values, error) {
return values, err return values, err
} }
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",
// "proxy", and "install" each containing JSON values. If none of these keys
// exist, FromConfigMap will return nil. This likely indicates that the
// installed version of Linkerd is stable-2.9.0 or later which uses a different
// config format.
func FromConfigMap(configMap map[string]string) (*pb.All, error) {
c := &pb.All{Global: &pb.Global{}, Proxy: &pb.Proxy{}, Install: &pb.Install{}}
global, globalOk := configMap["global"]
proxy, proxyOk := configMap["proxy"]
install, installOk := configMap["install"]
if !globalOk && !proxyOk && !installOk {
return nil, nil
}
if err := unmarshal(global, c.Global); err != nil {
return nil, fmt.Errorf("invalid global config: %s", err)
}
if err := unmarshal(proxy, c.Proxy); err != nil {
return nil, fmt.Errorf("invalid proxy config: %s", err)
}
if err := unmarshal(install, c.Install); err != nil {
return nil, fmt.Errorf("invalid install config: %s", err)
}
return c, nil
}
// RemoveGlobalFieldIfPresent removes the `global` node and // RemoveGlobalFieldIfPresent removes the `global` node and
// attaches the children nodes there. // attaches the children nodes there.
func RemoveGlobalFieldIfPresent(bytes []byte) ([]byte, error) { func RemoveGlobalFieldIfPresent(bytes []byte) ([]byte, error) {
@ -101,106 +60,12 @@ func RemoveGlobalFieldIfPresent(bytes []byte) ([]byte, error) {
return bytes, nil return bytes, nil
} }
// ToValues converts configuration into a Values struct, i.e to be consumed by check // FetchLinkerdConfigMap retrieves the `linkerd-config` ConfigMap from
// TODO: Remove this once the newer configuration becomes the default i.e 2.10 // Kubernetes.
func ToValues(configs *pb.All) *l5dcharts.Values { func FetchLinkerdConfigMap(ctx context.Context, k kubernetes.Interface, controlPlaneNamespace string) (*corev1.ConfigMap, error) {
cm, err := k.CoreV1().ConfigMaps(controlPlaneNamespace).Get(ctx, k8s.ConfigConfigMapName, metav1.GetOptions{})
// convert install flags into values if err != nil {
values := &l5dcharts.Values{ return nil, err
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(),
},
},
DebugContainer: &l5dcharts.DebugContainer{
Image: &l5dcharts.Image{
Name: configs.GetProxy().GetDebugImage().GetImageName(),
PullPolicy: configs.GetProxy().GetDebugImage().GetPullPolicy(),
Version: configs.GetProxy().GetDebugImageVersion(),
},
},
} }
return cm, nil
// 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.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.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
} }

View File

@ -13,7 +13,6 @@ import (
"strings" "strings"
"time" "time"
configPb "github.com/linkerd/linkerd2/controller/gen/config"
controllerK8s "github.com/linkerd/linkerd2/controller/k8s" controllerK8s "github.com/linkerd/linkerd2/controller/k8s"
l5dcharts "github.com/linkerd/linkerd2/pkg/charts/linkerd2" l5dcharts "github.com/linkerd/linkerd2/pkg/charts/linkerd2"
"github.com/linkerd/linkerd2/pkg/config" "github.com/linkerd/linkerd2/pkg/config"
@ -1689,15 +1688,18 @@ func (hc *HealthChecker) checkCertificatesConfig(ctx context.Context) (*tls.Cred
// FetchCurrentConfiguration retrieves the current Linkerd configuration // FetchCurrentConfiguration retrieves the current Linkerd configuration
func FetchCurrentConfiguration(ctx context.Context, k kubernetes.Interface, controlPlaneNamespace string) (*corev1.ConfigMap, *l5dcharts.Values, error) { func FetchCurrentConfiguration(ctx context.Context, k kubernetes.Interface, controlPlaneNamespace string) (*corev1.ConfigMap, *l5dcharts.Values, error) {
// Get the linkerd-config values if present.
// Get the linkerd-config values if present configMap, err := config.FetchLinkerdConfigMap(ctx, k, controlPlaneNamespace)
configMap, configPb, err := FetchLinkerdConfigMap(ctx, k, controlPlaneNamespace)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
if rawValues := configMap.Data["values"]; rawValues != "" { rawValues := configMap.Data["values"]
// Convert into latest values, where global field is removed if rawValues == "" {
return configMap, nil, nil
}
// Convert into latest values, where global field is removed.
rawValuesBytes, err := config.RemoveGlobalFieldIfPresent([]byte(rawValues)) rawValuesBytes, err := config.RemoveGlobalFieldIfPresent([]byte(rawValues))
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -1710,14 +1712,6 @@ func FetchCurrentConfiguration(ctx context.Context, k kubernetes.Interface, cont
return nil, nil, err return nil, nil, err
} }
return configMap, &fullValues, nil return configMap, &fullValues, nil
}
if configPb == nil {
return configMap, nil, nil
}
// fall back to the older configMap
// TODO: remove this once the newer config override secret becomes the default i.e 2.10
return configMap, config.ToValues(configPb), nil
} }
func (hc *HealthChecker) fetchProxyInjectorCaBundle(ctx context.Context) ([]*x509.Certificate, error) { func (hc *HealthChecker) fetchProxyInjectorCaBundle(ctx context.Context) ([]*x509.Certificate, error) {
@ -1802,26 +1796,6 @@ func (hc *HealthChecker) FetchCredsFromOldSecret(ctx context.Context, namespace
return cred, nil return cred, nil
} }
// FetchLinkerdConfigMap retrieves the `linkerd-config` ConfigMap from
// Kubernetes and parses it into `linkerd2.config` protobuf.
// TODO: Consider a different package for this function. This lives in the
// healthcheck package because healthcheck depends on it, along with other
// packages that also depend on healthcheck. This function depends on both
// `pkg/k8s` and `pkg/config`, which do not depend on each other.
func FetchLinkerdConfigMap(ctx context.Context, k kubernetes.Interface, controlPlaneNamespace string) (*corev1.ConfigMap, *configPb.All, error) {
cm, err := k.CoreV1().ConfigMaps(controlPlaneNamespace).Get(ctx, k8s.ConfigConfigMapName, metav1.GetOptions{})
if err != nil {
return nil, nil, err
}
configPB, err := config.FromConfigMap(cm.Data)
if err != nil {
return nil, nil, err
}
return cm, configPB, nil
}
// CheckNamespace checks whether the given namespace exists, and returns an // CheckNamespace checks whether the given namespace exists, and returns an
// error if it does not match `shouldExist`. // error if it does not match `shouldExist`.
func (hc *HealthChecker) CheckNamespace(ctx context.Context, namespace string, shouldExist bool) error { func (hc *HealthChecker) CheckNamespace(ctx context.Context, namespace string, shouldExist bool) error {

View File

@ -11,19 +11,14 @@ import (
"testing" "testing"
"time" "time"
"github.com/golang/protobuf/ptypes/duration"
configPb "github.com/linkerd/linkerd2/controller/gen/config"
"github.com/linkerd/linkerd2/pkg/charts/linkerd2" "github.com/linkerd/linkerd2/pkg/charts/linkerd2"
"github.com/linkerd/linkerd2/pkg/identity" "github.com/linkerd/linkerd2/pkg/identity"
"github.com/linkerd/linkerd2/pkg/issuercerts" "github.com/linkerd/linkerd2/pkg/issuercerts"
"github.com/linkerd/linkerd2/pkg/k8s" "github.com/linkerd/linkerd2/pkg/k8s"
"github.com/linkerd/linkerd2/pkg/tls" "github.com/linkerd/linkerd2/pkg/tls"
"github.com/linkerd/linkerd2/testutil" "github.com/linkerd/linkerd2/testutil"
"google.golang.org/protobuf/proto"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
) )
type observer struct { type observer struct {
@ -1279,8 +1274,9 @@ apiVersion: v1
metadata: metadata:
name: %s name: %s
data: data:
global: | values: |
{"identityContext":{"trustAnchorsPem": "%s"}} identityTrustAnchorsPEM: %s
`, k8s.ConfigConfigMapName, currentCertificate) `, k8s.ConfigConfigMapName, currentCertificate)
var testCases = []struct { var testCases = []struct {
@ -2170,138 +2166,6 @@ func TestKubeSystemNamespaceInHA(t *testing.T) {
} }
func TestFetchLinkerdConfigMap(t *testing.T) {
testCases := []struct {
k8sConfigs []string
expected *configPb.All
err error
}{
{
[]string{`
kind: ConfigMap
apiVersion: v1
metadata:
name: linkerd-config
namespace: linkerd
data:
global: |
{"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"fake-trust-anchors-pem","issuanceLifetime":"86400s","clockSkewAllowance":"20s"}}
proxy: |
{"proxyImage":{"imageName":"cr.l5d.io/linkerd/proxy","pullPolicy":"IfNotPresent"},"proxyInitImage":{"imageName":"cr.l5d.io/linkerd/proxy-init","pullPolicy":"IfNotPresent"},"controlPort":{"port":4190},"ignoreInboundPorts":[],"ignoreOutboundPorts":[],"inboundPort":{"port":4143},"adminPort":{"port":4191},"outboundPort":{"port":4140},"resource":{"requestCpu":"","requestMemory":"","limitCpu":"","limitMemory":""},"proxyUid":"2102","logLevel":{"level":"warn,linkerd=info"},"disableExternalProfiles":true,"proxyVersion":"install-proxy-version","proxy_init_image_version":"v1.5.1","debugImage":{"imageName":"cr.l5d.io/linkerd/debug","pullPolicy":"IfNotPresent"},"debugImageVersion":"install-debug-version"}
install: |
{"cliVersion":"dev-undefined","flags":[]}`,
},
&configPb.All{
Global: &configPb.Global{
LinkerdNamespace: "linkerd",
Version: "install-control-plane-version",
IdentityContext: &configPb.IdentityContext{
TrustDomain: "cluster.local",
TrustAnchorsPem: "fake-trust-anchors-pem",
IssuanceLifetime: &duration.Duration{
Seconds: 86400,
},
ClockSkewAllowance: &duration.Duration{
Seconds: 20,
},
},
}, Proxy: &configPb.Proxy{
ProxyImage: &configPb.Image{
ImageName: "cr.l5d.io/linkerd/proxy",
PullPolicy: "IfNotPresent",
},
ProxyInitImage: &configPb.Image{
ImageName: "cr.l5d.io/linkerd/proxy-init",
PullPolicy: "IfNotPresent",
},
ControlPort: &configPb.Port{
Port: 4190,
},
InboundPort: &configPb.Port{
Port: 4143,
},
AdminPort: &configPb.Port{
Port: 4191,
},
OutboundPort: &configPb.Port{
Port: 4140,
},
Resource: &configPb.ResourceRequirements{},
ProxyUid: 2102,
LogLevel: &configPb.LogLevel{
Level: "warn,linkerd=info",
},
DisableExternalProfiles: true,
ProxyVersion: "install-proxy-version",
ProxyInitImageVersion: "v1.5.1",
DebugImage: &configPb.Image{
ImageName: "cr.l5d.io/linkerd/debug",
PullPolicy: "IfNotPresent",
},
DebugImageVersion: "install-debug-version",
}, Install: &configPb.Install{
CliVersion: "dev-undefined",
}},
nil,
},
{
[]string{`
kind: ConfigMap
apiVersion: v1
metadata:
name: linkerd-config
namespace: linkerd
data:
global: |
{"linkerdNamespace":"ns","identityContext":null}
proxy: "{}"
install: "{}"`,
},
&configPb.All{Global: &configPb.Global{LinkerdNamespace: "ns", IdentityContext: nil}, Proxy: &configPb.Proxy{}, Install: &configPb.Install{}},
nil,
},
{
[]string{`
kind: ConfigMap
apiVersion: v1
metadata:
name: linkerd-config
namespace: linkerd
data:
global: "{}"
proxy: "{}"
install: "{}"`,
},
&configPb.All{Global: &configPb.Global{}, Proxy: &configPb.Proxy{}, Install: &configPb.Install{}},
nil,
},
{
nil,
nil,
k8sErrors.NewNotFound(schema.GroupResource{Resource: "configmaps"}, "linkerd-config"),
},
}
for i, tc := range testCases {
tc := tc // pin
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
clientset, err := k8s.NewFakeAPI(tc.k8sConfigs...)
if err != nil {
t.Fatalf("Unexpected error: %s", err)
}
_, configs, err := FetchLinkerdConfigMap(context.Background(), clientset, "linkerd")
if !reflect.DeepEqual(err, tc.err) {
t.Fatalf("Expected \"%+v\", got \"%+v\"", tc.err, err)
}
if !proto.Equal(configs, tc.expected) {
t.Fatalf("Unexpected config:\nExpected:\n%+v\nGot:\n%+v", tc.expected, configs)
}
})
}
}
func TestFetchCurrentConfiguration(t *testing.T) { func TestFetchCurrentConfiguration(t *testing.T) {
defaultValues, err := linkerd2.NewValues() defaultValues, err := linkerd2.NewValues()
@ -2635,50 +2499,6 @@ data:
}, },
nil, nil,
}, },
{
[]string{`
kind: ConfigMap
apiVersion: v1
metadata:
name: linkerd-config
namespace: linkerd
data:
global: |
{"linkerdNamespace":"ns","identityContext":null, "cniEnabled": true}
proxy: |
{"proxyImage":{"imageName":"registry", "pullPolicy":"Always"}}
install: |
{"flags":[{"name":"ha","value":"true"}]}`,
},
&linkerd2.Values{
Namespace: "ns",
CNIEnabled: true,
HighAvailability: true,
Proxy: &linkerd2.Proxy{
EnableExternalProfiles: true,
Image: &linkerd2.Image{
Name: "registry",
PullPolicy: "Always",
},
LogLevel: "",
Ports: &linkerd2.Ports{},
Resources: &linkerd2.Resources{
CPU: linkerd2.Constraints{},
Memory: linkerd2.Constraints{},
},
},
ProxyInit: &linkerd2.ProxyInit{
Image: &linkerd2.Image{},
},
Identity: &linkerd2.Identity{
Issuer: &linkerd2.Issuer{},
},
DebugContainer: &linkerd2.DebugContainer{
Image: &linkerd2.Image{},
},
},
nil,
},
} }
for i, tc := range testCases { for i, tc := range testCases {
@ -2710,8 +2530,13 @@ metadata:
name: linkerd-config name: linkerd-config
namespace: linkerd namespace: linkerd
data: data:
global: | values: |
{"linkerdNamespace": "linkerd", "identityContext":{"trustAnchorsPem": %s, "trustDomain": "cluster.local", "scheme": "%s"}} namespace: linkerd
identityTrustAnchorsPEM: %s
identityTrustDomain: cluster.local
identity:
issuer:
scheme: %s
--- ---
`, anchors, scheme) `, anchors, scheme)
} }

View File

@ -4,13 +4,15 @@ import (
"context" "context"
"fmt" "fmt"
"github.com/linkerd/linkerd2/pkg/config"
"github.com/linkerd/linkerd2/pkg/charts/linkerd2" "github.com/linkerd/linkerd2/pkg/charts/linkerd2"
"github.com/linkerd/linkerd2/pkg/k8s" "github.com/linkerd/linkerd2/pkg/k8s"
) )
// GetServerVersion returns Linkerd's version, as set in linkerd-config // GetServerVersion returns Linkerd's version, as set in linkerd-config
func GetServerVersion(ctx context.Context, controlPlaneNamespace string, kubeAPI *k8s.KubernetesAPI) (string, error) { func GetServerVersion(ctx context.Context, controlPlaneNamespace string, kubeAPI *k8s.KubernetesAPI) (string, error) {
cm, _, err := FetchLinkerdConfigMap(ctx, kubeAPI, controlPlaneNamespace) cm, err := config.FetchLinkerdConfigMap(ctx, kubeAPI, controlPlaneNamespace)
if err != nil { if err != nil {
return "", fmt.Errorf("failed to fetch linkerd-config: %s", err) return "", fmt.Errorf("failed to fetch linkerd-config: %s", err)
} }

View File

@ -5,7 +5,6 @@ import (
"strings" "strings"
"github.com/linkerd/linkerd2-proxy-init/ports" "github.com/linkerd/linkerd2-proxy-init/ports"
"github.com/linkerd/linkerd2/controller/gen/config"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
) )
@ -16,8 +15,7 @@ func ParsePorts(portsString string) (map[uint32]struct{}, error) {
opaquePorts := make(map[uint32]struct{}) opaquePorts := make(map[uint32]struct{})
if portsString != "" { if portsString != "" {
portRanges := GetPortRanges(portsString) portRanges := GetPortRanges(portsString)
for _, portRange := range portRanges { for _, pr := range portRanges {
pr := portRange.GetPortRange()
portsRange, err := ports.ParsePortRange(pr) portsRange, err := ports.ParsePortRange(pr)
if err != nil { if err != nil {
log.Warnf("Invalid port range [%v]: %s", pr, err) log.Warnf("Invalid port range [%v]: %s", pr, err)
@ -38,8 +36,7 @@ func ParsePorts(portsString string) (map[uint32]struct{}, error) {
func ParseContainerOpaquePorts(override string, containers []corev1.Container) []string { func ParseContainerOpaquePorts(override string, containers []corev1.Container) []string {
portRanges := GetPortRanges(override) portRanges := GetPortRanges(override)
var values []string var values []string
for _, portRange := range portRanges { for _, pr := range portRanges {
pr := portRange.GetPortRange()
port, named := isNamed(pr, containers) port, named := isNamed(pr, containers)
if named { if named {
values = append(values, strconv.Itoa(int(port))) values = append(values, strconv.Itoa(int(port)))
@ -58,13 +55,8 @@ func ParseContainerOpaquePorts(override string, containers []corev1.Container) [
} }
// GetPortRanges gets port ranges from an override annotation // GetPortRanges gets port ranges from an override annotation
func GetPortRanges(override string) []*config.PortRange { func GetPortRanges(override string) []string {
split := strings.Split(strings.TrimSuffix(override, ","), ",") return strings.Split(strings.TrimSuffix(override, ","), ",")
ports := make([]*config.PortRange, len(split))
for i, p := range split {
ports[i] = &config.PortRange{PortRange: p}
}
return ports
} }
// isNamed checks if a port range is actually a container named port (e.g. // isNamed checks if a port range is actually a container named port (e.g.

View File

@ -1,119 +0,0 @@
syntax = "proto3";
package linkerd2.config;
import "google/protobuf/duration.proto";
option go_package = "github.com/linkerd/linkerd2/controller/gen/config";
message All {
Global global = 1;
Proxy proxy = 2;
Install install = 3;
}
message Global {
string linkerd_namespace = 1;
bool cni_enabled = 2;
// Control plane version
string version = 3;
// If present, configures identity.
IdentityContext identity_context = 4;
AutoInjectContext auto_inject_context = 6 [deprecated=true];
bool omitWebhookSideEffects = 7 [deprecated=true];
// Override default `cluster.local`
string cluster_domain = 8;
}
message Proxy {
Image proxy_image = 1;
Image proxy_init_image = 2;
Port control_port = 3;
repeated PortRange ignore_inbound_ports = 4;
repeated PortRange ignore_outbound_ports = 5;
Port inbound_port = 6;
Port admin_port = 7;
Port outbound_port = 8;
ResourceRequirements resource = 9;
int64 proxy_uid = 10;
LogLevel log_level = 11;
bool disable_external_profiles = 12;
string proxy_version = 13;
string proxy_init_image_version = 14;
Image debug_image = 15;
string debug_image_version = 16;
string destination_get_networks = 17;
string log_format = 18;
string outbound_connect_timeout = 19;
string inbound_connect_timeout = 20;
}
message Image {
string image_name = 1;
string pull_policy = 2;
}
message Port {
uint32 port = 1;
}
message PortRange {
string port_range = 1;
}
message ResourceRequirements {
string request_cpu = 1;
string request_memory = 2;
string limit_cpu = 3;
string limit_memory = 4;
}
message AutoInjectContext { option deprecated = true; }
message IdentityContext {
string trust_domain = 1;
string trust_anchors_pem = 2;
google.protobuf.Duration issuance_lifetime = 3;
google.protobuf.Duration clock_skew_allowance = 4;
string scheme = 5;
}
message LogLevel {
string level = 1;
}
// Stores information about the last installation/upgrade.
//
// Useful for driving upgrades.
message Install {
reserved 1;
//string uuid = 1;
// The CLI version that drove the last install or upgrade.
string cli_version = 2;
// The CLI arguments to the install (or upgrade) command, indicating the
// installer's intent.
repeated Flag flags = 3;
message Flag {
string name = 1;
string value = 2;
}
}

View File

@ -10,6 +10,8 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/linkerd/linkerd2/pkg/config"
"github.com/linkerd/linkerd2/pkg/admin" "github.com/linkerd/linkerd2/pkg/admin"
"github.com/linkerd/linkerd2/pkg/charts/linkerd2" "github.com/linkerd/linkerd2/pkg/charts/linkerd2"
"github.com/linkerd/linkerd2/pkg/flags" "github.com/linkerd/linkerd2/pkg/flags"
@ -120,7 +122,7 @@ func getUUIDAndVersion(ctx context.Context, k8sAPI *k8s.KubernetesAPI, controlle
var uuid string var uuid string
var version string var version string
cm, _, err := healthcheck.FetchLinkerdConfigMap(ctx, k8sAPI, controllerNamespace) cm, err := config.FetchLinkerdConfigMap(ctx, k8sAPI, controllerNamespace)
if err != nil { if err != nil {
log.Errorf("Failed to fetch linkerd-config: %s", err) log.Errorf("Failed to fetch linkerd-config: %s", err)
} else { } else {