istio
328 строк · 13.5 Кб
1//go:build integ
2// +build integ
3
4// Copyright Istio Authors
5//
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18package helmupgrade19
20import (21"context"22"fmt"23"path/filepath"24"strings"25
26metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"27
28"istio.io/api/label"29"istio.io/istio/pkg/test/framework"30"istio.io/istio/pkg/test/framework/components/cluster"31kubecluster "istio.io/istio/pkg/test/framework/components/cluster/kube"32"istio.io/istio/pkg/test/helm"33kubetest "istio.io/istio/pkg/test/kube"34"istio.io/istio/pkg/test/scopes"35"istio.io/istio/pkg/test/shell"36"istio.io/istio/pkg/test/util/retry"37helmtest "istio.io/istio/tests/integration/helm"38"istio.io/istio/tests/util/sanitycheck"39)
40
41const (42gcrHub = "gcr.io/istio-release"43prodTag = "prod"44canaryTag = "canary"45latestRevisionTag = "latest"46)
47
48// upgradeCharts upgrades Istio using Helm charts with the provided
49// override values file to the latest charts in $ISTIO_SRC/manifests
50func upgradeCharts(ctx framework.TestContext, h *helm.Helm, overrideValuesFile string, isAmbient bool) {51execCmd := fmt.Sprintf(52"kubectl apply -n %v -f %v",53helmtest.IstioNamespace,54filepath.Join(helmtest.ManifestsChartPath, helmtest.BaseChart, helmtest.CRDsFolder))55_, err := shell.Execute(false, execCmd)56if err != nil {57ctx.Fatalf("couldn't run kubectl apply on crds folder: %v", err)58}59
60// Upgrade base chart61err = h.UpgradeChart(helmtest.BaseReleaseName, filepath.Join(helmtest.ManifestsChartPath, helmtest.BaseChart),62helmtest.IstioNamespace, overrideValuesFile, helmtest.Timeout, "--skip-crds")63if err != nil {64ctx.Fatalf("failed to upgrade istio %s chart", helmtest.BaseReleaseName)65}66
67// Upgrade discovery chart68err = h.UpgradeChart(helmtest.IstiodReleaseName, filepath.Join(helmtest.ManifestsChartPath, helmtest.ControlChartsDir, helmtest.DiscoveryChartsDir),69helmtest.IstioNamespace, overrideValuesFile, helmtest.Timeout)70if err != nil {71ctx.Fatalf("failed to upgrade istio %s chart", helmtest.IstiodReleaseName)72}73
74if isAmbient {75// Upgrade istio-cni chart76err = h.UpgradeChart(helmtest.CniReleaseName, filepath.Join(helmtest.ManifestsChartPath, helmtest.CniChartsDir),77helmtest.IstioNamespace, overrideValuesFile, helmtest.Timeout)78if err != nil {79ctx.Fatalf("failed to upgrade istio %s chart", helmtest.CniReleaseName)80}81// Upgrade ztunnel chart82err = h.UpgradeChart(helmtest.ZtunnelReleaseName, filepath.Join(helmtest.ManifestsChartPath, helmtest.ZtunnelChartsDir),83helmtest.IstioNamespace, overrideValuesFile, helmtest.Timeout)84if err != nil {85ctx.Fatalf("failed to upgrade istio %s chart", helmtest.ZtunnelReleaseName)86}87}88
89// Upgrade ingress gateway chart90err = h.UpgradeChart(helmtest.IngressReleaseName, filepath.Join(helmtest.ManifestsChartPath, helmtest.GatewayChartsDir),91helmtest.IstioNamespace, overrideValuesFile, helmtest.Timeout)92if err != nil {93ctx.Fatalf("failed to upgrade istio %s chart", helmtest.IngressReleaseName)94}95}
96
97// deleteIstio deletes installed Istio Helm charts and resources
98func deleteIstio(cs cluster.Cluster, h *helm.Helm, gatewayChartInstalled bool) error {99scopes.Framework.Infof("cleaning up resources")100if gatewayChartInstalled {101if err := h.DeleteChart(helmtest.IngressReleaseName, helmtest.IstioNamespace); err != nil {102return fmt.Errorf("failed to delete %s release", helmtest.IngressReleaseName)103}104}105
106if err := h.DeleteChart(helmtest.IstiodReleaseName, helmtest.IstioNamespace); err != nil {107return fmt.Errorf("failed to delete %s release", helmtest.IstiodReleaseName)108}109
110return cleanupIstio(cs, h)111}
112
113func cleanupIstio(cs cluster.Cluster, h *helm.Helm) error {114if err := h.DeleteChart(helmtest.BaseReleaseName, helmtest.IstioNamespace); err != nil {115return fmt.Errorf("failed to delete %s release", helmtest.BaseReleaseName)116}117if err := cs.Kube().CoreV1().Namespaces().Delete(context.TODO(), helmtest.IstioNamespace, metav1.DeleteOptions{}); err != nil {118return fmt.Errorf("failed to delete istio namespace: %v", err)119}120if err := kubetest.WaitForNamespaceDeletion(cs.Kube(), helmtest.IstioNamespace, retry.Timeout(helmtest.RetryTimeOut)); err != nil {121return fmt.Errorf("waiting for istio namespace to be deleted: %v", err)122}123return nil124}
125
126// deleteIstioCanary deletes installed Istio Helm charts and resources
127func deleteIstioRevision(h *helm.Helm, revision string) error {128scopes.Framework.Infof("cleaning up revision resources (%s)", revision)129name := helmtest.IstiodReleaseName + "-" + strings.ReplaceAll(revision, ".", "-")130if err := h.DeleteChart(name, helmtest.IstioNamespace); err != nil {131return fmt.Errorf("failed to delete revision (%s)", name)132}133
134return nil135}
136
137// performInPlaceUpgradeFunc returns the provided function necessary to run inside an integration test
138// for upgrade capability
139func performInPlaceUpgradeFunc(previousVersion string, isAmbient bool) func(framework.TestContext) {140return func(t framework.TestContext) {141cs := t.Clusters().Default().(*kubecluster.Cluster)142h := helm.New(cs.Filename())143
144t.CleanupConditionally(func() {145// only need to do call this once as helm doesn't need to remove146// all versions147helmtest.DeleteIstio(t, h, cs, isAmbient)148})149overrideValuesFile := helmtest.GetValuesOverrides(t, gcrHub, previousVersion, "", isAmbient)150helmtest.InstallIstio(t, cs, h, overrideValuesFile, previousVersion, true, isAmbient)151helmtest.VerifyInstallation(t, cs, true, isAmbient)152
153_, oldClient, oldServer := sanitycheck.SetupTrafficTest(t, t, "")154sanitycheck.RunTrafficTestClientServer(t, oldClient, oldServer)155
156s := t.Settings()157overrideValuesFile = helmtest.GetValuesOverrides(t, s.Image.Hub, s.Image.Tag, "", isAmbient)158upgradeCharts(t, h, overrideValuesFile, isAmbient)159helmtest.VerifyInstallation(t, cs, true, isAmbient)160
161_, newClient, newServer := sanitycheck.SetupTrafficTest(t, t, "")162sanitycheck.RunTrafficTestClientServer(t, newClient, newServer)163
164// now check that we are compatible with N-1 proxy with N proxy165sanitycheck.RunTrafficTestClientServer(t, oldClient, newServer)166}167}
168
169// performCanaryUpgradeFunc returns the provided function necessary to run inside an integration test
170// for upgrade capability with revisions
171func performCanaryUpgradeFunc(previousVersion string) func(framework.TestContext) {172return func(t framework.TestContext) {173cs := t.Clusters().Default().(*kubecluster.Cluster)174h := helm.New(cs.Filename())175t.CleanupConditionally(func() {176err := deleteIstioRevision(h, canaryTag)177if err != nil {178t.Fatalf("could not delete istio: %v", err)179}180err = deleteIstio(cs, h, false)181if err != nil {182t.Fatalf("could not delete istio: %v", err)183}184})185
186overrideValuesFile := helmtest.GetValuesOverrides(t, gcrHub, previousVersion, "", false)187helmtest.InstallIstio(t, cs, h, overrideValuesFile, previousVersion, false, false)188helmtest.VerifyInstallation(t, cs, false, false)189
190_, oldClient, oldServer := sanitycheck.SetupTrafficTest(t, t, "")191sanitycheck.RunTrafficTestClientServer(t, oldClient, oldServer)192
193s := t.Settings()194overrideValuesFile = helmtest.GetValuesOverrides(t, s.Image.Hub, s.Image.Tag, canaryTag, false)195helmtest.InstallIstioWithRevision(t, cs, h, "", canaryTag, overrideValuesFile, true, false)196helmtest.VerifyInstallation(t, cs, false, false)197
198// now that we've installed with a revision we have a new mutating webhook199helmtest.VerifyMutatingWebhookConfigurations(t, cs, []string{200"istio-sidecar-injector",201"istio-sidecar-injector-canary",202})203
204_, newClient, newServer := sanitycheck.SetupTrafficTest(t, t, canaryTag)205sanitycheck.RunTrafficTestClientServer(t, newClient, newServer)206
207// now check that we are compatible with N-1 proxy with N proxy208sanitycheck.RunTrafficTestClientServer(t, oldClient, newServer)209}210}
211
212// performRevisionTagsUpgradeFunc returns the provided function necessary to run inside an integration test
213// for upgrade capability with stable label revision upgrades
214func performRevisionTagsUpgradeFunc(previousVersion string) func(framework.TestContext) {215return func(t framework.TestContext) {216cs := t.Clusters().Default().(*kubecluster.Cluster)217h := helm.New(cs.Filename())218t.CleanupConditionally(func() {219err := deleteIstioRevision(h, latestRevisionTag)220if err != nil {221t.Fatalf("could not delete istio revision (%v): %v", latestRevisionTag, err)222}223err = deleteIstioRevision(h, previousVersion)224if err != nil {225t.Fatalf("could not delete istio revision (%v): %v", previousVersion, err)226}227
228err = cleanupIstio(cs, h)229if err != nil {230t.Fatalf("could not cleanup istio: %v", err)231}232})233
234// install MAJOR.MINOR.PATCH charts with revision set to "MAJOR-MINOR-PATCH" name. For example,235// helm install istio-base istio/base --version 1.15.0 --namespace istio-system -f values.yaml236// helm install istiod-1-15 istio/istiod --version 1.15.0 -f values.yaml237previousRevision := strings.ReplaceAll(previousVersion, ".", "-")238overrideValuesFile := helmtest.GetValuesOverrides(t, gcrHub, previousVersion, previousRevision, false)239helmtest.InstallIstioWithRevision(t, cs, h, previousVersion, previousRevision, overrideValuesFile, false, true)240helmtest.VerifyInstallation(t, cs, false, false)241
242// helm template istiod-1-15-0 istio/istiod --version 1.15.0 -s templates/revision-tags.yaml --set revision=1-15-0 --set revisionTags={prod}243helmtest.SetRevisionTagWithVersion(t, h, previousRevision, prodTag, previousVersion)244helmtest.VerifyMutatingWebhookConfigurations(t, cs, []string{245"istio-revision-tag-prod",246fmt.Sprintf("istio-sidecar-injector-%s", previousRevision),247})248
249// setup istio.io/rev=1-15-0 for the default-1 namespace250oldNs, oldClient, oldServer := sanitycheck.SetupTrafficTest(t, t, previousRevision)251sanitycheck.RunTrafficTestClientServer(t, oldClient, oldServer)252
253// install the charts from this branch with revision set to "latest"254// helm upgrade istio-base ../manifests/charts/base --namespace istio-system -f values.yaml255// helm install istiod-latest ../manifests/charts/istio-control/istio-discovery -f values.yaml256s := t.Settings()257overrideValuesFile = helmtest.GetValuesOverrides(t, s.Image.Hub, s.Image.Tag, latestRevisionTag, false)258helmtest.InstallIstioWithRevision(t, cs, h, "", latestRevisionTag, overrideValuesFile, true, false)259helmtest.VerifyInstallation(t, cs, false, false)260
261// helm template istiod-latest ../manifests/charts/istio-control/istio-discovery --namespace istio-system262// -s templates/revision-tags.yaml --set revision=latest --set revisionTags={canary}263helmtest.SetRevisionTag(t, h, "", latestRevisionTag, canaryTag, helmtest.ManifestsChartPath, "")264helmtest.VerifyMutatingWebhookConfigurations(t, cs, []string{265"istio-revision-tag-prod",266fmt.Sprintf("istio-sidecar-injector-%v", previousRevision),267"istio-revision-tag-canary",268"istio-sidecar-injector-latest",269})270
271// setup istio.io/rev=latest for the default-2 namespace272_, newClient, newServer := sanitycheck.SetupTrafficTest(t, t, latestRevisionTag)273sanitycheck.RunTrafficTestClientServer(t, newClient, newServer)274
275// now check that we are compatible with N-1 proxy with N proxy between a client276// in default-1 namespace and a server in the default-2 namespace, respectively277sanitycheck.RunTrafficTestClientServer(t, oldClient, newServer)278
279// change the mutating webhook configuration to use the latest revision (istiod-latest service in istio-system)280// helm template istiod-latest ../manifests/charts/istio-control/istio-discovery --namespace istio-system281// -s templates/revision-tags.yaml --set revision=latest --set revisionTags={prod}282helmtest.SetRevisionTag(t, h, "", latestRevisionTag, prodTag, helmtest.ManifestsChartPath, "")283
284// change the old namespace that was pointing to the old prod (1-15-0) to point to the285// 'latest' revision by setting the `istio.io/rev=prod` label on the namespace286err := oldNs.SetLabel(label.IoIstioRev.Name, prodTag)287if err != nil {288t.Fatal("could not remove istio.io/rev from old namespace")289}290
291err = oldClient.Restart()292if err != nil {293t.Fatal("could not restart old client")294}295err = oldServer.Restart()296if err != nil {297t.Fatal("could not restart old server")298}299
300// make sure the restarted pods in default-1 namespace do not use301// the previous version (check for the previousVersion in the image string)302err = checkVersion(t, oldNs.Name(), previousVersion)303if err != nil {304t.Fatalf("found a pod in namespace (%s) with the previous version: %v", oldNs.Name(), err)305}306
307// now check traffic still works between the proxies308sanitycheck.RunTrafficTestClientServer(t, oldClient, newServer)309}310}
311
312func checkVersion(t framework.TestContext, namespace, version string) error {313// func NewPodFetch(a istioKube.CLIClient, namespace string, selectors ...string) PodFetchFunc {314fetch := kubetest.NewPodFetch(t.Clusters().Default(), namespace)315pods, err := kubetest.CheckPodsAreReady(fetch)316if err != nil {317return fmt.Errorf("failed to retrieve pods: %v", err)318}319for _, p := range pods {320for _, c := range p.Spec.Containers {321if strings.Contains(c.Image, version) {322return fmt.Errorf("expected container image to not include version %q, got %q", version, c.Image)323}324}325}326
327return nil328}
329