...

Source file src/github.com/linkerd/linkerd2/test/integration/install/install_test.go

Documentation: github.com/linkerd/linkerd2/test/integration/install

     1  package test
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  	"regexp"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/go-test/deep"
    13  	"github.com/linkerd/linkerd2/pkg/cmd"
    14  	"github.com/linkerd/linkerd2/pkg/flags"
    15  	"github.com/linkerd/linkerd2/pkg/tls"
    16  	"github.com/linkerd/linkerd2/pkg/tree"
    17  	"github.com/linkerd/linkerd2/testutil"
    18  )
    19  
    20  //////////////////////
    21  ///   TEST SETUP   ///
    22  //////////////////////
    23  
    24  var (
    25  	TestHelper *testutil.TestHelper
    26  )
    27  
    28  func TestMain(m *testing.M) {
    29  	TestHelper = testutil.NewTestHelper()
    30  	os.Exit(m.Run())
    31  }
    32  
    33  var (
    34  	configMapUID string
    35  
    36  	helmTLSCerts *tls.CA
    37  
    38  	linkerdSvcEdge = []testutil.Service{
    39  		{Namespace: "linkerd", Name: "linkerd-dst"},
    40  		{Namespace: "linkerd", Name: "linkerd-identity"},
    41  
    42  		{Namespace: "linkerd", Name: "linkerd-dst-headless"},
    43  		{Namespace: "linkerd", Name: "linkerd-identity-headless"},
    44  	}
    45  
    46  	// Override in case edge starts to deviate from stable service-wise
    47  	linkerdSvcStable = linkerdSvcEdge
    48  
    49  	// skippedInboundPorts lists some ports to be marked as skipped, which will
    50  	// be verified in test/integration/inject
    51  	skippedInboundPorts  = "1234,5678"
    52  	skippedOutboundPorts = "1234,5678"
    53  	vizExtensionName     = "viz"
    54  )
    55  
    56  //////////////////////
    57  /// TEST EXECUTION ///
    58  //////////////////////
    59  
    60  // Tests are executed in serial in the order defined
    61  // Later tests depend on the success of earlier tests
    62  
    63  func TestVersionPreInstall(t *testing.T) {
    64  	version := "unavailable"
    65  	if TestHelper.UpgradeFromVersion() != "" {
    66  		version = TestHelper.UpgradeFromVersion()
    67  	}
    68  
    69  	err := TestHelper.CheckVersion(version)
    70  	if err != nil {
    71  		testutil.AnnotatedFatalf(t, "Version command failed", "Version command failed\n%s", err.Error())
    72  	}
    73  }
    74  
    75  func TestCheckPreInstall(t *testing.T) {
    76  	if TestHelper.ExternalIssuer() {
    77  		t.Skip("Skipping pre-install check for external issuer test")
    78  	}
    79  
    80  	if TestHelper.UpgradeFromVersion() != "" {
    81  		t.Skip("Skipping pre-install check for upgrade test")
    82  	}
    83  
    84  	if err := TestHelper.TestCheckPre(); err != nil {
    85  		t.Fatalf("'linkerd check --pre' command failed: %s", err)
    86  	}
    87  }
    88  
    89  func TestUpgradeTestAppWorksBeforeUpgrade(t *testing.T) {
    90  	if TestHelper.UpgradeFromVersion() != "" {
    91  		ctx := context.Background()
    92  		// make sure app is running
    93  		testAppNamespace := "upgrade-test"
    94  		for _, deploy := range []string{"emoji", "voting", "web"} {
    95  			if err := TestHelper.CheckPods(ctx, testAppNamespace, deploy, 1); err != nil {
    96  				//nolint:errorlint
    97  				if rce, ok := err.(*testutil.RestartCountError); ok {
    98  					testutil.AnnotatedWarn(t, "CheckPods timed-out", rce)
    99  				} else {
   100  					testutil.AnnotatedError(t, "CheckPods timed-out", err)
   101  				}
   102  			}
   103  		}
   104  
   105  		if err := testutil.ExerciseTestAppEndpoint("/api/list", testAppNamespace, TestHelper); err != nil {
   106  			testutil.AnnotatedFatalf(t, "error exercising test app endpoint before upgrade",
   107  				"error exercising test app endpoint before upgrade %s", err)
   108  		}
   109  	} else {
   110  		t.Skip("Skipping for non upgrade test")
   111  	}
   112  }
   113  
   114  func TestRetrieveUidPreUpgrade(t *testing.T) {
   115  	if TestHelper.UpgradeFromVersion() != "" {
   116  		var err error
   117  		configMapUID, err = TestHelper.KubernetesHelper.GetConfigUID(context.Background(), TestHelper.GetLinkerdNamespace())
   118  		if err != nil || configMapUID == "" {
   119  			testutil.AnnotatedFatalf(t, "error retrieving linkerd-config's uid",
   120  				"error retrieving linkerd-config's uid: %s", err)
   121  		}
   122  	}
   123  }
   124  
   125  func TestInstallOrUpgradeCli(t *testing.T) {
   126  	if TestHelper.GetHelmReleaseName() != "" {
   127  		return
   128  	}
   129  
   130  	var (
   131  		cmd  = "install"
   132  		args = []string{
   133  			"--controller-log-level", "debug",
   134  			"--set", fmt.Sprintf("proxy.image.version=%s", TestHelper.GetVersion()),
   135  			"--skip-inbound-ports", skippedInboundPorts,
   136  			"--set", "heartbeatSchedule=1 2 3 4 5",
   137  		}
   138  		vizCmd  = []string{"viz", "install"}
   139  		vizArgs = []string{
   140  			"--set", fmt.Sprintf("namespace=%s", TestHelper.GetVizNamespace()),
   141  		}
   142  	)
   143  
   144  	if TestHelper.GetClusterDomain() != "cluster.local" {
   145  		args = append(args, "--cluster-domain", TestHelper.GetClusterDomain())
   146  		vizArgs = append(vizArgs, "--set", fmt.Sprintf("clusterDomain=%s", TestHelper.GetClusterDomain()))
   147  	}
   148  
   149  	if policy := TestHelper.DefaultInboundPolicy(); policy != "" {
   150  		args = append(args, "--set", "proxy.defaultInboundPolicy="+policy)
   151  	}
   152  
   153  	if TestHelper.UpgradeFromVersion() != "" {
   154  
   155  		cmd = "upgrade"
   156  		// upgrade CRDs and then control-plane
   157  		out, err := TestHelper.LinkerdRun(cmd, "--crds")
   158  		if err != nil {
   159  			testutil.AnnotatedFatal(t, "'linkerd upgrade config' command failed", err)
   160  		}
   161  
   162  		// apply CRDs
   163  		// Limit the pruning only to known resources
   164  		// that we intend to be delete in this stage to prevent it
   165  		// from deleting other resources that have the
   166  		// label
   167  		out, err = TestHelper.KubectlApplyWithArgs(out, []string{
   168  			"--prune",
   169  			"-l", "linkerd.io/control-plane-ns=linkerd",
   170  			"--prune-allowlist", "rbac.authorization.k8s.io/v1/clusterrole",
   171  			"--prune-allowlist", "rbac.authorization.k8s.io/v1/clusterrolebinding",
   172  			"--prune-allowlist", "apiregistration.k8s.io/v1/apiservice",
   173  		}...)
   174  		if err != nil {
   175  			testutil.AnnotatedFatalf(t, "'kubectl apply' command failed",
   176  				"kubectl apply command failed\n%s", out)
   177  		}
   178  
   179  		// prepare for upgrade of control-plane
   180  		edge, err := regexp.Match(`(edge)-([0-9]+\.[0-9]+\.[0-9]+)`, []byte(TestHelper.UpgradeFromVersion()))
   181  		if err != nil {
   182  			testutil.AnnotatedFatal(t, "could not match regex", err)
   183  		}
   184  
   185  		if edge {
   186  			args = append(args, []string{"--set", fmt.Sprintf("proxyInit.ignoreOutboundPorts=%s", strings.Replace(skippedOutboundPorts, ",", "\\,", 1))}...)
   187  		} else {
   188  			args = append(args, []string{"--skip-outbound-ports", skippedOutboundPorts}...)
   189  		}
   190  	} else {
   191  		// install CRDs first
   192  		exec := append([]string{cmd}, append(args, "--crds")...)
   193  		out, err := TestHelper.LinkerdRun(exec...)
   194  		if err != nil {
   195  			testutil.AnnotatedFatal(t, "'linkerd install' command failed", err)
   196  		}
   197  		out, err = TestHelper.KubectlApply(out, "")
   198  		if err != nil {
   199  			testutil.AnnotatedFatalf(t, "'kubectl apply' command failed",
   200  				"kubectl apply command failed\n%s", out)
   201  		}
   202  	}
   203  
   204  	exec := append([]string{cmd}, args...)
   205  	out, err := TestHelper.LinkerdRun(exec...)
   206  	if err != nil {
   207  		testutil.AnnotatedFatal(t, "'linkerd install' command failed", err)
   208  	}
   209  
   210  	// test `linkerd upgrade --from-manifests`
   211  	if TestHelper.UpgradeFromVersion() != "" {
   212  		kubeArgs := append([]string{"--namespace", TestHelper.GetLinkerdNamespace(), "get"}, "configmaps", "-oyaml")
   213  		configManifests, err := TestHelper.Kubectl("", kubeArgs...)
   214  		if err != nil {
   215  			testutil.AnnotatedFatalf(t, "'kubectl get' command failed",
   216  				"'kubectl get' command failed with %s\n%s\n%s", err, configManifests, kubeArgs)
   217  		}
   218  
   219  		kubeArgs = append([]string{"--namespace", TestHelper.GetLinkerdNamespace(), "get"}, "secrets", "-oyaml")
   220  		secretManifests, err := TestHelper.Kubectl("", kubeArgs...)
   221  		if err != nil {
   222  			testutil.AnnotatedFatalf(t, "'kubectl get' command failed",
   223  				"'kubectl get' command failed with %s\n%s\n%s", err, secretManifests, kubeArgs)
   224  		}
   225  
   226  		manifests := configManifests + "---\n" + secretManifests
   227  
   228  		exec = append(exec, "--from-manifests", "-")
   229  		upgradeFromManifests, stderr, err := TestHelper.PipeToLinkerdRun(manifests, exec...)
   230  		if err != nil {
   231  			testutil.AnnotatedFatalf(t, "'linkerd upgrade --from-manifests' command failed",
   232  				"'linkerd upgrade --from-manifests' command failed with %s\n%s\n%s\n%s", err, stderr, upgradeFromManifests, manifests)
   233  		}
   234  
   235  		if out != upgradeFromManifests {
   236  			// retry in case it's just a discrepancy in the heartbeat cron schedule
   237  			exec := append([]string{cmd}, args...)
   238  			out, err := TestHelper.LinkerdRun(exec...)
   239  			if err != nil {
   240  				testutil.AnnotatedFatalf(t, fmt.Sprintf("command failed: %v", exec),
   241  					"command failed: %v\n%s\n%s", exec, out, stderr)
   242  			}
   243  
   244  			if out != upgradeFromManifests {
   245  				testutil.AnnotatedFatalf(t, "manifest upgrade differs from k8s upgrade",
   246  					"manifest upgrade differs from k8s upgrade.\nk8s upgrade:\n%s\nmanifest upgrade:\n%s", out, upgradeFromManifests)
   247  			}
   248  		}
   249  	}
   250  
   251  	// Limit the pruning only to known resources
   252  	// that we intend to be delete in this stage to prevent it
   253  	// from deleting other resources that have the
   254  	// label
   255  	cmdOut, err := TestHelper.KubectlApplyWithArgs(out, []string{
   256  		"--prune",
   257  		"-l", "linkerd.io/control-plane-ns=linkerd",
   258  		"--prune-allowlist", "apps/v1/deployment",
   259  		"--prune-allowlist", "core/v1/service",
   260  		"--prune-allowlist", "core/v1/configmap",
   261  	}...)
   262  	if err != nil {
   263  		testutil.AnnotatedFatalf(t, "'kubectl apply' command failed",
   264  			"'kubectl apply' command failed\n%s", cmdOut)
   265  	}
   266  
   267  	TestHelper.WaitRollout(t, testutil.LinkerdDeployReplicasEdge)
   268  
   269  	// It is necessary to clone LinkerdVizDeployReplicas so that we do not
   270  	// mutate its original value.
   271  	expectedDeployments := make(map[string]testutil.DeploySpec)
   272  	for k, v := range testutil.LinkerdVizDeployReplicas {
   273  		expectedDeployments[k] = v
   274  	}
   275  
   276  	// Install Linkerd Viz Extension
   277  	if TestHelper.UpgradeFromVersion() != "" {
   278  		exec = append(vizCmd, vizArgs...)
   279  		out, err = TestHelper.LinkerdRun(exec...)
   280  		if err != nil {
   281  			testutil.AnnotatedFatal(t, "'linkerd viz install' command failed", err)
   282  		}
   283  
   284  		out, err = TestHelper.KubectlApplyWithArgs(out, []string{
   285  			"--prune",
   286  			"-l", "linkerd.io/extension=viz",
   287  		}...)
   288  		if err != nil {
   289  			testutil.AnnotatedFatalf(t, "'kubectl apply' command failed",
   290  				"'kubectl apply' command failed\n%s", out)
   291  		}
   292  
   293  		TestHelper.WaitRollout(t, expectedDeployments)
   294  	}
   295  
   296  	// Install Linkerd Viz Extension
   297  	exec = append(vizCmd, vizArgs...)
   298  	out, err = TestHelper.LinkerdRun(exec...)
   299  	if err != nil {
   300  		testutil.AnnotatedFatal(t, "'linkerd viz install' command failed", err)
   301  	}
   302  
   303  	out, err = TestHelper.KubectlApplyWithArgs(out, []string{
   304  		"--prune",
   305  		"-l", "linkerd.io/extension=viz",
   306  	}...)
   307  	if err != nil {
   308  		testutil.AnnotatedFatalf(t, "'kubectl apply' command failed",
   309  			"'kubectl apply' command failed\n%s", out)
   310  	}
   311  
   312  	TestHelper.WaitRollout(t, expectedDeployments)
   313  
   314  }
   315  
   316  // helmInstallFlags returns the flags required for the `helm install` command,
   317  // both for the linkerd-control-plane and the linkerd-viz charts
   318  func helmInstallFlags(root *tls.CA) ([]string, []string) {
   319  	coreArgs := []string{
   320  		"--set", "controllerLogLevel=debug",
   321  		"--set", "linkerdVersion=" + TestHelper.UpgradeHelmFromVersion(),
   322  		"--set", "proxy.image.version=" + TestHelper.UpgradeHelmFromVersion(),
   323  		"--set", "identityTrustDomain=cluster.local",
   324  		"--set", "identityTrustAnchorsPEM=" + root.Cred.Crt.EncodeCertificatePEM(),
   325  		"--set", "identity.issuer.tls.crtPEM=" + root.Cred.Crt.EncodeCertificatePEM(),
   326  		"--set", "identity.issuer.tls.keyPEM=" + root.Cred.EncodePrivateKeyPEM(),
   327  		"--set", "identity.issuer.crtExpiry=" + root.Cred.Crt.Certificate.NotAfter.Format(time.RFC3339),
   328  	}
   329  	vizArgs := []string{
   330  		"--namespace", TestHelper.GetVizNamespace(),
   331  		"--create-namespace",
   332  		"--set", "linkerdVersion=" + TestHelper.UpgradeHelmFromVersion(),
   333  	}
   334  	return coreArgs, vizArgs
   335  }
   336  
   337  // helmUpgradeFlags returns the flags required for the `helm upgrade` command,
   338  // both for the linkerd-control-plane and the linkerd-viz charts
   339  func helmUpgradeFlags(root *tls.CA) ([]string, []string) {
   340  	skippedInboundPortsEscaped := strings.Replace(skippedInboundPorts, ",", "\\,", 1)
   341  	coreArgs := []string{
   342  		"--set", "controllerLogLevel=debug",
   343  		"--set", "linkerdVersion=" + TestHelper.GetVersion(),
   344  		// these ports will get verified in test/integration/inject
   345  		"--set", "proxyInit.ignoreInboundPorts=" + skippedInboundPortsEscaped,
   346  		"--set", "identityTrustAnchorsPEM=" + root.Cred.Crt.EncodeCertificatePEM(),
   347  		"--set", "identity.issuer.tls.crtPEM=" + root.Cred.Crt.EncodeCertificatePEM(),
   348  		"--set", "identity.issuer.tls.keyPEM=" + root.Cred.EncodePrivateKeyPEM(),
   349  	}
   350  	vizArgs := []string{
   351  		"--namespace", TestHelper.GetVizNamespace(),
   352  		"--set", "linkerdVersion=" + TestHelper.GetVersion(),
   353  	}
   354  
   355  	if override := os.Getenv(flags.EnvOverrideDockerRegistry); override != "" {
   356  		coreArgs = append(coreArgs,
   357  			"--set", "policyController.image.name="+cmd.RegistryOverride("cr.l5d.io/linkerd/policy-controller", override),
   358  			"--set", "proxy.image.name="+cmd.RegistryOverride("cr.l5d.io/linkerd/proxy", override),
   359  			"--set", "proxyInit.image.name="+cmd.RegistryOverride("cr.l5d.io/linkerd/proxy-init", override),
   360  			"--set", "controllerImage="+cmd.RegistryOverride("cr.l5d.io/linkerd/controller", override),
   361  			"--set", "debugContainer.image.name="+cmd.RegistryOverride("cr.l5d.io/linkerd/debug", override),
   362  		)
   363  		vizArgs = append(vizArgs,
   364  			"--set", "metricsAPI.image.registry="+override,
   365  			"--set", "tap.image.registry="+override,
   366  			"--set", "tapInjector.image.registry="+override,
   367  			"--set", "dashboard.image.registry="+override,
   368  		)
   369  	}
   370  
   371  	return coreArgs, vizArgs
   372  }
   373  
   374  func TestInstallHelm(t *testing.T) {
   375  	if TestHelper.GetHelmReleaseName() == "" {
   376  		return
   377  	}
   378  
   379  	cn := fmt.Sprintf("identity.%s.cluster.local", TestHelper.GetLinkerdNamespace())
   380  	var err error
   381  	helmTLSCerts, err = tls.GenerateRootCAWithDefaults(cn)
   382  	if err != nil {
   383  		testutil.AnnotatedFatalf(t, "failed to generate root certificate for identity",
   384  			"failed to generate root certificate for identity: %s", err)
   385  	}
   386  
   387  	args, vizArgs := helmInstallFlags(helmTLSCerts)
   388  
   389  	releaseName := TestHelper.GetHelmReleaseName() + "-crds"
   390  	if stdout, stderr, err := TestHelper.HelmInstall("linkerd/linkerd-crds", releaseName, args...); err != nil {
   391  		testutil.AnnotatedFatalf(t, "'helm install' command failed",
   392  			"'helm install' command failed\n%s\n%s", stdout, stderr)
   393  	}
   394  
   395  	releaseName = TestHelper.GetHelmReleaseName() + "-control-plane"
   396  	if stdout, stderr, err := TestHelper.HelmInstall("linkerd/linkerd-control-plane", releaseName, args...); err != nil {
   397  		testutil.AnnotatedFatalf(t, "'helm install' command failed",
   398  			"'helm install' command failed\n%s\n%s", stdout, stderr)
   399  	}
   400  	TestHelper.WaitRollout(t, testutil.LinkerdDeployReplicasEdge)
   401  
   402  	releaseName = TestHelper.GetHelmReleaseName() + "-l5d-viz"
   403  	if stdout, stderr, err := TestHelper.HelmCmdPlain("install", "linkerd/linkerd-viz", releaseName, vizArgs...); err != nil {
   404  		testutil.AnnotatedFatalf(t, "'helm install' command failed",
   405  			"'helm install' command failed\n%s\n%s", stdout, stderr)
   406  	}
   407  
   408  	TestHelper.WaitRollout(t, testutil.LinkerdVizDeployReplicas)
   409  }
   410  
   411  func TestControlPlaneResourcesPostInstall(t *testing.T) {
   412  	expectedServices := linkerdSvcEdge
   413  	expectedDeployments := testutil.LinkerdDeployReplicasEdge
   414  	if !TestHelper.ExternalPrometheus() {
   415  		vizServices := []testutil.Service{
   416  			{Namespace: "linkerd-viz", Name: "web"},
   417  			{Namespace: "linkerd-viz", Name: "tap"},
   418  			{Namespace: "linkerd-viz", Name: "prometheus"},
   419  		}
   420  		expectedServices = append(expectedServices, vizServices...)
   421  		expectedDeployments["prometheus"] = testutil.DeploySpec{Namespace: "linkerd-viz", Replicas: 1}
   422  	}
   423  
   424  	// Upgrade Case
   425  	if TestHelper.UpgradeHelmFromVersion() != "" {
   426  		expectedServices = linkerdSvcStable
   427  		expectedDeployments = testutil.LinkerdDeployReplicasStable
   428  	}
   429  	testutil.TestResourcesPostInstall(TestHelper.GetLinkerdNamespace(), expectedServices, expectedDeployments, TestHelper, t)
   430  }
   431  
   432  func TestUpgradeHelm(t *testing.T) {
   433  	if TestHelper.UpgradeHelmFromVersion() == "" {
   434  		t.Skip("Skipping as this is not a helm upgrade test")
   435  	}
   436  
   437  	args := []string{
   438  		// implicit as at least one value is set manually: "--reset-values",
   439  		// (see https://medium.com/@kcatstack/understand-helm-upgrade-flags-reset-values-reuse-values-6e58ac8f127e )
   440  
   441  		// Also ensure that the CPU requests are fairly small (<100m) in order
   442  		// to avoid squeeze-out of other pods in CI tests.
   443  
   444  		"--set", "proxy.resources.cpu.limit=200m",
   445  		"--set", "proxy.resources.cpu.request=20m",
   446  		"--set", "proxy.resources.memory.limit=200Mi",
   447  		"--set", "proxy.resources.memory.request=100Mi",
   448  		// actually sets the value for the controller pod
   449  		"--set", "destinationProxyResources.cpu.limit=1020m",
   450  		"--set", "destinationProxyResources.memory.request=102Mi",
   451  		"--set", "identityProxyResources.cpu.limit=1040m",
   452  		"--set", "identityProxyResources.memory.request=104Mi",
   453  		"--set", "proxyInjectorProxyResources.cpu.limit=1060m",
   454  		"--set", "proxyInjectorProxyResources.memory.request=106Mi",
   455  		"--atomic",
   456  		"--timeout", "60m",
   457  		"--wait",
   458  	}
   459  	extraArgs, vizArgs := helmUpgradeFlags(helmTLSCerts)
   460  	args = append(args, extraArgs...)
   461  	releaseName := TestHelper.GetHelmReleaseName() + "-crds"
   462  	if stdout, stderr, err := TestHelper.HelmUpgrade(TestHelper.GetHelmCharts()+"/linkerd-crds", releaseName, args...); err != nil {
   463  		testutil.AnnotatedFatalf(t, "'helm upgrade' command failed",
   464  			"'helm upgrade' command failed\n%s\n%s", stdout, stderr)
   465  	}
   466  
   467  	releaseName = TestHelper.GetHelmReleaseName() + "-control-plane"
   468  	if stdout, stderr, err := TestHelper.HelmUpgrade(TestHelper.GetHelmCharts()+"/linkerd-control-plane", releaseName, args...); err != nil {
   469  		TestHelper.WaitRollout(t, testutil.LinkerdDeployReplicasEdge)
   470  		testutil.AnnotatedFatalf(t, "'helm upgrade' command failed",
   471  			"'helm upgrade' command failed\n%s\n%s", stdout, stderr)
   472  	}
   473  	TestHelper.WaitRollout(t, testutil.LinkerdVizDeployReplicas)
   474  
   475  	vizChart := TestHelper.GetLinkerdVizHelmChart()
   476  	releaseName = TestHelper.GetHelmReleaseName() + "-l5d-viz"
   477  	if stdout, stderr, err := TestHelper.HelmCmdPlain("upgrade", vizChart, releaseName, vizArgs...); err != nil {
   478  		testutil.AnnotatedFatalf(t, "'helm upgrade' command failed",
   479  			"'helm upgrade' command failed\n%s\n%s", stdout, stderr)
   480  	}
   481  
   482  	TestHelper.WaitRollout(t, testutil.LinkerdVizDeployReplicas)
   483  
   484  	TestHelper.AddInstalledExtension(vizExtensionName)
   485  }
   486  
   487  func TestRetrieveUidPostUpgrade(t *testing.T) {
   488  	if TestHelper.UpgradeFromVersion() != "" {
   489  		newConfigMapUID, err := TestHelper.KubernetesHelper.GetConfigUID(context.Background(), TestHelper.GetLinkerdNamespace())
   490  		if err != nil || newConfigMapUID == "" {
   491  			testutil.AnnotatedFatalf(t, "error retrieving linkerd-config's uid",
   492  				"error retrieving linkerd-config's uid: %s", err)
   493  		}
   494  		if configMapUID != newConfigMapUID {
   495  			testutil.AnnotatedFatalf(t, "linkerd-config's uid after upgrade doesn't match its value before the upgrade",
   496  				"linkerd-config's uid after upgrade [%s] doesn't match its value before the upgrade [%s]",
   497  				newConfigMapUID, configMapUID,
   498  			)
   499  		}
   500  	}
   501  }
   502  
   503  func TestOverridesSecret(t *testing.T) {
   504  
   505  	if TestHelper.GetHelmReleaseName() != "" {
   506  		t.Skip("Skipping as this is a helm test where linkerd-config-overrides is absent")
   507  	}
   508  
   509  	configOverridesSecret, err := TestHelper.KubernetesHelper.GetSecret(context.Background(), TestHelper.GetLinkerdNamespace(), "linkerd-config-overrides")
   510  	if err != nil {
   511  		testutil.AnnotatedFatalf(t, "could not retrieve linkerd-config-overrides",
   512  			"could not retrieve linkerd-config-overrides\n%s", err)
   513  	}
   514  
   515  	overrides := configOverridesSecret.Data["linkerd-config-overrides"]
   516  	overridesTree, err := tree.BytesToTree(overrides)
   517  	if err != nil {
   518  		testutil.AnnotatedFatalf(t, "could not retrieve linkerd-config-overrides",
   519  			"could not retrieve linkerd-config-overrides\n%s", err)
   520  	}
   521  
   522  	// Check for fields that were added during install
   523  	testCases := []struct {
   524  		path  []string
   525  		value string
   526  	}{
   527  		{
   528  			[]string{"controllerLogLevel"},
   529  			"debug",
   530  		},
   531  		{
   532  			[]string{"proxyInit", "ignoreInboundPorts"},
   533  			skippedInboundPorts,
   534  		},
   535  	}
   536  
   537  	// Check for fields that were added during upgrade
   538  	if TestHelper.UpgradeFromVersion() != "" {
   539  		testCases = append(testCases, []struct {
   540  			path  []string
   541  			value string
   542  		}{
   543  			{
   544  				[]string{"proxyInit", "ignoreOutboundPorts"},
   545  				skippedOutboundPorts,
   546  			},
   547  		}...)
   548  	}
   549  
   550  	for _, tc := range testCases {
   551  		tc := tc // pin
   552  		t.Run(fmt.Sprintf("%s: %s", strings.Join(tc.path, "/"), tc.value), func(t *testing.T) {
   553  			finalValue, err := overridesTree.GetString(tc.path...)
   554  			if err != nil {
   555  				testutil.AnnotatedFatalf(t, "could not perform tree.GetString",
   556  					"could not perform tree.GetString\n%s", err)
   557  			}
   558  
   559  			if tc.value != finalValue {
   560  				testutil.AnnotatedFatalf(t, fmt.Sprintf("Values at path %s do not match", strings.Join(tc.path, "/")),
   561  					"Expected value at [%s] to be [%s] but received [%s]",
   562  					strings.Join(tc.path, "/"), tc.value, finalValue)
   563  			}
   564  		})
   565  	}
   566  
   567  	extractValue := func(t *testing.T, path ...string) string {
   568  		val, err := overridesTree.GetString(path...)
   569  		if err != nil {
   570  			testutil.AnnotatedFatalf(t, "error calling overridesTree.GetString()",
   571  				"error calling overridesTree.GetString(): %s", err)
   572  			return ""
   573  
   574  		}
   575  		return val
   576  	}
   577  
   578  	t.Run("Check if any unknown fields sneaked in", func(t *testing.T) {
   579  		knownKeys := tree.Tree{
   580  			"controllerLogLevel": "debug",
   581  			"heartbeatSchedule":  "1 2 3 4 5",
   582  			"identity": tree.Tree{
   583  				"issuer": tree.Tree{},
   584  			},
   585  			"identityTrustAnchorsPEM": extractValue(t, "identityTrustAnchorsPEM"),
   586  			"proxyInit": tree.Tree{
   587  				"ignoreInboundPorts": skippedInboundPorts,
   588  			},
   589  			"proxy": tree.Tree{
   590  				"image": tree.Tree{
   591  					"version": TestHelper.GetVersion(),
   592  				},
   593  			},
   594  		}
   595  
   596  		if reg := os.Getenv(flags.EnvOverrideDockerRegistry); reg != "" {
   597  			knownKeys["controllerImage"] = reg + "/controller"
   598  			knownKeys["debugContainer"] = tree.Tree{
   599  				"image": tree.Tree{
   600  					"name": reg + "/debug",
   601  				},
   602  			}
   603  			knownKeys["policyController"] = tree.Tree{
   604  				"image": tree.Tree{
   605  					"name": reg + "/policy-controller",
   606  				},
   607  			}
   608  			knownKeys["proxy"] = tree.Tree{
   609  				"image": tree.Tree{
   610  					"name":    reg + "/proxy",
   611  					"version": TestHelper.GetVersion(),
   612  				},
   613  			}
   614  			knownKeys["proxyInit"].(tree.Tree)["image"] = tree.Tree{
   615  				"name": reg + "/proxy-init",
   616  			}
   617  		}
   618  
   619  		// Check for fields that were added during upgrade
   620  		if TestHelper.UpgradeFromVersion() != "" {
   621  			knownKeys["proxyInit"].(tree.Tree)["ignoreOutboundPorts"] = skippedOutboundPorts
   622  		}
   623  
   624  		if TestHelper.GetClusterDomain() != "cluster.local" {
   625  			knownKeys["clusterDomain"] = TestHelper.GetClusterDomain()
   626  		}
   627  
   628  		if TestHelper.ExternalIssuer() {
   629  			knownKeys["identity"].(tree.Tree)["issuer"].(tree.Tree)["issuanceLifetime"] = "15s"
   630  			knownKeys["identity"].(tree.Tree)["issuer"].(tree.Tree)["scheme"] = "kubernetes.io/tls"
   631  		} else {
   632  			knownKeys["identity"].(tree.Tree)["issuer"].(tree.Tree)["tls"] = tree.Tree{
   633  				"crtPEM": extractValue(t, "identity", "issuer", "tls", "crtPEM"),
   634  				"keyPEM": extractValue(t, "identity", "issuer", "tls", "keyPEM"),
   635  			}
   636  		}
   637  
   638  		if TestHelper.CNI() {
   639  			knownKeys["cniEnabled"] = true
   640  		}
   641  
   642  		if policy := TestHelper.DefaultInboundPolicy(); policy != "" {
   643  			knownKeys["proxy"].(tree.Tree)["defaultInboundPolicy"] = policy
   644  		}
   645  
   646  		// Check if the keys in overridesTree match with knownKeys
   647  		if diff := deep.Equal(overridesTree.String(), knownKeys.String()); diff != nil {
   648  			testutil.AnnotatedFatalf(t, "Overrides and knownKeys are different", "%+v", diff)
   649  		}
   650  	})
   651  }
   652  
   653  type expectedData struct {
   654  	pod        string
   655  	cpuLimit   string
   656  	cpuRequest string
   657  	memLimit   string
   658  	memRequest string
   659  }
   660  
   661  var expectedResources = []expectedData{
   662  	{
   663  		pod:        "linkerd-destination",
   664  		cpuLimit:   "1020m",
   665  		cpuRequest: "20m",
   666  		memLimit:   "200Mi",
   667  		memRequest: "102Mi",
   668  	},
   669  	{
   670  		pod:        "linkerd-identity",
   671  		cpuLimit:   "1040m",
   672  		cpuRequest: "20m",
   673  		memLimit:   "200Mi",
   674  		memRequest: "104Mi",
   675  	},
   676  	{
   677  		pod:        "linkerd-proxy-injector",
   678  		cpuLimit:   "1060m",
   679  		cpuRequest: "20m",
   680  		memLimit:   "200Mi",
   681  		memRequest: "106Mi",
   682  	},
   683  }
   684  
   685  func TestComponentProxyResources(t *testing.T) {
   686  	if TestHelper.UpgradeHelmFromVersion() == "" {
   687  		t.Skip("Skipping as this is not a helm upgrade test")
   688  	}
   689  
   690  	for _, expected := range expectedResources {
   691  		resourceReqs, err := TestHelper.GetResources(context.Background(), "linkerd-proxy", expected.pod, TestHelper.GetLinkerdNamespace())
   692  		if err != nil {
   693  			testutil.AnnotatedFatalf(t, "setting proxy resources failed", "Error retrieving resource requirements for %s: %s", expected.pod, err)
   694  		}
   695  
   696  		cpuLimitStr := resourceReqs.Limits.Cpu().String()
   697  		if cpuLimitStr != expected.cpuLimit {
   698  			testutil.AnnotatedFatalf(t, "setting proxy resources failed", "unexpected %s CPU limit: expected %s, was %s", expected.pod, expected.cpuLimit, cpuLimitStr)
   699  		}
   700  		cpuRequestStr := resourceReqs.Requests.Cpu().String()
   701  		if cpuRequestStr != expected.cpuRequest {
   702  			testutil.AnnotatedFatalf(t, "setting proxy resources failed", "unexpected %s CPU request: expected %s, was %s", expected.pod, expected.cpuRequest, cpuRequestStr)
   703  		}
   704  		memLimitStr := resourceReqs.Limits.Memory().String()
   705  		if memLimitStr != expected.memLimit {
   706  			testutil.AnnotatedFatalf(t, "setting proxy resources failed", "unexpected %s memory limit: expected %s, was %s", expected.pod, expected.memLimit, memLimitStr)
   707  		}
   708  		memRequestStr := resourceReqs.Requests.Memory().String()
   709  		if memRequestStr != expected.memRequest {
   710  			testutil.AnnotatedFatalf(t, "setting proxy resources failed", "unexpected %s memory request: expected %s, was %s", expected.pod, expected.memRequest, memRequestStr)
   711  		}
   712  	}
   713  }
   714  
   715  func TestVersionPostInstall(t *testing.T) {
   716  	err := TestHelper.CheckVersion(TestHelper.GetVersion())
   717  	if err != nil {
   718  		testutil.AnnotatedFatalf(t, "Version command failed",
   719  			"Version command failed\n%s", err.Error())
   720  	}
   721  }
   722  
   723  func TestCheckPostInstall(t *testing.T) {
   724  	if err := TestHelper.TestCheckProxy(TestHelper.GetVersion(), TestHelper.GetLinkerdNamespace()); err != nil {
   725  		t.Fatalf("'linkerd check --proxy' command failed: %s", err)
   726  	}
   727  }
   728  
   729  func TestUpgradeTestAppWorksAfterUpgrade(t *testing.T) {
   730  	if TestHelper.UpgradeFromVersion() != "" {
   731  		testAppNamespace := "upgrade-test"
   732  		if err := testutil.ExerciseTestAppEndpoint("/api/vote?choice=:policeman:", testAppNamespace, TestHelper); err != nil {
   733  			testutil.AnnotatedFatalf(t, "error exercising test app endpoint after upgrade",
   734  				"error exercising test app endpoint after upgrade %s", err)
   735  		}
   736  	} else {
   737  		t.Skip("Skipping for non upgrade test")
   738  	}
   739  }
   740  
   741  func TestRestarts(t *testing.T) {
   742  	expectedDeployments := testutil.LinkerdDeployReplicasEdge
   743  	if !TestHelper.ExternalPrometheus() {
   744  		expectedDeployments["prometheus"] = testutil.DeploySpec{Namespace: "linkerd-viz", Replicas: 1}
   745  	}
   746  	for deploy, spec := range expectedDeployments {
   747  		if err := TestHelper.CheckPods(context.Background(), spec.Namespace, deploy, spec.Replicas); err != nil {
   748  			//nolint:errorlint
   749  			if rce, ok := err.(*testutil.RestartCountError); ok {
   750  				testutil.AnnotatedWarn(t, "CheckPods timed-out", rce)
   751  			} else {
   752  				testutil.AnnotatedFatal(t, "CheckPods timed-out", err)
   753  			}
   754  		}
   755  	}
   756  }
   757  

View as plain text