blob: fc193a5e9bab96e0eb0a097f399e64b710f1a822 [file] [log] [blame]
//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()
}