| //go:build integ |
| // +build integ |
| |
| // Copyright Istio Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package pilot |
| |
| import ( |
| "fmt" |
| "strings" |
| "testing" |
| "time" |
| ) |
| |
| import ( |
| "github.com/hashicorp/go-multierror" |
| "istio.io/pkg/log" |
| ) |
| |
| import ( |
| "github.com/apache/dubbo-go-pixiu/pkg/config/protocol" |
| "github.com/apache/dubbo-go-pixiu/pkg/test/framework" |
| "github.com/apache/dubbo-go-pixiu/pkg/test/framework/components/echo" |
| "github.com/apache/dubbo-go-pixiu/pkg/test/framework/components/echo/deployment" |
| "github.com/apache/dubbo-go-pixiu/pkg/test/framework/components/echo/util/traffic" |
| "github.com/apache/dubbo-go-pixiu/pkg/test/framework/components/namespace" |
| "github.com/apache/dubbo-go-pixiu/pkg/test/framework/label" |
| kubetest "github.com/apache/dubbo-go-pixiu/pkg/test/kube" |
| ) |
| |
| const ( |
| callInterval = 200 * time.Millisecond |
| successThreshold = 0.95 |
| ) |
| |
| // TestRevisionedUpgrade tests a revision-based upgrade from the specified versions to current master |
| func TestRevisionedUpgrade(t *testing.T) { |
| framework.NewTest(t). |
| RequiresSingleCluster(). |
| RequiresLocalControlPlane(). |
| // Requires installation of CPs from manifests, won't succeed |
| // if existing CPs have different root cert |
| Label(label.CustomSetup). |
| Features("installation.upgrade"). |
| Run(func(t framework.TestContext) { |
| // Kubernetes 1.22 drops support for a number of legacy resources, so we cannot install the old versions |
| if !t.Clusters().Default().MaxKubeVersion(21) { |
| t.Skipf("k8s version not supported for %s (>%s)", t.Name(), "1.21") |
| } |
| versions := []string{NMinusOne, NMinusTwo, NMinusThree, NMinusFour} |
| for _, v := range versions { |
| t.NewSubTest(fmt.Sprintf("%s->master", v)).Run(func(t framework.TestContext) { |
| testUpgradeFromVersion(t, v) |
| }) |
| } |
| }) |
| } |
| |
| // testUpgradeFromVersion tests an upgrade from the target version to the master version |
| // provided fromVersion must be present in tests/integration/pilot/testdata/upgrade for the installation to succeed |
| // TODO(monkeyanator) pass this a generic UpgradeFunc allowing for reuse across in-place and revisioned upgrades |
| func testUpgradeFromVersion(t framework.TestContext, fromVersion string) { |
| configs := make(map[string]string) |
| t.ConditionalCleanup(func() { |
| for _, config := range configs { |
| _ = t.ConfigIstio().YAML("dubbo-system", config).Delete() |
| } |
| }) |
| |
| // install control plane on the specified version and create namespace pointed to that control plane |
| installRevisionOrFail(t, fromVersion, configs) |
| revision := strings.ReplaceAll(fromVersion, ".", "-") |
| revisionedNamespace := namespace.NewOrFail(t, t, namespace.Config{ |
| Prefix: revision, |
| Inject: true, |
| Revision: revision, |
| }) |
| |
| var revisionedInstance echo.Instance |
| builder := deployment.New(t) |
| builder.With(&revisionedInstance, echo.Config{ |
| Service: fmt.Sprintf("svc-%s", revision), |
| Namespace: revisionedNamespace, |
| Ports: []echo.Port{ |
| { |
| Name: "http", |
| Protocol: protocol.HTTP, |
| WorkloadPort: 8080, |
| }, |
| }, |
| }) |
| builder.BuildOrFail(t) |
| |
| // Create a traffic generator between A and B. |
| g := traffic.NewGenerator(t, traffic.Config{ |
| Source: apps.A[0], |
| Options: echo.CallOptions{ |
| To: apps.B, |
| Port: echo.Port{ |
| Name: "http", |
| }, |
| }, |
| Interval: callInterval, |
| }).Start() |
| |
| if err := enableDefaultInjection(revisionedNamespace); err != nil { |
| t.Fatalf("could not relabel namespace to enable default injection: %v", err) |
| } |
| |
| log.Infof("rolling out echo workloads for service %q", revisionedInstance.Config().Service) |
| if err := revisionedInstance.Restart(); err != nil { |
| t.Fatalf("revisioned instance rollout failed with: %v", err) |
| } |
| fetch := kubetest.NewPodMustFetch(t.Clusters().Default(), revisionedInstance.Config().Namespace.Name(), fmt.Sprintf("app=%s", revisionedInstance.Config().Service)) // nolint: lll |
| pods, err := kubetest.CheckPodsAreReady(fetch) |
| if err != nil { |
| t.Fatalf("failed to retrieve upgraded pods: %v", err) |
| } |
| for _, p := range pods { |
| for _, c := range p.Spec.Containers { |
| if strings.Contains(c.Image, fromVersion) { |
| t.Fatalf("expected post-upgrade container image not to include %q, got %q", fromVersion, c.Image) |
| } |
| } |
| } |
| |
| // Stop the traffic generator and get the result. |
| g.Stop().CheckSuccessRate(t, successThreshold) |
| } |
| |
| // enableDefaultInjection takes a namespaces and relabels it such that it will have a default sidecar injected |
| func enableDefaultInjection(ns namespace.Instance) error { |
| var errs *multierror.Error |
| errs = multierror.Append(errs, ns.SetLabel("istio-injection", "enabled")) |
| errs = multierror.Append(errs, ns.RemoveLabel("istio.io/rev")) |
| return errs.ErrorOrNil() |
| } |