istio.io/istio@v0.0.0-20240520182934-d79c90f27776/tests/integration/helm/install_test.go (about)

     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  
    18  package helm
    19  
    20  import (
    21  	"fmt"
    22  	"os"
    23  	"path/filepath"
    24  	"strings"
    25  	"testing"
    26  
    27  	"k8s.io/apimachinery/pkg/types"
    28  
    29  	"istio.io/istio/pkg/test/framework"
    30  	kubecluster "istio.io/istio/pkg/test/framework/components/cluster/kube"
    31  	"istio.io/istio/pkg/test/framework/components/namespace"
    32  	"istio.io/istio/pkg/test/helm"
    33  	"istio.io/istio/tests/util/sanitycheck"
    34  )
    35  
    36  // TestDefaultInstall tests Istio installation using Helm with default options
    37  func TestDefaultInstall(t *testing.T) {
    38  	overrideValuesStr := `
    39  global:
    40    hub: %s
    41    tag: %s
    42    variant: %q
    43  `
    44  	framework.
    45  		NewTest(t).
    46  		Run(setupInstallation(overrideValuesStr, false, DefaultNamespaceConfig, ""))
    47  }
    48  
    49  // TestAmbientInstall tests Istio ambient profile installation using Helm
    50  func TestAmbientInstall(t *testing.T) {
    51  	framework.
    52  		NewTest(t).
    53  		Run(setupInstallation(ambientProfileOverride, true, DefaultNamespaceConfig, ""))
    54  }
    55  
    56  func TestAmbientInstallMultiNamespace(t *testing.T) {
    57  	tests := []struct {
    58  		name     string
    59  		nsConfig NamespaceConfig
    60  	}{{
    61  		name: "isolated-istio-cni",
    62  		nsConfig: NewNamespaceConfig(types.NamespacedName{
    63  			Name: CniReleaseName, Namespace: "istio-cni",
    64  		}),
    65  	}, {
    66  		name: "isolated-istio-cni-and-ztunnel",
    67  		nsConfig: NewNamespaceConfig(types.NamespacedName{
    68  			Name: CniReleaseName, Namespace: "istio-cni",
    69  		}, types.NamespacedName{
    70  			Name: ZtunnelReleaseName, Namespace: "kube-system",
    71  		}),
    72  	}, {
    73  		name: "isolated-istio-cni-ztunnel-and-gateway",
    74  		nsConfig: NewNamespaceConfig(types.NamespacedName{
    75  			Name: CniReleaseName, Namespace: "istio-cni",
    76  		}, types.NamespacedName{
    77  			Name: ZtunnelReleaseName, Namespace: "ztunnel",
    78  		}, types.NamespacedName{
    79  			Name: IngressReleaseName, Namespace: "ingress-release",
    80  		}),
    81  	}}
    82  	for _, tt := range tests {
    83  		t.Run(tt.name, func(t *testing.T) {
    84  			framework.
    85  				NewTest(t).
    86  				Run(setupInstallation(ambientProfileOverride, true, tt.nsConfig, ""))
    87  		})
    88  	}
    89  }
    90  
    91  // TestReleaseChannels tests that non-stable CRDs and fields get blocked
    92  // by the default ValidatingAdmissionPolicy
    93  func TestReleaseChannels(t *testing.T) {
    94  	overrideValuesStr := `
    95  global:
    96    hub: %s
    97    tag: %s
    98    variant: %q
    99  profile: stable
   100  `
   101  
   102  	framework.
   103  		NewTest(t).
   104  		RequireKubernetesMinorVersion(30).
   105  		Run(setupInstallationWithCustomCheck(overrideValuesStr, false, DefaultNamespaceConfig, func(t framework.TestContext) {
   106  			// Try to apply an EnvoyFilter (it should be rejected)
   107  			expectedErrorPrefix := `%s "sample" is forbidden: ValidatingAdmissionPolicy 'stable-channel-default-policy.istio.io' ` +
   108  				`with binding 'stable-channel-default-policy-binding.istio.io' denied request`
   109  			err := t.ConfigIstio().Eval("default", nil, sampleEnvoyFilter).Apply()
   110  			if err == nil {
   111  				t.Errorf("Did not receive an error while applying sample EnvoyFilter with stable admission policy")
   112  			} else {
   113  				msg := fmt.Sprintf(expectedErrorPrefix, "envoyfilters.networking.istio.io")
   114  				if !strings.Contains(err.Error(), msg) {
   115  					t.Errorf("Expected error %q to contain %q", err.Error(), msg)
   116  				}
   117  			}
   118  
   119  			// Now test field-level blocks with Telemetry
   120  			err = t.ConfigIstio().Eval("default", nil, extendedTelemetry).Apply()
   121  			if err == nil {
   122  				t.Error("Did not receive an error while applying extended Telemetry resource with stable admission policy")
   123  			} else {
   124  				msg := fmt.Sprintf(expectedErrorPrefix, "telemetries.telemetry.istio.io")
   125  				if !strings.Contains(err.Error(), msg) {
   126  					t.Errorf("Expected error %q to contain %q", err.Error(), msg)
   127  				}
   128  			}
   129  		}, ""))
   130  }
   131  
   132  // TestRevisionedReleaseChannels tests that non-stable CRDs and fields get blocked
   133  // by the revisioned ValidatingAdmissionPolicy
   134  func TestRevisionedReleaseChannels(t *testing.T) {
   135  	overrideValuesStr := `
   136  global:
   137    hub: %s
   138    tag: %s
   139    variant: %q
   140  profile: stable
   141  revision: 1-x
   142  defaultRevision: ""
   143  `
   144  	revision := "1-x"
   145  	framework.
   146  		NewTest(t).
   147  		RequireKubernetesMinorVersion(30).
   148  		Run(setupInstallationWithCustomCheck(overrideValuesStr, false, DefaultNamespaceConfig, func(t framework.TestContext) {
   149  			// Try to apply an EnvoyFilter (it should be rejected)
   150  			expectedErrorPrefix := `%s "sample" is forbidden: ValidatingAdmissionPolicy 'stable-channel-policy-1-x-istio-system.istio.io' ` +
   151  				`with binding 'stable-channel-policy-binding-1-x-istio-system.istio.io' denied request`
   152  			err := t.ConfigIstio().Eval("default", nil, fmt.Sprintf(revisionedSampleEnvoyFilter, revision)).Apply()
   153  			if err == nil {
   154  				t.Errorf("Did not receive an error while applying sample EnvoyFilter with stable admission policy")
   155  			} else {
   156  				msg := fmt.Sprintf(expectedErrorPrefix, "envoyfilters.networking.istio.io")
   157  				if !strings.Contains(err.Error(), msg) {
   158  					t.Errorf("Expected error %q to contain %q", err.Error(), msg)
   159  				}
   160  			}
   161  
   162  			// Now test field-level blocks with Telemetry
   163  			err = t.ConfigIstio().Eval("default", nil, fmt.Sprintf(revisionedExtendedTelemetry, revision)).Apply()
   164  			if err == nil {
   165  				t.Error("Did not receive an error while applying extended Telemetry resource with stable admission policy")
   166  			} else {
   167  				msg := fmt.Sprintf(expectedErrorPrefix, "telemetries.telemetry.istio.io")
   168  				if !strings.Contains(err.Error(), msg) {
   169  					t.Errorf("Expected error %q to contain %q", err.Error(), msg)
   170  				}
   171  			}
   172  		}, revision))
   173  }
   174  
   175  func setupInstallation(overrideValuesStr string, isAmbient bool, config NamespaceConfig, revision string) func(t framework.TestContext) {
   176  	return baseSetup(overrideValuesStr, isAmbient, config, func(t framework.TestContext) {
   177  		sanitycheck.RunTrafficTest(t, t)
   178  	}, revision)
   179  }
   180  
   181  func setupInstallationWithCustomCheck(overrideValuesStr string, isAmbient bool, config NamespaceConfig,
   182  	check func(t framework.TestContext), revision string,
   183  ) func(t framework.TestContext) {
   184  	return baseSetup(overrideValuesStr, isAmbient, config, check, revision)
   185  }
   186  
   187  func baseSetup(overrideValuesStr string, isAmbient bool, config NamespaceConfig,
   188  	check func(t framework.TestContext), revision string,
   189  ) func(t framework.TestContext) {
   190  	return func(t framework.TestContext) {
   191  		workDir, err := t.CreateTmpDirectory("helm-install-test")
   192  		if err != nil {
   193  			t.Fatal("failed to create test directory")
   194  		}
   195  		cs := t.Clusters().Default().(*kubecluster.Cluster)
   196  		h := helm.New(cs.Filename())
   197  		s := t.Settings()
   198  
   199  		// Some templates contain a tag definition, in which we just replace %s it with the tag value,
   200  		// others just contain a %s placeholder for the whole tag: line
   201  		tag := s.Image.Tag
   202  		if !strings.Contains(overrideValuesStr, "tag: ") {
   203  			tag = "tag: " + tag
   204  		}
   205  		overrideValues := fmt.Sprintf(overrideValuesStr, s.Image.Hub, tag, s.Image.Variant)
   206  		overrideValues = adjustValuesForOpenShift(t, overrideValues)
   207  
   208  		overrideValuesFile := filepath.Join(workDir, "values.yaml")
   209  		if err := os.WriteFile(overrideValuesFile, []byte(overrideValues), os.ModePerm); err != nil {
   210  			t.Fatalf("failed to write iop cr file: %v", err)
   211  		}
   212  		t.Cleanup(func() {
   213  			if !t.Failed() {
   214  				return
   215  			}
   216  			if t.Settings().CIMode {
   217  				for _, ns := range config.AllNamespaces() {
   218  					namespace.Dump(t, ns)
   219  				}
   220  			}
   221  		})
   222  
   223  		InstallIstio(t, cs, h, overrideValuesFile, "", true, isAmbient, config)
   224  
   225  		VerifyInstallation(t, cs, config, true, isAmbient, revision)
   226  		verifyValidation(t, revision)
   227  
   228  		check(t)
   229  		t.Cleanup(func() {
   230  			DeleteIstio(t, h, cs, config, isAmbient)
   231  		})
   232  	}
   233  }