istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/test/framework/components/cluster/staticvm/staticvm.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 staticvm 16 17 import ( 18 "errors" 19 "fmt" 20 "net" 21 "strings" 22 23 "k8s.io/apimachinery/pkg/version" 24 25 "istio.io/istio/pkg/kube" 26 "istio.io/istio/pkg/test/framework/components/cluster" 27 "istio.io/istio/pkg/test/framework/components/echo" 28 "istio.io/istio/pkg/test/framework/components/namespace" 29 "istio.io/istio/pkg/test/framework/config" 30 "istio.io/istio/pkg/test/scopes" 31 ) 32 33 func init() { 34 cluster.RegisterFactory(cluster.StaticVM, build) 35 } 36 37 var _ echo.Cluster = &vmcluster{} 38 39 type vmcluster struct { 40 kube.CLIClient 41 cluster.Topology 42 43 vms []echo.Config 44 } 45 46 func build(cfg cluster.Config, topology cluster.Topology) (cluster.Cluster, error) { 47 vms, err := readInstances(cfg) 48 if err != nil { 49 return nil, err 50 } 51 return &vmcluster{ 52 Topology: topology, 53 vms: vms, 54 }, nil 55 } 56 57 func readInstances(cfg cluster.Config) ([]echo.Config, error) { 58 var out []echo.Config 59 deployments := cfg.Meta.Slice("deployments") 60 for i, deploymentMeta := range deployments { 61 vm, err := instanceFromMeta(deploymentMeta) 62 if err != nil { 63 scopes.Framework.Errorf("failed reading deployment config %d of %s: %v", i, cfg.Name, err) 64 } 65 out = append(out, vm) 66 } 67 if len(out) == 0 || len(out) != len(deployments) { 68 return nil, fmt.Errorf("static vm cluster %s has no deployments provided", cfg.Name) 69 } 70 return out, nil 71 } 72 73 func instanceFromMeta(cfg config.Map) (echo.Config, error) { 74 svc := cfg.String("service") 75 if svc == "" { 76 return echo.Config{}, errors.New("service must not be empty") 77 } 78 ns := cfg.String("namespace") 79 if ns == "" { 80 return echo.Config{}, errors.New("namespace must not be empty") 81 } 82 83 var ips []string 84 for _, meta := range cfg.Slice("instances") { 85 publicIPStr := meta.String("ip") 86 privateIPStr := meta.String("instanceIP") 87 ip := net.ParseIP(publicIPStr) 88 if len(ip) == 0 { 89 return echo.Config{}, fmt.Errorf("failed parsing %q as IP address", publicIPStr) 90 } 91 ip = net.ParseIP(privateIPStr) 92 if len(ip) == 0 { 93 return echo.Config{}, fmt.Errorf("failed parsing %q as IP address", privateIPStr) 94 } 95 ips = append(ips, publicIPStr+":"+privateIPStr) 96 } 97 if len(ips) == 0 { 98 return echo.Config{}, fmt.Errorf("%s has no IPs", svc) 99 } 100 101 return echo.Config{ 102 Namespace: namespace.Static(ns), 103 Service: svc, 104 // Will set the version of each subset if not provided 105 Version: cfg.String("version"), 106 StaticAddresses: ips, 107 // TODO support listing subsets 108 Subsets: nil, 109 // TODO support TLS for gRPC client 110 TLSSettings: nil, 111 }, nil 112 } 113 114 func (v vmcluster) CanDeploy(config echo.Config) (echo.Config, bool) { 115 if !config.DeployAsVM { 116 return echo.Config{}, false 117 } 118 for _, vm := range v.vms { 119 if matchConfig(vm, config) { 120 vmCfg := config.DeepCopy() 121 vmCfg.StaticAddresses = vm.StaticAddresses 122 return vmCfg, true 123 } 124 } 125 return echo.Config{}, false 126 } 127 128 func (v vmcluster) GetKubernetesVersion() (*version.Info, error) { 129 return nil, nil 130 } 131 132 func matchConfig(vm, cfg echo.Config) bool { 133 return vm.Service == cfg.Service && strings.HasPrefix(cfg.Namespace.Name(), vm.Namespace.Name()) 134 }