istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/test/framework/components/jwt/kube.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 jwt 16 17 import ( 18 "fmt" 19 "os" 20 "path/filepath" 21 "time" 22 23 "github.com/hashicorp/go-multierror" 24 25 "istio.io/istio/pkg/test/env" 26 "istio.io/istio/pkg/test/framework/components/namespace" 27 "istio.io/istio/pkg/test/framework/resource" 28 "istio.io/istio/pkg/test/framework/resource/config/apply" 29 "istio.io/istio/pkg/test/kube" 30 "istio.io/istio/pkg/test/scopes" 31 "istio.io/istio/pkg/test/util/yml" 32 ) 33 34 const ( 35 serviceName = "jwt-server" 36 httpPort = 8000 37 httpsPort = 8443 38 ) 39 40 var ( 41 _ resource.Resource = &serverImpl{} 42 _ Server = &serverImpl{} 43 ) 44 45 func newKubeServer(ctx resource.Context, ns namespace.Instance) (server *serverImpl, err error) { 46 start := time.Now() 47 scopes.Framework.Info("=== BEGIN: Deploy JWT server ===") 48 defer func() { 49 if err != nil { 50 scopes.Framework.Error("=== FAILED: Deploy JWT server ===") 51 scopes.Framework.Error(err) 52 } else { 53 scopes.Framework.Infof("=== SUCCEEDED: Deploy JWT server in %v ===", time.Since(start)) 54 } 55 }() 56 57 // Create the namespace, if unspecified. 58 if ns == nil { 59 ns, err = namespace.New(ctx, namespace.Config{ 60 Prefix: "jwt", 61 Inject: true, 62 }) 63 if err != nil { 64 return 65 } 66 } 67 68 server = &serverImpl{ 69 ns: ns, 70 } 71 server.id = ctx.TrackResource(server) 72 73 // Deploy the server. 74 if err = server.deploy(ctx); err != nil { 75 return 76 } 77 78 return 79 } 80 81 func readDeploymentYAML() (string, error) { 82 // Read the samples file. 83 filePath := filepath.Join(env.IstioSrc, "samples/jwt-server", "jwt-server.yaml") 84 data, err := os.ReadFile(filePath) 85 if err != nil { 86 return "", err 87 } 88 yamlText := string(data) 89 90 return yamlText, nil 91 } 92 93 func (s *serverImpl) deploy(ctx resource.Context) error { 94 yamlText, err := readDeploymentYAML() 95 if err != nil { 96 return err 97 } 98 99 image := ctx.Settings().Image 100 if image.PullSecret != "" { 101 var imageSpec resource.ImageSettings 102 imageSpec.PullSecret = image.PullSecret 103 secretName, err := imageSpec.PullSecretName() 104 if err != nil { 105 return err 106 } 107 yamlText, err = addPullSecret(yamlText, secretName) 108 if err != nil { 109 return err 110 } 111 } 112 113 if err := ctx.ConfigKube(ctx.AllClusters()...). 114 YAML(s.ns.Name(), yamlText). 115 Apply(apply.CleanupConditionally); err != nil { 116 return err 117 } 118 119 // Wait for the endpoints to be ready. 120 var g multierror.Group 121 for _, c := range ctx.AllClusters() { 122 c := c 123 g.Go(func() error { 124 fetchFn := kube.NewPodFetch(c, s.ns.Name(), "app=jwt-server") 125 _, err := kube.WaitUntilPodsAreReady(fetchFn) 126 if err != nil { 127 return fmt.Errorf("jwt-server pod not ready in cluster %s: %v", c.Name(), err) 128 } 129 130 _, _, err = kube.WaitUntilServiceEndpointsAreReady(c.Kube(), s.ns.Name(), "jwt-server") 131 return err 132 }) 133 } 134 135 return g.Wait().ErrorOrNil() 136 } 137 138 func addPullSecret(resource string, pullSecret string) (string, error) { 139 res := yml.SplitString(resource) 140 updatedYaml, err := yml.ApplyPullSecret(res[2], pullSecret) 141 if err != nil { 142 return "", err 143 } 144 mergedYaml := yml.JoinString(res[0], res[1], updatedYaml) 145 return mergedYaml, nil 146 } 147 148 type serverImpl struct { 149 id resource.ID 150 ns namespace.Instance 151 } 152 153 func (s *serverImpl) FQDN() string { 154 return fmt.Sprintf("%s.%s.svc.cluster.local", serviceName, s.ns.Name()) 155 } 156 157 func (s *serverImpl) HTTPPort() int { 158 return httpPort 159 } 160 161 func (s *serverImpl) HTTPSPort() int { 162 return httpsPort 163 } 164 165 func (s *serverImpl) JwksURI() string { 166 uri := fmt.Sprintf("http://%s:%d/jwks", s.FQDN(), s.HTTPPort()) 167 return uri 168 } 169 170 func (s *serverImpl) ID() resource.ID { 171 return s.id 172 } 173 174 func (s *serverImpl) Namespace() namespace.Instance { 175 return s.ns 176 }