istio.io/istio@v0.0.0-20240520182934-d79c90f27776/tests/integration/ambient/gateway_conformance_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 ambient
    19  
    20  import (
    21  	"io/fs"
    22  	"os"
    23  	"path/filepath"
    24  	"testing"
    25  
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  	k8ssets "k8s.io/apimachinery/pkg/util/sets" //nolint: depguard
    28  	"sigs.k8s.io/controller-runtime/pkg/client"
    29  	v1 "sigs.k8s.io/gateway-api/apis/v1"
    30  	"sigs.k8s.io/gateway-api/conformance"
    31  	confv1 "sigs.k8s.io/gateway-api/conformance/apis/v1"
    32  	"sigs.k8s.io/gateway-api/conformance/tests"
    33  	"sigs.k8s.io/gateway-api/conformance/utils/suite"
    34  	gwfeatures "sigs.k8s.io/gateway-api/pkg/features"
    35  	"sigs.k8s.io/yaml"
    36  
    37  	"istio.io/istio/pilot/pkg/config/kube/gateway"
    38  	"istio.io/istio/pkg/config/constants"
    39  	"istio.io/istio/pkg/kube"
    40  	"istio.io/istio/pkg/maps"
    41  	"istio.io/istio/pkg/test/env"
    42  	"istio.io/istio/pkg/test/framework"
    43  	ambientComponent "istio.io/istio/pkg/test/framework/components/ambient"
    44  	"istio.io/istio/pkg/test/framework/components/namespace"
    45  	"istio.io/istio/pkg/test/prow"
    46  	"istio.io/istio/pkg/test/scopes"
    47  	"istio.io/istio/pkg/test/util/assert"
    48  )
    49  
    50  // GatewayConformanceInputs defines inputs to the gateway conformance test.
    51  // The upstream build requires using `testing.T` types, which we cannot pass using our framework.
    52  // To workaround this, we set up the inputs it TestMain.
    53  type GatewayConformanceInputs struct {
    54  	Client  kube.CLIClient
    55  	Cleanup bool
    56  }
    57  
    58  var gatewayConformanceInputs GatewayConformanceInputs
    59  
    60  // defined in sigs.k8s.io/gateway-api/conformance/base/manifests.yaml
    61  var conformanceNamespaces = []string{
    62  	"gateway-conformance-infra",
    63  	"gateway-conformance-app-backend",
    64  	"gateway-conformance-web-backend",
    65  	"gateway-conformance-mesh",
    66  }
    67  
    68  var skippedTests = map[string]string{}
    69  
    70  func TestGatewayConformance(t *testing.T) {
    71  	framework.
    72  		NewTest(t).
    73  		Run(func(ctx framework.TestContext) {
    74  			// Precreate the GatewayConformance namespaces, and apply the Image Pull Secret to them.
    75  			if ctx.Settings().Image.PullSecret != "" {
    76  				for _, ns := range conformanceNamespaces {
    77  					namespace.Claim(ctx, namespace.Config{
    78  						Prefix: ns,
    79  						Inject: false,
    80  					})
    81  				}
    82  			}
    83  
    84  			mapper, _ := gatewayConformanceInputs.Client.UtilFactory().ToRESTMapper()
    85  			c, err := client.New(gatewayConformanceInputs.Client.RESTConfig(), client.Options{
    86  				Scheme: kube.IstioScheme,
    87  				Mapper: mapper,
    88  			})
    89  			if err != nil {
    90  				t.Fatal(err)
    91  			}
    92  
    93  			hostnameType := v1.AddressType("Hostname")
    94  			istioVersion, _ := env.ReadVersion()
    95  			supported := gateway.SupportedFeatures.Clone().Delete(gwfeatures.SupportMeshConsumerRoute)
    96  			opts := suite.ConformanceOptions{
    97  				Client:                   c,
    98  				Clientset:                gatewayConformanceInputs.Client.Kube(),
    99  				RestConfig:               gatewayConformanceInputs.Client.RESTConfig(),
   100  				GatewayClassName:         "istio",
   101  				Debug:                    scopes.Framework.DebugEnabled(),
   102  				CleanupBaseResources:     gatewayConformanceInputs.Cleanup,
   103  				ManifestFS:               []fs.FS{&conformance.Manifests},
   104  				SupportedFeatures:        supported,
   105  				SkipTests:                maps.Keys(skippedTests),
   106  				UsableNetworkAddresses:   []v1.GatewayAddress{{Value: "infra-backend-v1.gateway-conformance-infra.svc.cluster.local", Type: &hostnameType}},
   107  				UnusableNetworkAddresses: []v1.GatewayAddress{{Value: "foo", Type: &hostnameType}},
   108  				ConformanceProfiles: k8ssets.New(
   109  					suite.GatewayHTTPConformanceProfileName,
   110  					suite.GatewayTLSConformanceProfileName,
   111  					suite.GatewayGRPCConformanceProfileName,
   112  					suite.MeshHTTPConformanceProfileName,
   113  				),
   114  				Implementation: confv1.Implementation{
   115  					Organization: "istio",
   116  					Project:      "istio",
   117  					URL:          "https://istio.io/",
   118  					Version:      istioVersion,
   119  					Contact:      []string{"@istio/maintainers"},
   120  				},
   121  				NamespaceLabels: map[string]string{
   122  					constants.DataplaneModeLabel: "ambient",
   123  				},
   124  				TimeoutConfig: ctx.Settings().GatewayConformanceTimeoutConfig,
   125  			}
   126  
   127  			ctx.Cleanup(func() {
   128  				if !ctx.Failed() {
   129  					return
   130  				}
   131  				if ctx.Settings().CIMode {
   132  					for _, ns := range conformanceNamespaces {
   133  						namespace.Dump(ctx, ns)
   134  					}
   135  				}
   136  			})
   137  			csuite, err := suite.NewConformanceTestSuite(opts)
   138  			assert.NoError(t, err)
   139  			csuite.Setup(t, tests.ConformanceTests)
   140  
   141  			// remove the dataplane mode label from the gateway-conformance-infra namespace
   142  			// so that the ingress gateway doesn't get captured
   143  			ns, err := namespace.Claim(ctx, namespace.Config{
   144  				Prefix: "gateway-conformance-infra",
   145  				Inject: false,
   146  			})
   147  			if err != nil {
   148  				t.Fatal(err)
   149  			}
   150  			ns.RemoveLabel(constants.DataplaneModeLabel)
   151  
   152  			// create a waypoint for mesh conformance
   153  			meshNS := namespace.Static("gateway-conformance-mesh")
   154  			ambientComponent.NewWaypointProxyOrFail(ctx, meshNS, "namespace")
   155  			for _, k := range ctx.AllClusters() {
   156  				ns, err := k.Kube().CoreV1().Namespaces().Get(ctx.Context(), meshNS.Name(), metav1.GetOptions{})
   157  				if err != nil {
   158  					t.Fatal(err)
   159  				}
   160  				labels := ns.Labels
   161  				if labels == nil {
   162  					labels = make(map[string]string)
   163  				}
   164  				labels[constants.AmbientUseWaypointLabel] = "namespace"
   165  				ns.Labels = labels
   166  				k.Kube().CoreV1().Namespaces().Update(ctx.Context(), ns, metav1.UpdateOptions{})
   167  			}
   168  
   169  			assert.NoError(t, csuite.Run(t, tests.ConformanceTests))
   170  			report, err := csuite.Report()
   171  			assert.NoError(t, err)
   172  			reportb, err := yaml.Marshal(report)
   173  			assert.NoError(t, err)
   174  			fp := filepath.Join(ctx.Settings().BaseDir, "conformance.yaml")
   175  			t.Logf("writing conformance test to %v (%v)", fp, prow.ArtifactsURL(fp))
   176  			assert.NoError(t, os.WriteFile(fp, reportb, 0o644))
   177  		})
   178  }