blob: a51c9a2a69a799cee047c0bc0a2c902820053dc5 [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 helm
import (
"context"
"fmt"
"path/filepath"
"time"
)
import (
networking "istio.io/api/networking/v1alpha3"
"istio.io/client-go/pkg/apis/networking/v1alpha3"
"istio.io/pkg/log"
v1 "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
import (
"github.com/apache/dubbo-go-pixiu/pkg/test"
"github.com/apache/dubbo-go-pixiu/pkg/test/env"
"github.com/apache/dubbo-go-pixiu/pkg/test/framework"
"github.com/apache/dubbo-go-pixiu/pkg/test/framework/components/cluster"
"github.com/apache/dubbo-go-pixiu/pkg/test/framework/components/cluster/kube"
"github.com/apache/dubbo-go-pixiu/pkg/test/helm"
kubetest "github.com/apache/dubbo-go-pixiu/pkg/test/kube"
"github.com/apache/dubbo-go-pixiu/pkg/test/scopes"
"github.com/apache/dubbo-go-pixiu/pkg/test/util/retry"
)
const (
IstioNamespace = "dubbo-system"
ReleasePrefix = "istio-"
BaseChart = "base"
CRDsFolder = "crds"
DiscoveryChart = "istio-discovery"
IngressGatewayChart = "istio-ingress"
EgressGatewayChart = "istio-egress"
BaseReleaseName = ReleasePrefix + BaseChart
IstiodReleaseName = "istiod"
IngressReleaseName = IngressGatewayChart
EgressReleaseName = EgressGatewayChart
ControlChartsDir = "istio-control"
GatewayChartsDir = "gateways"
RetryDelay = 2 * time.Second
RetryTimeOut = 5 * time.Minute
Timeout = 2 * time.Minute
)
// ManifestsChartPath is path of local Helm charts used for testing.
var ManifestsChartPath = filepath.Join(env.IstioSrc, "manifests/charts")
// TestDataChartPath is path of local Helm charts used for testing.
var TestDataChartPath = filepath.Join(env.IstioSrc, "tests/integration/helm/testdata")
// InstallIstio install Istio using Helm charts with the provided
// override values file and fails the tests on any failures.
func InstallIstio(t test.Failer, cs cluster.Cluster,
h *helm.Helm, suffix, overrideValuesFile, relPath, version string, installGateways bool) {
CreateNamespace(t, cs, IstioNamespace)
// Install base chart
err := h.InstallChart(BaseReleaseName, filepath.Join(relPath, version, BaseChart+suffix),
IstioNamespace, overrideValuesFile, Timeout)
if err != nil {
t.Fatalf("failed to install istio %s chart", BaseChart)
}
// Install discovery chart
err = h.InstallChart(IstiodReleaseName, filepath.Join(relPath, version, ControlChartsDir, DiscoveryChart)+suffix,
IstioNamespace, overrideValuesFile, Timeout)
if err != nil {
t.Fatalf("failed to install istio %s chart", DiscoveryChart)
}
if installGateways {
// Install ingress gateway chart
err = h.InstallChart(IngressReleaseName, filepath.Join(relPath, version, GatewayChartsDir, IngressGatewayChart)+suffix,
IstioNamespace, overrideValuesFile, Timeout)
if err != nil {
t.Fatalf("failed to install istio %s chart", IngressGatewayChart)
}
// Install egress gateway chart
err = h.InstallChart(EgressReleaseName, filepath.Join(relPath, version, GatewayChartsDir, EgressGatewayChart)+suffix,
IstioNamespace, overrideValuesFile, Timeout)
if err != nil {
t.Fatalf("failed to install istio %s chart", EgressGatewayChart)
}
}
}
// InstallIstioWithRevision install Istio using Helm charts with the provided
// override values file and fails the tests on any failures.
func InstallIstioWithRevision(t test.Failer, cs cluster.Cluster,
h *helm.Helm, fileSuffix, version, revision, overrideValuesFile string, upgradeBaseChart, useTestData bool) {
CreateNamespace(t, cs, IstioNamespace)
// base chart may already be installed if the Istio was previously already installed
if upgradeBaseChart {
// upgrade is always done with ../manifests/charts/base
err := h.UpgradeChart(BaseReleaseName, filepath.Join(ManifestsChartPath, BaseChart),
IstioNamespace, overrideValuesFile, Timeout)
if err != nil {
t.Fatalf("failed to upgrade istio %s chart", BaseChart)
}
} else {
err := h.InstallChart(BaseReleaseName, filepath.Join(TestDataChartPath, version, BaseChart+fileSuffix),
IstioNamespace, overrideValuesFile, Timeout)
if err != nil {
t.Fatalf("failed to upgrade istio %s chart", BaseChart)
}
}
// install discovery chart with --set revision=NAME
if useTestData {
err := h.InstallChart(IstiodReleaseName+"-"+revision, filepath.Join(TestDataChartPath, version, ControlChartsDir, DiscoveryChart+fileSuffix),
IstioNamespace, overrideValuesFile, Timeout)
if err != nil {
t.Fatalf("failed to install istio %s chart", DiscoveryChart)
}
} else {
err := h.InstallChart(IstiodReleaseName+"-"+revision, filepath.Join(ManifestsChartPath, ControlChartsDir, DiscoveryChart),
IstioNamespace, overrideValuesFile, Timeout)
if err != nil {
t.Fatalf("failed to install istio %s chart", DiscoveryChart)
}
}
// TODO: ingress and egress charts for use with revisions is considered experimental
// and are not a part of this test for now
}
func CreateNamespace(t test.Failer, cs cluster.Cluster, namespace string) {
if _, err := cs.CoreV1().Namespaces().Create(context.TODO(), &v1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: namespace,
},
}, metav1.CreateOptions{}); err != nil {
if kerrors.IsAlreadyExists(err) {
log.Debugf("%v namespace already exist", IstioNamespace)
} else {
t.Fatalf("failed to create %v namespace: %v", IstioNamespace, err)
}
}
}
// deleteIstio deletes installed Istio Helm charts and resources
func deleteIstio(t framework.TestContext, h *helm.Helm, cs *kube.Cluster) {
scopes.Framework.Infof("cleaning up resources")
if err := h.DeleteChart(EgressReleaseName, IstioNamespace); err != nil {
t.Errorf("failed to delete %s release", EgressReleaseName)
}
if err := h.DeleteChart(IngressReleaseName, IstioNamespace); err != nil {
t.Errorf("failed to delete %s release", IngressReleaseName)
}
if err := h.DeleteChart(IstiodReleaseName, IstioNamespace); err != nil {
t.Errorf("failed to delete %s release", IstiodReleaseName)
}
if err := h.DeleteChart(BaseReleaseName, IstioNamespace); err != nil {
t.Errorf("failed to delete %s release", BaseReleaseName)
}
if err := cs.CoreV1().Namespaces().Delete(context.TODO(), IstioNamespace, metav1.DeleteOptions{}); err != nil {
t.Errorf("failed to delete istio namespace: %v", err)
}
if err := kubetest.WaitForNamespaceDeletion(cs, IstioNamespace, retry.Timeout(RetryTimeOut)); err != nil {
t.Errorf("waiting for istio namespace to be deleted: %v", err)
}
}
// VerifyInstallation verify that the Helm installation is successful
func VerifyInstallation(ctx framework.TestContext, cs cluster.Cluster, verifyGateways bool) {
scopes.Framework.Infof("=== verifying istio installation === ")
retry.UntilSuccessOrFail(ctx, func() error {
if _, err := kubetest.CheckPodsAreReady(kubetest.NewPodFetch(cs, IstioNamespace, "app=istiod")); err != nil {
return fmt.Errorf("istiod pod is not ready: %v", err)
}
if verifyGateways {
if _, err := kubetest.CheckPodsAreReady(kubetest.NewPodFetch(cs, IstioNamespace, "app=istio-ingressgateway")); err != nil {
return fmt.Errorf("istio ingress gateway pod is not ready: %v", err)
}
if _, err := kubetest.CheckPodsAreReady(kubetest.NewPodFetch(cs, IstioNamespace, "app=istio-egressgateway")); err != nil {
return fmt.Errorf("istio egress gateway pod is not ready: %v", err)
}
}
return nil
}, retry.Timeout(RetryTimeOut), retry.Delay(RetryDelay))
scopes.Framework.Infof("=== succeeded ===")
}
func SetRevisionTag(ctx framework.TestContext, h *helm.Helm, fileSuffix, revision, revisionTag, relPath, version string) {
scopes.Framework.Infof("=== setting revision tag === ")
template, err := h.Template(IstiodReleaseName+"-"+revision, filepath.Join(relPath, version, ControlChartsDir, DiscoveryChart)+fileSuffix,
IstioNamespace, "templates/revision-tags.yaml", Timeout, "--set",
fmt.Sprintf("revision=%s", revision), "--set", fmt.Sprintf("revisionTags={%s}", revisionTag))
if err != nil {
ctx.Fatalf("failed to install istio %s chart", DiscoveryChart)
}
err = ctx.ConfigIstio().YAML(IstioNamespace, template).Apply()
if err != nil {
ctx.Fatalf("failed to apply templated revision tags yaml: %v", err)
}
scopes.Framework.Infof("=== succeeded === ")
}
// VerifyMutatingWebhookConfigurations verifies that the proper number of mutating webhooks are running, used with
// revisions and revision tags
func VerifyMutatingWebhookConfigurations(ctx framework.TestContext, cs cluster.Cluster, names []string) {
scopes.Framework.Infof("=== verifying mutating webhook configurations === ")
if ok := kubetest.MutatingWebhookConfigurationsExists(cs, names); !ok {
ctx.Fatalf("Not all mutating webhook configurations were installed. Expected [%v]", names)
}
scopes.Framework.Infof("=== succeeded ===")
}
// ValidatingWebhookConfigurations verifies that the proper number of validating webhooks are running, used with
// revisions and revision tags
func ValidatingWebhookConfigurations(ctx framework.TestContext, cs cluster.Cluster, names []string) {
scopes.Framework.Infof("=== verifying validating webhook configurations === ")
if ok := kubetest.ValidatingWebhookConfigurationsExists(cs, names); !ok {
ctx.Fatalf("Not all validating webhook configurations were installed. Expected [%v]", names)
}
scopes.Framework.Infof("=== succeeded ===")
}
// VerifyValidation verifies that Istio resource validation is active on the cluster.
func VerifyValidation(ctx framework.TestContext) {
ctx.Helper()
invalidGateway := &v1alpha3.Gateway{
ObjectMeta: metav1.ObjectMeta{
Name: "invalid-istio-gateway",
Namespace: IstioNamespace,
},
Spec: networking.Gateway{},
}
createOptions := metav1.CreateOptions{DryRun: []string{metav1.DryRunAll}}
istioClient := ctx.Clusters().Default().Istio().NetworkingV1alpha3()
retry.UntilOrFail(ctx, func() bool {
_, err := istioClient.Gateways(IstioNamespace).Create(context.TODO(), invalidGateway, createOptions)
rejected := err != nil
return rejected
})
}