istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/test/framework/components/echo/common/deployment/namespace.go (about)

     1  // Copyright Istio Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package deployment
    16  
    17  import (
    18  	"fmt"
    19  
    20  	"istio.io/istio/pkg/test/framework/components/echo"
    21  	"istio.io/istio/pkg/test/framework/components/echo/deployment"
    22  	"istio.io/istio/pkg/test/framework/components/echo/match"
    23  	"istio.io/istio/pkg/test/framework/components/namespace"
    24  	"istio.io/istio/pkg/test/framework/resource"
    25  	"istio.io/istio/pkg/test/framework/resource/config"
    26  	"istio.io/istio/pkg/test/framework/resource/config/apply"
    27  )
    28  
    29  const (
    30  	ASvc             = "a"
    31  	BSvc             = "b"
    32  	CSvc             = "c"
    33  	DSvc             = "d"
    34  	ESvc             = "e"
    35  	TproxySvc        = "tproxy"
    36  	VMSvc            = "vm"
    37  	HeadlessSvc      = "headless"
    38  	StatefulSetSvc   = "statefulset"
    39  	ProxylessGRPCSvc = "proxyless-grpc"
    40  	NakedSvc         = "naked"
    41  	SotwSvc          = "sotw"
    42  	WaypointSvc      = "waypoint"
    43  	CapturedSvc      = "captured"
    44  )
    45  
    46  // EchoNamespace contains the echo instances for a single namespace.
    47  type EchoNamespace struct {
    48  	// Namespace where the services are deployed.
    49  	Namespace namespace.Instance
    50  
    51  	// Standard echo app to be used by tests
    52  	A echo.Instances
    53  	// Standard echo app to be used by tests
    54  	B echo.Instances
    55  	// Standard echo app to be used by tests
    56  	C echo.Instances
    57  	// Dual-stack echo app to be used by tests if running in dual-stack mode
    58  	D echo.Instances
    59  	// IPv6 only echo app to be used by tests if running in dual-stack mode
    60  	E echo.Instances
    61  	// Standard echo app with TPROXY interception mode to be used by tests
    62  	Tproxy echo.Instances
    63  	// Headless echo app to be used by tests
    64  	Headless echo.Instances
    65  	// StatefulSet echo app to be used by tests
    66  	StatefulSet echo.Instances
    67  	// ProxylessGRPC echo app to be used by tests
    68  	ProxylessGRPC echo.Instances
    69  	// Echo app to be used by tests, with no sidecar injected
    70  	Naked echo.Instances
    71  	// A virtual machine echo app (only deployed to one cluster)
    72  	VM echo.Instances
    73  	// Sotw echo app uses the sotw XDS protocol. This should be functionally equivalent to A.
    74  	Sotw echo.Instances
    75  	// All echo apps in this namespace
    76  	All echo.Services
    77  }
    78  
    79  func (n EchoNamespace) build(b deployment.Builder, cfg Config) deployment.Builder {
    80  	for _, config := range cfg.Configs.Get() {
    81  		if config.Namespace == nil {
    82  			config.Namespace = n.Namespace
    83  		}
    84  		if config.Namespace.Name() == n.Namespace.Name() {
    85  			b = b.WithConfig(config)
    86  		}
    87  	}
    88  	return b
    89  }
    90  
    91  func (n *EchoNamespace) loadValues(t resource.Context, echos echo.Instances, d *Echos) error {
    92  	ns := n.Namespace
    93  	n.All = match.Namespace(ns).GetMatches(echos).Services()
    94  
    95  	n.A = match.ServiceName(echo.NamespacedName{Name: ASvc, Namespace: ns}).GetMatches(echos)
    96  	n.B = match.ServiceName(echo.NamespacedName{Name: BSvc, Namespace: ns}).GetMatches(echos)
    97  	n.C = match.ServiceName(echo.NamespacedName{Name: CSvc, Namespace: ns}).GetMatches(echos)
    98  	if t.Settings().EnableDualStack {
    99  		n.D = match.ServiceName(echo.NamespacedName{Name: DSvc, Namespace: ns}).GetMatches(echos)
   100  		n.E = match.ServiceName(echo.NamespacedName{Name: ESvc, Namespace: ns}).GetMatches(echos)
   101  	}
   102  	n.Tproxy = match.ServiceName(echo.NamespacedName{Name: TproxySvc, Namespace: ns}).GetMatches(echos)
   103  	n.Headless = match.ServiceName(echo.NamespacedName{Name: HeadlessSvc, Namespace: ns}).GetMatches(echos)
   104  	n.StatefulSet = match.ServiceName(echo.NamespacedName{Name: StatefulSetSvc, Namespace: ns}).GetMatches(echos)
   105  	n.Naked = match.ServiceName(echo.NamespacedName{Name: NakedSvc, Namespace: ns}).GetMatches(echos)
   106  	n.ProxylessGRPC = match.ServiceName(echo.NamespacedName{Name: ProxylessGRPCSvc, Namespace: ns}).GetMatches(echos)
   107  	if !t.Settings().Skip(echo.VM) {
   108  		n.VM = match.ServiceName(echo.NamespacedName{Name: VMSvc, Namespace: ns}).GetMatches(echos)
   109  	}
   110  	if !t.Settings().Skip(echo.Sotw) {
   111  		n.Sotw = match.ServiceName(echo.NamespacedName{Name: SotwSvc, Namespace: ns}).GetMatches(echos)
   112  	}
   113  
   114  	namespaces, err := namespace.GetAll(t)
   115  	if err != nil {
   116  		return fmt.Errorf("failed retrieving list of namespaces: %v", err)
   117  	}
   118  
   119  	// Restrict egress from this namespace to only those endpoints in the same Echos.
   120  	cfg := t.ConfigIstio().New()
   121  	cfg.Eval(ns.Name(), map[string]any{
   122  		"Namespaces": namespaces,
   123  	}, `
   124  apiVersion: networking.istio.io/v1alpha3
   125  kind: Sidecar
   126  metadata:
   127    name: restrict-to-namespace
   128  spec:
   129    egress:
   130    - hosts:
   131      - "istio-system/*"
   132  {{ range $ns := .Namespaces }}
   133      - "{{ $ns.Name }}/*"
   134  {{ end }}
   135  `)
   136  
   137  	if !t.Settings().DisableDefaultExternalServiceConnectivity {
   138  		// Create a ServiceEntry to allow apps in this namespace to talk to the external service.
   139  		if d.External.Namespace != nil {
   140  			DeployExternalServiceEntry(cfg, ns, d.External.Namespace, false)
   141  		}
   142  	}
   143  
   144  	return cfg.Apply(apply.NoCleanup)
   145  }
   146  
   147  func DeployExternalServiceEntry(cfg config.Factory, deployedNamespace, externalNamespace namespace.Instance, manuallyAllocate bool) config.Plan {
   148  	return cfg.Eval(deployedNamespace.Name(), map[string]any{
   149  		"Namespace":        externalNamespace.Name(),
   150  		"Hostname":         ExternalHostname,
   151  		"Ports":            serviceEntryPorts(),
   152  		"ManuallyAllocate": manuallyAllocate,
   153  	}, `apiVersion: networking.istio.io/v1alpha3
   154  kind: ServiceEntry
   155  metadata:
   156    name: external-service
   157  spec:
   158  {{- if .ManuallyAllocate }}
   159    addresses: [240.240.240.239] # Semi-random address for the range Istio allocates in
   160  {{- end }}
   161    exportTo: [.]
   162    hosts:
   163    - {{.Hostname}}
   164    location: MESH_EXTERNAL
   165    resolution: DNS
   166    endpoints:
   167    - address: external.{{.Namespace}}.svc.cluster.local
   168    ports:
   169    - name: http-tls-origination
   170      number: 8888
   171      protocol: http
   172      targetPort: 443
   173    - name: http2-tls-origination
   174      number: 8882
   175      protocol: http2
   176      targetPort: 443
   177  {{- range $i, $p := .Ports }}
   178    - name: {{$p.Name}}
   179      number: {{$p.ServicePort}}
   180      protocol: "{{$p.Protocol}}"
   181  {{- end }}
   182  `)
   183  }