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  }