github.com/kubeshop/testkube@v1.17.23/internal/app/api/v1/handlers.go (about)

     1  package v1
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"strings"
     7  
     8  	"github.com/gofiber/fiber/v2"
     9  
    10  	"github.com/kubeshop/testkube/pkg/api/v1/testkube"
    11  	"github.com/kubeshop/testkube/pkg/k8sclient"
    12  	"github.com/kubeshop/testkube/pkg/oauth"
    13  	"github.com/kubeshop/testkube/pkg/version"
    14  )
    15  
    16  const (
    17  	// cliIngressHeader is cli ingress header
    18  	cliIngressHeader = "X-CLI-Ingress"
    19  	// mediaTypeJSON is json media type
    20  	mediaTypeJSON = "application/json"
    21  	// mediaTypeYAML is yaml media type
    22  	mediaTypeYAML = "text/yaml"
    23  
    24  	// contextCloud is cloud context
    25  	contextCloud = "cloud"
    26  	// contextOSS is oss context
    27  	contextOSS = "oss"
    28  )
    29  
    30  // AuthHandler is auth middleware
    31  func (s *TestkubeAPI) AuthHandler() fiber.Handler {
    32  	return func(c *fiber.Ctx) error {
    33  		if c.Get(cliIngressHeader, "") != "" {
    34  			token := strings.TrimSpace(strings.TrimPrefix(c.Get("Authorization", ""), oauth.AuthorizationPrefix))
    35  			var scopes []string
    36  			if s.oauthParams.Scopes != "" {
    37  				scopes = strings.Split(s.oauthParams.Scopes, ",")
    38  			}
    39  
    40  			provider := oauth.NewProvider(s.oauthParams.ClientID, s.oauthParams.ClientSecret, scopes)
    41  			if err := provider.ValidateAccessToken(s.oauthParams.Provider, token); err != nil {
    42  				s.Log.Errorw("error validating token", "error", err)
    43  				return s.Error(c, http.StatusUnauthorized, err)
    44  			}
    45  		}
    46  
    47  		return c.Next()
    48  	}
    49  }
    50  
    51  // InfoHandler is a handler to get info
    52  func (s *TestkubeAPI) InfoHandler() fiber.Handler {
    53  	apiContext := contextOSS
    54  	if s.proContext != nil && s.proContext.APIKey != "" {
    55  		apiContext = contextCloud
    56  	}
    57  	var envID, orgID string
    58  	if s.proContext != nil {
    59  		envID = s.proContext.EnvID
    60  		orgID = s.proContext.OrgID
    61  	}
    62  
    63  	var executionNamespaces []string
    64  	for namespace := range s.serviceAccountNames {
    65  		if namespace == s.Namespace {
    66  			continue
    67  		}
    68  
    69  		executionNamespaces = append(executionNamespaces, namespace)
    70  	}
    71  
    72  	return func(c *fiber.Ctx) error {
    73  		return c.JSON(testkube.ServerInfo{
    74  			Commit:                version.Commit,
    75  			Version:               version.Version,
    76  			Namespace:             s.Namespace,
    77  			Context:               apiContext,
    78  			ClusterId:             s.Config.ClusterID,
    79  			EnvId:                 envID,
    80  			OrgId:                 orgID,
    81  			HelmchartVersion:      s.helmchartVersion,
    82  			DashboardUri:          s.dashboardURI,
    83  			EnableSecretEndpoint:  s.enableSecretsEndpoint,
    84  			DisableSecretCreation: s.disableSecretCreation,
    85  			Features: &testkube.Features{
    86  				LogsV2: s.featureFlags.LogsV2,
    87  			},
    88  			ExecutionNamespaces: executionNamespaces,
    89  		})
    90  	}
    91  }
    92  
    93  // RoutesHandler is a handler to get existing routes
    94  func (s *TestkubeAPI) RoutesHandler() fiber.Handler {
    95  	return func(c *fiber.Ctx) error {
    96  		var routes []fiber.Route
    97  
    98  		stack := s.Mux.Stack()
    99  		for _, e := range stack {
   100  			for _, s := range e {
   101  				route := *s
   102  				routes = append(routes, route)
   103  			}
   104  		}
   105  
   106  		return c.JSON(routes)
   107  	}
   108  }
   109  
   110  // DebugHandler is a handler to get debug information
   111  func (s *TestkubeAPI) DebugHandler() fiber.Handler {
   112  	return func(c *fiber.Ctx) error {
   113  		errPrefix := "failed to get debug information"
   114  		clientSet, err := k8sclient.ConnectToK8s()
   115  		if err != nil {
   116  			return s.Error(c, http.StatusBadGateway, fmt.Errorf("%s: could not connect to cluster: %w", errPrefix, err))
   117  		}
   118  
   119  		clusterVersion, err := k8sclient.GetClusterVersion(clientSet)
   120  		if err != nil {
   121  			return s.Error(c, http.StatusBadGateway, fmt.Errorf("%s: could not get cluster version: %w", errPrefix, err))
   122  		}
   123  
   124  		apiLogs, err := k8sclient.GetAPIServerLogs(c.UserContext(), clientSet, s.Namespace)
   125  		if err != nil {
   126  			return s.Error(c, http.StatusBadGateway, fmt.Errorf("%s: could not get api server logs: %w", errPrefix, err))
   127  		}
   128  
   129  		operatorLogs, err := k8sclient.GetOperatorLogs(c.UserContext(), clientSet, s.Namespace)
   130  		if err != nil {
   131  			return s.Error(c, http.StatusBadGateway, fmt.Errorf("%s: could not get operator logs: %w", errPrefix, err))
   132  		}
   133  
   134  		executionLogs, err := s.GetLatestExecutionLogs(c.UserContext())
   135  		if err != nil {
   136  			return s.Error(c, http.StatusInternalServerError, fmt.Errorf("%s: could not get execution logs: %w", errPrefix, err))
   137  		}
   138  
   139  		return c.JSON(testkube.DebugInfo{
   140  			ClusterVersion: clusterVersion,
   141  			ApiLogs:        apiLogs,
   142  			OperatorLogs:   operatorLogs,
   143  			ExecutionLogs:  executionLogs,
   144  		})
   145  	}
   146  }