Make workspace routes more user-friendly (#1672)
* Make workspace routes more user-friendly Signed-off-by: David Kwon <dakwon@redhat.com> * Add update verb for ingress in che-operator CR Signed-off-by: David Kwon <dakwon@redhat.com> * Legacy support Signed-off-by: David Kwon <dakwon@redhat.com> * Remove componentName field from from legacy strategy Signed-off-by: David Kwon <dakwon@redhat.com> * Determine path strategy in different function Signed-off-by: David Kwon <dakwon@redhat.com> * Enforce lowercase for username and dw name Signed-off-by: David Kwon <dakwon@redhat.com> * Run make update-dev-resources' Signed-off-by: David Kwon <dakwon@redhat.com> * Update dev resources Signed-off-by: Anatolii Bazko <abazko@redhat.com> --------- Signed-off-by: David Kwon <dakwon@redhat.com> Signed-off-by: Anatolii Bazko <abazko@redhat.com> Co-authored-by: Anatolii Bazko <abazko@redhat.com>pull/1696/head
parent
a716cafd07
commit
34a10852d4
|
|
@ -77,7 +77,7 @@ metadata:
|
|||
operators.operatorframework.io/project_layout: go.kubebuilder.io/v3
|
||||
repository: https://github.com/eclipse-che/che-operator
|
||||
support: Eclipse Foundation
|
||||
name: eclipse-che.v7.68.0-797.next
|
||||
name: eclipse-che.v7.68.0-798.next
|
||||
namespace: placeholder
|
||||
spec:
|
||||
apiservicedefinitions: {}
|
||||
|
|
@ -1231,7 +1231,7 @@ spec:
|
|||
minKubeVersion: 1.19.0
|
||||
provider:
|
||||
name: Eclipse Foundation
|
||||
version: 7.68.0-797.next
|
||||
version: 7.68.0-798.next
|
||||
webhookdefinitions:
|
||||
- admissionReviewVersions:
|
||||
- v1
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"path"
|
||||
"strconv"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
dw "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
|
||||
|
|
@ -232,6 +232,8 @@ func (c *CheRoutingSolver) cheExposedEndpoints(cheCluster *chev2.CheCluster, wor
|
|||
|
||||
gatewayHost := cheCluster.GetCheHost()
|
||||
|
||||
endpointStrategy := getEndpointPathStrategy(c.client, workspaceID, routingObj.Services[0].Namespace, routingObj.Services[0].ObjectMeta.OwnerReferences[0].Name)
|
||||
|
||||
for component, endpoints := range componentEndpoints {
|
||||
for _, endpoint := range endpoints {
|
||||
if dw.EndpointExposure(endpoint.Exposure) == dw.NoneEndpointExposure {
|
||||
|
|
@ -279,7 +281,7 @@ func (c *CheRoutingSolver) cheExposedEndpoints(cheCluster *chev2.CheCluster, wor
|
|||
return map[string]dwo.ExposedEndpointList{}, false, nil
|
||||
}
|
||||
|
||||
publicURLPrefix := getPublicURLPrefixForEndpoint(workspaceID, component, endpoint)
|
||||
publicURLPrefix := getPublicURLPrefixForEndpoint(component, endpoint, endpointStrategy)
|
||||
endpointURL = path.Join(gatewayHost, publicURLPrefix, endpoint.Path)
|
||||
}
|
||||
|
||||
|
|
@ -329,19 +331,20 @@ func (c *CheRoutingSolver) getGatewayConfigsAndFillRoutingObjects(cheCluster *ch
|
|||
}
|
||||
|
||||
configs := make([]corev1.ConfigMap, 0)
|
||||
endpointStrategy := getEndpointPathStrategy(c.client, workspaceID, routing.Namespace, routing.Name)
|
||||
|
||||
// first do routing from main che-gateway into workspace service
|
||||
if mainWsRouteConfig, err := provisionMainWorkspaceRoute(cheCluster, routing, cmLabels); err != nil {
|
||||
if mainWsRouteConfig, err := provisionMainWorkspaceRoute(cheCluster, routing, cmLabels, endpointStrategy); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
configs = append(configs, *mainWsRouteConfig)
|
||||
}
|
||||
|
||||
// then expose the endpoints
|
||||
if infraExposer, err := c.getInfraSpecificExposer(cheCluster, routing, objs); err != nil {
|
||||
if infraExposer, err := c.getInfraSpecificExposer(cheCluster, routing, objs, endpointStrategy); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
if workspaceConfig := exposeAllEndpoints(cheCluster, routing, objs, infraExposer); workspaceConfig != nil {
|
||||
if workspaceConfig := exposeAllEndpoints(cheCluster, routing, objs, infraExposer, endpointStrategy); workspaceConfig != nil {
|
||||
configs = append(configs, *workspaceConfig)
|
||||
}
|
||||
}
|
||||
|
|
@ -349,14 +352,103 @@ func (c *CheRoutingSolver) getGatewayConfigsAndFillRoutingObjects(cheCluster *ch
|
|||
return configs, nil
|
||||
}
|
||||
|
||||
func (c *CheRoutingSolver) getInfraSpecificExposer(cheCluster *chev2.CheCluster, routing *dwo.DevWorkspaceRouting, objs *solvers.RoutingObjects) (func(info *EndpointInfo), error) {
|
||||
func getEndpointPathStrategy(c client.Client, workspaceId string, namespace string, dwRoutingName string) EndpointStrategy {
|
||||
useLegacyPaths := false
|
||||
username, err := getNormalizedUsername(c, namespace)
|
||||
if err != nil {
|
||||
useLegacyPaths = true
|
||||
}
|
||||
|
||||
dwName, err := getNormalizedWkspName(c, namespace, dwRoutingName)
|
||||
if err != nil {
|
||||
useLegacyPaths = true
|
||||
}
|
||||
|
||||
if useLegacyPaths {
|
||||
strategy := new(Legacy)
|
||||
strategy.workspaceID = workspaceId
|
||||
return strategy
|
||||
} else {
|
||||
strategy := new(UsernameWkspName)
|
||||
strategy.username = username
|
||||
strategy.workspaceName = dwName
|
||||
return strategy
|
||||
}
|
||||
}
|
||||
|
||||
func getNormalizedUsername(c client.Client, namespace string) (string, error) {
|
||||
username, err := getUsernameFromNamespace(c, namespace)
|
||||
|
||||
if err != nil {
|
||||
username, err = getUsernameFromSecret(c, namespace)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return normalize(username), nil
|
||||
}
|
||||
|
||||
func getUsernameFromSecret(c client.Client, namespace string) (string, error) {
|
||||
secret := &corev1.Secret{}
|
||||
err := c.Get(context.TODO(), client.ObjectKey{Name: "user-profile", Namespace: namespace}, secret)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
username := string(secret.Data["name"])
|
||||
return normalize(username), nil
|
||||
}
|
||||
|
||||
func getUsernameFromNamespace(c client.Client, namespace string) (string, error) {
|
||||
nsInfo := &corev1.Namespace{}
|
||||
err := c.Get(context.TODO(), client.ObjectKey{Name: namespace}, nsInfo)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
notFoundError := fmt.Errorf("username not found in namespace %s", namespace)
|
||||
|
||||
if nsInfo.GetAnnotations() == nil {
|
||||
return "", notFoundError
|
||||
}
|
||||
|
||||
username, exists := nsInfo.GetAnnotations()["che.eclipse.org/username"]
|
||||
|
||||
if exists {
|
||||
return username, nil
|
||||
}
|
||||
|
||||
return "", notFoundError
|
||||
}
|
||||
|
||||
func getNormalizedWkspName(c client.Client, namespace string, routingName string) (string, error) {
|
||||
routing := &dwo.DevWorkspaceRouting{}
|
||||
err := c.Get(context.TODO(), client.ObjectKey{Name: routingName, Namespace: namespace}, routing)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return normalize(routing.ObjectMeta.OwnerReferences[0].Name), nil
|
||||
}
|
||||
|
||||
func normalize(username string) string {
|
||||
r1 := regexp.MustCompile(`[^-a-zA-Z0-9]`)
|
||||
r2 := regexp.MustCompile(`-+`)
|
||||
r3 := regexp.MustCompile(`^-|-$`)
|
||||
|
||||
result := r1.ReplaceAllString(username, "-") // replace invalid chars with '-'
|
||||
result = r2.ReplaceAllString(result, "-") // replace multiple '-' with single ones
|
||||
result = r3.ReplaceAllString(result, "") // trim dashes at beginning/end
|
||||
return strings.ToLower(result)
|
||||
}
|
||||
|
||||
func (c *CheRoutingSolver) getInfraSpecificExposer(cheCluster *chev2.CheCluster, routing *dwo.DevWorkspaceRouting, objs *solvers.RoutingObjects, endpointStrategy EndpointStrategy) (func(info *EndpointInfo), error) {
|
||||
if infrastructure.IsOpenShift() {
|
||||
exposer := &RouteExposer{}
|
||||
if err := exposer.initFrom(context.TODO(), c.client, cheCluster, routing); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return func(info *EndpointInfo) {
|
||||
route := exposer.getRouteForService(info)
|
||||
route := exposer.getRouteForService(info, endpointStrategy)
|
||||
objs.Routes = append(objs.Routes, route)
|
||||
}, nil
|
||||
} else {
|
||||
|
|
@ -365,7 +457,7 @@ func (c *CheRoutingSolver) getInfraSpecificExposer(cheCluster *chev2.CheCluster,
|
|||
return nil, err
|
||||
}
|
||||
return func(info *EndpointInfo) {
|
||||
ingress := exposer.getIngressForService(info)
|
||||
ingress := exposer.getIngressForService(info, endpointStrategy)
|
||||
objs.Ingresses = append(objs.Ingresses, ingress)
|
||||
}, nil
|
||||
}
|
||||
|
|
@ -381,7 +473,7 @@ func getCommonService(objs *solvers.RoutingObjects, dwId string) *corev1.Service
|
|||
return nil
|
||||
}
|
||||
|
||||
func exposeAllEndpoints(cheCluster *chev2.CheCluster, routing *dwo.DevWorkspaceRouting, objs *solvers.RoutingObjects, ingressExpose func(*EndpointInfo)) *corev1.ConfigMap {
|
||||
func exposeAllEndpoints(cheCluster *chev2.CheCluster, routing *dwo.DevWorkspaceRouting, objs *solvers.RoutingObjects, ingressExpose func(*EndpointInfo), endpointStrategy EndpointStrategy) *corev1.ConfigMap {
|
||||
wsRouteConfig := gateway.CreateEmptyTraefikConfig()
|
||||
|
||||
commonService := getCommonService(objs, routing.Spec.DevWorkspaceId)
|
||||
|
|
@ -412,7 +504,7 @@ func exposeAllEndpoints(cheCluster *chev2.CheCluster, routing *dwo.DevWorkspaceR
|
|||
}
|
||||
|
||||
if e.Attributes.GetString(urlRewriteSupportedEndpointAttributeName, nil) == "true" {
|
||||
addEndpointToTraefikConfig(componentName, e, wsRouteConfig, cheCluster, routing)
|
||||
addEndpointToTraefikConfig(componentName, e, wsRouteConfig, cheCluster, routing, endpointStrategy)
|
||||
} else {
|
||||
ingressExpose(&EndpointInfo{
|
||||
order: order,
|
||||
|
|
@ -473,16 +565,16 @@ func containPort(service *corev1.Service, port int32) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func provisionMainWorkspaceRoute(cheCluster *chev2.CheCluster, routing *dwo.DevWorkspaceRouting, cmLabels map[string]string) (*corev1.ConfigMap, error) {
|
||||
func provisionMainWorkspaceRoute(cheCluster *chev2.CheCluster, routing *dwo.DevWorkspaceRouting, cmLabels map[string]string, endpointStrategy EndpointStrategy) (*corev1.ConfigMap, error) {
|
||||
dwId := routing.Spec.DevWorkspaceId
|
||||
dwNamespace := routing.Namespace
|
||||
|
||||
cfg := gateway.CreateCommonTraefikConfig(
|
||||
dwId,
|
||||
fmt.Sprintf("PathPrefix(`/%s`)", dwId),
|
||||
fmt.Sprintf("PathPrefix(`%s`)", endpointStrategy.getMainWorkspacePathPrefix()),
|
||||
100,
|
||||
getServiceURL(wsGatewayPort, dwId, dwNamespace),
|
||||
[]string{"/" + dwId})
|
||||
[]string{endpointStrategy.getMainWorkspacePathPrefix()})
|
||||
|
||||
if cheCluster.IsAccessTokenConfigured() {
|
||||
cfg.AddAuthHeaderRewrite(dwId)
|
||||
|
|
@ -494,7 +586,7 @@ func provisionMainWorkspaceRoute(cheCluster *chev2.CheCluster, routing *dwo.DevW
|
|||
add5XXErrorHandling(cfg, dwId)
|
||||
|
||||
// make '/healthz' path of main endpoints reachable from outside
|
||||
routeForHealthzEndpoint(cfg, dwId, routing.Spec.Endpoints)
|
||||
routeForHealthzEndpoint(cfg, dwId, routing.Spec.Endpoints, endpointStrategy)
|
||||
|
||||
if contents, err := yaml.Marshal(cfg); err != nil {
|
||||
return nil, err
|
||||
|
|
@ -540,7 +632,7 @@ func add5XXErrorHandling(cfg *gateway.TraefikConfig, dwId string) {
|
|||
}
|
||||
|
||||
// makes '/healthz' path of main endpoints reachable from the outside
|
||||
func routeForHealthzEndpoint(cfg *gateway.TraefikConfig, dwId string, endpoints map[string]dwo.EndpointList) {
|
||||
func routeForHealthzEndpoint(cfg *gateway.TraefikConfig, dwId string, endpoints map[string]dwo.EndpointList, endpointStrategy EndpointStrategy) {
|
||||
for componentName, endpoints := range endpoints {
|
||||
for _, e := range endpoints {
|
||||
if e.Attributes.GetString(string(dwo.TypeEndpointAttribute), nil) == string(dwo.MainEndpointType) {
|
||||
|
|
@ -548,10 +640,10 @@ func routeForHealthzEndpoint(cfg *gateway.TraefikConfig, dwId string, endpoints
|
|||
if infrastructure.IsOpenShift() {
|
||||
middlewares = append(middlewares, dwId+gateway.HeaderRewriteMiddlewareSuffix)
|
||||
}
|
||||
routeName, endpointPath := createEndpointPath(&e, componentName)
|
||||
routeName, endpointPath := endpointStrategy.getEndpointPath(&e, componentName)
|
||||
routerName := fmt.Sprintf("%s-%s-healthz", dwId, routeName)
|
||||
cfg.HTTP.Routers[routerName] = &gateway.TraefikConfigRouter{
|
||||
Rule: fmt.Sprintf("Path(`/%s%s/healthz`)", dwId, endpointPath),
|
||||
Rule: fmt.Sprintf("Path(`%s/healthz`)", endpointStrategy.getEndpointPathPrefix(endpointPath)),
|
||||
Service: dwId,
|
||||
Middlewares: middlewares,
|
||||
Priority: 101,
|
||||
|
|
@ -561,8 +653,8 @@ func routeForHealthzEndpoint(cfg *gateway.TraefikConfig, dwId string, endpoints
|
|||
}
|
||||
}
|
||||
|
||||
func addEndpointToTraefikConfig(componentName string, e dwo.Endpoint, cfg *gateway.TraefikConfig, cheCluster *chev2.CheCluster, routing *dwo.DevWorkspaceRouting) {
|
||||
routeName, prefix := createEndpointPath(&e, componentName)
|
||||
func addEndpointToTraefikConfig(componentName string, e dwo.Endpoint, cfg *gateway.TraefikConfig, cheCluster *chev2.CheCluster, routing *dwo.DevWorkspaceRouting, endpointStrategy EndpointStrategy) {
|
||||
routeName, prefix := endpointStrategy.getEndpointPath(&e, componentName)
|
||||
rulePrefix := fmt.Sprintf("PathPrefix(`%s`)", prefix)
|
||||
|
||||
// skip if exact same route is already exposed
|
||||
|
|
@ -594,19 +686,6 @@ func addEndpointToTraefikConfig(componentName string, e dwo.Endpoint, cfg *gatew
|
|||
}
|
||||
}
|
||||
|
||||
func createEndpointPath(e *dwo.Endpoint, componentName string) (routeName string, path string) {
|
||||
if e.Attributes.GetString(uniqueEndpointAttributeName, nil) == "true" {
|
||||
// if endpoint is unique, we're exposing on /componentName/<endpoint-name>
|
||||
routeName = e.Name
|
||||
} else {
|
||||
// if endpoint is NOT unique, we're exposing on /componentName/<port-number>
|
||||
routeName = strconv.Itoa(e.TargetPort)
|
||||
}
|
||||
path = fmt.Sprintf("/%s/%s", componentName, routeName)
|
||||
|
||||
return routeName, path
|
||||
}
|
||||
|
||||
func findServiceForPort(port int32, objs *solvers.RoutingObjects) *corev1.Service {
|
||||
for i := range objs.Services {
|
||||
svc := &objs.Services[i]
|
||||
|
|
@ -713,20 +792,12 @@ func getServiceURL(port int32, workspaceID string, workspaceNamespace string) st
|
|||
return fmt.Sprintf("http://%s.%s.svc:%d", common.ServiceName(workspaceID), workspaceNamespace, port)
|
||||
}
|
||||
|
||||
func getPublicURLPrefixForEndpoint(workspaceID string, machineName string, endpoint dwo.Endpoint) string {
|
||||
func getPublicURLPrefixForEndpoint(componentName string, endpoint dwo.Endpoint, endpointStrategy EndpointStrategy) string {
|
||||
endpointName := ""
|
||||
if endpoint.Attributes.GetString(uniqueEndpointAttributeName, nil) == "true" {
|
||||
endpointName = endpoint.Name
|
||||
}
|
||||
|
||||
return getPublicURLPrefix(workspaceID, machineName, int32(endpoint.TargetPort), endpointName)
|
||||
}
|
||||
|
||||
func getPublicURLPrefix(workspaceID string, machineName string, port int32, uniqueEndpointName string) string {
|
||||
if uniqueEndpointName == "" {
|
||||
return fmt.Sprintf(endpointURLPrefixPattern, workspaceID, machineName, port)
|
||||
}
|
||||
return fmt.Sprintf(uniqueEndpointURLPrefixPattern, workspaceID, machineName, uniqueEndpointName)
|
||||
return endpointStrategy.getPublicURLPrefix(int32(endpoint.TargetPort), endpointName, componentName)
|
||||
}
|
||||
|
||||
func determineEndpointScheme(e dwo.Endpoint) string {
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ import (
|
|||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
|
@ -66,7 +67,7 @@ func createTestScheme() *runtime.Scheme {
|
|||
func getSpecObjectsForManager(t *testing.T, mgr *chev2.CheCluster, routing *dwo.DevWorkspaceRouting, additionalInitialObjects ...runtime.Object) (client.Client, solvers.RoutingSolver, solvers.RoutingObjects) {
|
||||
scheme := createTestScheme()
|
||||
|
||||
allObjs := []runtime.Object{mgr}
|
||||
allObjs := []runtime.Object{mgr, routing}
|
||||
for i := range additionalInitialObjects {
|
||||
allObjs = append(allObjs, additionalInitialObjects[i])
|
||||
}
|
||||
|
|
@ -95,6 +96,26 @@ func getSpecObjectsForManager(t *testing.T, mgr *chev2.CheCluster, routing *dwo.
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// set owner references for the routing objects
|
||||
for idx := range objs.Services {
|
||||
err := controllerutil.SetControllerReference(routing, &objs.Services[idx], scheme)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
for idx := range objs.Ingresses {
|
||||
err := controllerutil.SetControllerReference(routing, &objs.Ingresses[idx], scheme)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
for idx := range objs.Routes {
|
||||
err := controllerutil.SetControllerReference(routing, &objs.Routes[idx], scheme)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// now we need a second round of che manager reconciliation so that it proclaims the che gateway as established
|
||||
cheRecon.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "che", Namespace: "ns"}})
|
||||
|
||||
|
|
@ -114,7 +135,7 @@ func getSpecObjects(t *testing.T, routing *dwo.DevWorkspaceRouting) (client.Clie
|
|||
Hostname: "over.the.rainbow",
|
||||
},
|
||||
},
|
||||
}, routing)
|
||||
}, routing, userProfileSecret())
|
||||
}
|
||||
|
||||
func subdomainDevWorkspaceRouting() *dwo.DevWorkspaceRouting {
|
||||
|
|
@ -122,6 +143,14 @@ func subdomainDevWorkspaceRouting() *dwo.DevWorkspaceRouting {
|
|||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "routing",
|
||||
Namespace: "ws",
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: "workspace.devfile.io/v1alpha2",
|
||||
Kind: "DevWorkspace",
|
||||
Name: "my-workspace",
|
||||
UID: "uid",
|
||||
},
|
||||
},
|
||||
},
|
||||
Spec: dwo.DevWorkspaceRoutingSpec{
|
||||
DevWorkspaceId: "wsid",
|
||||
|
|
@ -159,6 +188,14 @@ func relocatableDevWorkspaceRouting() *dwo.DevWorkspaceRouting {
|
|||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "routing",
|
||||
Namespace: "ws",
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: "workspace.devfile.io/v1alpha2",
|
||||
Kind: "DevWorkspace",
|
||||
Name: "my-workspace",
|
||||
UID: "uid",
|
||||
},
|
||||
},
|
||||
},
|
||||
Spec: dwo.DevWorkspaceRoutingSpec{
|
||||
DevWorkspaceId: "wsid",
|
||||
|
|
@ -201,6 +238,19 @@ func relocatableDevWorkspaceRouting() *dwo.DevWorkspaceRouting {
|
|||
}
|
||||
}
|
||||
|
||||
func userProfileSecret() *corev1.Secret {
|
||||
return &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "user-profile",
|
||||
Namespace: "ws",
|
||||
Finalizers: []string{controller.FinalizerName},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"name": []byte("username"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateRelocatedObjectsK8S(t *testing.T) {
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
cl, _, objs := getSpecObjects(t, relocatableDevWorkspaceRouting())
|
||||
|
|
@ -327,6 +377,149 @@ func TestCreateRelocatedObjectsK8S(t *testing.T) {
|
|||
assert.Truef(t, found, "traefik config route doesn't set middleware '%s'", mware)
|
||||
}
|
||||
|
||||
t.Run("testEndpointInMainWorkspaceRoute", func(t *testing.T) {
|
||||
assert.Contains(t, workspaceMainConfig.HTTP.Routers, wsid)
|
||||
assert.Equal(t, workspaceMainConfig.HTTP.Routers[wsid].Service, wsid)
|
||||
assert.Equal(t, workspaceMainConfig.HTTP.Routers[wsid].Rule, "PathPrefix(`/username/my-workspace`)")
|
||||
})
|
||||
|
||||
t.Run("testServerTransportInMainWorkspaceRoute", func(t *testing.T) {
|
||||
serverTransportName := wsid
|
||||
|
||||
assert.Len(t, workspaceMainConfig.HTTP.ServersTransports, 1)
|
||||
assert.Contains(t, workspaceMainConfig.HTTP.ServersTransports, serverTransportName)
|
||||
|
||||
assert.Len(t, workspaceMainConfig.HTTP.Services, 1)
|
||||
assert.Contains(t, workspaceMainConfig.HTTP.Services, wsid)
|
||||
assert.Equal(t, workspaceMainConfig.HTTP.Services[wsid].LoadBalancer.ServersTransport, serverTransportName)
|
||||
})
|
||||
|
||||
t.Run("testHealthzEndpointInMainWorkspaceRoute", func(t *testing.T) {
|
||||
healthzName := "wsid-9999-healthz"
|
||||
assert.Contains(t, workspaceMainConfig.HTTP.Routers, healthzName)
|
||||
assert.Equal(t, workspaceMainConfig.HTTP.Routers[healthzName].Service, wsid)
|
||||
assert.Equal(t, workspaceMainConfig.HTTP.Routers[healthzName].Rule, "Path(`/username/my-workspace/9999/healthz`)")
|
||||
assert.NotContains(t, workspaceMainConfig.HTTP.Routers[healthzName].Middlewares, "wsid"+gateway.AuthMiddlewareSuffix)
|
||||
assert.Contains(t, workspaceMainConfig.HTTP.Routers[healthzName].Middlewares, "wsid"+gateway.StripPrefixMiddlewareSuffix)
|
||||
assert.NotContains(t, workspaceMainConfig.HTTP.Routers[healthzName].Middlewares, "wsid"+gateway.HeaderRewriteMiddlewareSuffix)
|
||||
})
|
||||
|
||||
t.Run("testHealthzEndpointInWorkspaceRoute", func(t *testing.T) {
|
||||
healthzName := "wsid-m1-9999-healthz"
|
||||
assert.Contains(t, workspaceConfig.HTTP.Routers, healthzName)
|
||||
assert.Equal(t, workspaceConfig.HTTP.Routers[healthzName].Service, healthzName)
|
||||
assert.Equal(t, workspaceConfig.HTTP.Routers[healthzName].Rule, "Path(`/9999/healthz`)")
|
||||
assert.NotContains(t, workspaceConfig.HTTP.Routers[healthzName].Middlewares, healthzName+gateway.AuthMiddlewareSuffix)
|
||||
assert.Contains(t, workspaceConfig.HTTP.Routers[healthzName].Middlewares, healthzName+gateway.StripPrefixMiddlewareSuffix)
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestCreateRelocatedObjectsK8SLegacy(t *testing.T) {
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
|
||||
cl, _, objs := getSpecObjectsForManager(t, &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "che",
|
||||
Namespace: "ns",
|
||||
Finalizers: []string{controller.FinalizerName},
|
||||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Networking: chev2.CheClusterSpecNetworking{
|
||||
Domain: "down.on.earth",
|
||||
Hostname: "over.the.rainbow",
|
||||
},
|
||||
},
|
||||
}, relocatableDevWorkspaceRouting())
|
||||
|
||||
t.Run("noIngresses", func(t *testing.T) {
|
||||
if len(objs.Ingresses) != 0 {
|
||||
t.Error()
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("noRoutes", func(t *testing.T) {
|
||||
if len(objs.Routes) != 0 {
|
||||
t.Error()
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("traefikConfig", func(t *testing.T) {
|
||||
cms := &corev1.ConfigMapList{}
|
||||
cl.List(context.TODO(), cms)
|
||||
|
||||
assert.Len(t, cms.Items, 2)
|
||||
|
||||
var workspaceMainCfg *corev1.ConfigMap
|
||||
var workspaceCfg *corev1.ConfigMap
|
||||
for _, cfg := range cms.Items {
|
||||
if cfg.Name == "wsid-route" && cfg.Namespace == "ns" {
|
||||
workspaceMainCfg = cfg.DeepCopy()
|
||||
}
|
||||
if cfg.Name == "wsid-route" && cfg.Namespace == "ws" {
|
||||
workspaceCfg = cfg.DeepCopy()
|
||||
}
|
||||
}
|
||||
|
||||
assert.NotNil(t, workspaceMainCfg)
|
||||
|
||||
traefikMainWorkspaceConfig := workspaceMainCfg.Data["wsid.yml"]
|
||||
assert.NotEmpty(t, traefikMainWorkspaceConfig)
|
||||
|
||||
traefikWorkspaceConfig := workspaceCfg.Data["workspace.yml"]
|
||||
assert.NotEmpty(t, traefikWorkspaceConfig)
|
||||
|
||||
workspaceConfig := gateway.TraefikConfig{}
|
||||
assert.NoError(t, yaml.Unmarshal([]byte(traefikWorkspaceConfig), &workspaceConfig))
|
||||
assert.Len(t, workspaceConfig.HTTP.Routers, 2)
|
||||
|
||||
wsid := "wsid-m1-9999"
|
||||
assert.Contains(t, workspaceConfig.HTTP.Routers, wsid)
|
||||
assert.Len(t, workspaceConfig.HTTP.Routers[wsid].Middlewares, 2)
|
||||
assert.Len(t, workspaceConfig.HTTP.Middlewares, 3)
|
||||
|
||||
mwares := []string{wsid + gateway.StripPrefixMiddlewareSuffix}
|
||||
for _, mware := range mwares {
|
||||
assert.Contains(t, workspaceConfig.HTTP.Middlewares, mware)
|
||||
found := false
|
||||
for _, r := range workspaceConfig.HTTP.Routers[wsid].Middlewares {
|
||||
if r == mware {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
assert.True(t, found)
|
||||
}
|
||||
|
||||
workspaceMainConfig := gateway.TraefikConfig{}
|
||||
assert.NoError(t, yaml.Unmarshal([]byte(traefikMainWorkspaceConfig), &workspaceMainConfig))
|
||||
assert.Len(t, workspaceMainConfig.HTTP.Middlewares, 5)
|
||||
|
||||
wsid = "wsid"
|
||||
mwares = []string{
|
||||
wsid + gateway.AuthMiddlewareSuffix,
|
||||
wsid + gateway.StripPrefixMiddlewareSuffix,
|
||||
wsid + gateway.HeadersMiddlewareSuffix,
|
||||
wsid + gateway.ErrorsMiddlewareSuffix,
|
||||
wsid + gateway.RetryMiddlewareSuffix}
|
||||
for _, mware := range mwares {
|
||||
assert.Contains(t, workspaceMainConfig.HTTP.Middlewares, mware)
|
||||
|
||||
found := false
|
||||
for _, r := range workspaceMainConfig.HTTP.Routers[wsid].Middlewares {
|
||||
if r == mware {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
assert.Truef(t, found, "traefik config route doesn't set middleware '%s'", mware)
|
||||
}
|
||||
|
||||
t.Run("testEndpointInMainWorkspaceRoute", func(t *testing.T) {
|
||||
assert.Contains(t, workspaceMainConfig.HTTP.Routers, wsid)
|
||||
assert.Equal(t, workspaceMainConfig.HTTP.Routers[wsid].Service, wsid)
|
||||
assert.Equal(t, workspaceMainConfig.HTTP.Routers[wsid].Rule, fmt.Sprintf("PathPrefix(`/%s`)", wsid))
|
||||
})
|
||||
|
||||
t.Run("testServerTransportInMainWorkspaceRoute", func(t *testing.T) {
|
||||
serverTransportName := wsid
|
||||
|
||||
|
|
@ -376,6 +569,114 @@ func TestCreateRelocatedObjectsOpenshift(t *testing.T) {
|
|||
assert.Equal(t, objs.PodAdditions.Volumes[0].Name, wsGatewayName)
|
||||
})
|
||||
|
||||
t.Run("traefikConfig", func(t *testing.T) {
|
||||
cms := &corev1.ConfigMapList{}
|
||||
cl.List(context.TODO(), cms)
|
||||
|
||||
assert.Len(t, cms.Items, 2)
|
||||
|
||||
var workspaceMainCfg *corev1.ConfigMap
|
||||
var workspaceCfg *corev1.ConfigMap
|
||||
for _, cfg := range cms.Items {
|
||||
if cfg.Name == "wsid-route" && cfg.Namespace == "ns" {
|
||||
workspaceMainCfg = cfg.DeepCopy()
|
||||
}
|
||||
if cfg.Name == "wsid-route" && cfg.Namespace == "ws" {
|
||||
workspaceCfg = cfg.DeepCopy()
|
||||
}
|
||||
}
|
||||
|
||||
assert.NotNil(t, workspaceMainCfg, "traefik configuration for the workspace not found")
|
||||
|
||||
traefikMainWorkspaceConfig := workspaceMainCfg.Data["wsid.yml"]
|
||||
assert.NotEmpty(t, traefikMainWorkspaceConfig, "No traefik config file found in the main workspace config configmap")
|
||||
|
||||
traefikWorkspaceConfig := workspaceCfg.Data["workspace.yml"]
|
||||
assert.NotEmpty(t, traefikWorkspaceConfig, "No traefik config file found in the workspace config configmap")
|
||||
|
||||
workspaceConfig := gateway.TraefikConfig{}
|
||||
assert.NoError(t, yaml.Unmarshal([]byte(traefikWorkspaceConfig), &workspaceConfig))
|
||||
|
||||
wsid := "wsid-m1-9999"
|
||||
assert.Contains(t, workspaceConfig.HTTP.Routers, wsid)
|
||||
assert.Len(t, workspaceConfig.HTTP.Routers[wsid].Middlewares, 2)
|
||||
|
||||
workspaceMainConfig := gateway.TraefikConfig{}
|
||||
assert.NoError(t, yaml.Unmarshal([]byte(traefikMainWorkspaceConfig), &workspaceMainConfig))
|
||||
assert.Len(t, workspaceMainConfig.HTTP.Middlewares, 6)
|
||||
|
||||
wsid = "wsid"
|
||||
mwares := []string{
|
||||
wsid + gateway.AuthMiddlewareSuffix,
|
||||
wsid + gateway.StripPrefixMiddlewareSuffix,
|
||||
wsid + gateway.HeaderRewriteMiddlewareSuffix,
|
||||
wsid + gateway.HeadersMiddlewareSuffix,
|
||||
wsid + gateway.ErrorsMiddlewareSuffix,
|
||||
wsid + gateway.RetryMiddlewareSuffix}
|
||||
for _, mware := range mwares {
|
||||
assert.Contains(t, workspaceMainConfig.HTTP.Middlewares, mware)
|
||||
|
||||
found := false
|
||||
for _, r := range workspaceMainConfig.HTTP.Routers[wsid].Middlewares {
|
||||
if r == mware {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
assert.Truef(t, found, "traefik config route doesn't set middleware '%s'", mware)
|
||||
}
|
||||
|
||||
t.Run("testServerTransportInMainWorkspaceRoute", func(t *testing.T) {
|
||||
serverTransportName := wsid
|
||||
|
||||
assert.Len(t, workspaceMainConfig.HTTP.ServersTransports, 1)
|
||||
assert.Contains(t, workspaceMainConfig.HTTP.ServersTransports, serverTransportName)
|
||||
|
||||
assert.Len(t, workspaceMainConfig.HTTP.Services, 1)
|
||||
assert.Contains(t, workspaceMainConfig.HTTP.Services, wsid)
|
||||
assert.Equal(t, workspaceMainConfig.HTTP.Services[wsid].LoadBalancer.ServersTransport, serverTransportName)
|
||||
})
|
||||
|
||||
t.Run("testHealthzEndpointInMainWorkspaceRoute", func(t *testing.T) {
|
||||
healthzName := "wsid-9999-healthz"
|
||||
assert.Contains(t, workspaceMainConfig.HTTP.Routers, healthzName)
|
||||
assert.Equal(t, workspaceMainConfig.HTTP.Routers[healthzName].Service, wsid)
|
||||
assert.Equal(t, workspaceMainConfig.HTTP.Routers[healthzName].Rule, "Path(`/username/my-workspace/9999/healthz`)")
|
||||
assert.NotContains(t, workspaceMainConfig.HTTP.Routers[healthzName].Middlewares, "wsid"+gateway.AuthMiddlewareSuffix)
|
||||
assert.Contains(t, workspaceMainConfig.HTTP.Routers[healthzName].Middlewares, "wsid"+gateway.StripPrefixMiddlewareSuffix)
|
||||
assert.Contains(t, workspaceMainConfig.HTTP.Routers[healthzName].Middlewares, "wsid"+gateway.HeaderRewriteMiddlewareSuffix)
|
||||
})
|
||||
|
||||
t.Run("testHealthzEndpointInWorkspaceRoute", func(t *testing.T) {
|
||||
healthzName := "wsid-m1-9999-healthz"
|
||||
assert.Contains(t, workspaceConfig.HTTP.Routers, healthzName)
|
||||
assert.Equal(t, workspaceConfig.HTTP.Routers[healthzName].Service, healthzName)
|
||||
assert.Equal(t, workspaceConfig.HTTP.Routers[healthzName].Rule, "Path(`/9999/healthz`)")
|
||||
assert.NotContains(t, workspaceConfig.HTTP.Routers[healthzName].Middlewares, healthzName+gateway.AuthMiddlewareSuffix)
|
||||
assert.Contains(t, workspaceConfig.HTTP.Routers[healthzName].Middlewares, healthzName+gateway.StripPrefixMiddlewareSuffix)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestCreateRelocatedObjectsOpenshiftLegacy(t *testing.T) {
|
||||
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
|
||||
|
||||
cl, _, objs := getSpecObjectsForManager(t, &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "che",
|
||||
Namespace: "ns",
|
||||
Finalizers: []string{controller.FinalizerName},
|
||||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Networking: chev2.CheClusterSpecNetworking{
|
||||
Domain: "down.on.earth",
|
||||
Hostname: "over.the.rainbow",
|
||||
},
|
||||
},
|
||||
}, relocatableDevWorkspaceRouting())
|
||||
|
||||
assert.Empty(t, objs.Ingresses)
|
||||
assert.Empty(t, objs.Routes)
|
||||
|
||||
t.Run("traefikConfig", func(t *testing.T) {
|
||||
cms := &corev1.ConfigMapList{}
|
||||
cl.List(context.TODO(), cms)
|
||||
|
|
@ -472,6 +773,14 @@ func TestUniqueMainEndpoint(t *testing.T) {
|
|||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "routing",
|
||||
Namespace: "ws",
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: "workspace.devfile.io/v1alpha2",
|
||||
Kind: "DevWorkspace",
|
||||
Name: "my-workspace",
|
||||
UID: "uid",
|
||||
},
|
||||
},
|
||||
},
|
||||
Spec: dwo.DevWorkspaceRoutingSpec{
|
||||
DevWorkspaceId: wsid,
|
||||
|
|
@ -519,6 +828,104 @@ func TestUniqueMainEndpoint(t *testing.T) {
|
|||
workspaceMainConfig := gateway.TraefikConfig{}
|
||||
assert.NoError(t, yaml.Unmarshal([]byte(traefikMainWorkspaceConfig), &workspaceMainConfig))
|
||||
|
||||
t.Run("testHealthzEndpointInMainWorkspaceRoute", func(t *testing.T) {
|
||||
healthzName := wsid + "-e1-healthz"
|
||||
assert.Contains(t, workspaceMainConfig.HTTP.Routers, healthzName)
|
||||
assert.Equal(t, workspaceMainConfig.HTTP.Routers[healthzName].Service, wsid)
|
||||
assert.Equal(t, workspaceMainConfig.HTTP.Routers[healthzName].Rule, "Path(`/username/my-workspace/e1/healthz`)")
|
||||
assert.NotContains(t, workspaceMainConfig.HTTP.Routers[healthzName].Middlewares, wsid+gateway.AuthMiddlewareSuffix)
|
||||
assert.Contains(t, workspaceMainConfig.HTTP.Routers[healthzName].Middlewares, wsid+gateway.StripPrefixMiddlewareSuffix)
|
||||
assert.Contains(t, workspaceMainConfig.HTTP.Routers[healthzName].Middlewares, wsid+gateway.HeaderRewriteMiddlewareSuffix)
|
||||
})
|
||||
|
||||
t.Run("testHealthzEndpointInWorkspaceRoute", func(t *testing.T) {
|
||||
healthzName := wsid + "-m1-e1-healthz"
|
||||
assert.Contains(t, workspaceConfig.HTTP.Routers, healthzName)
|
||||
assert.Equal(t, workspaceConfig.HTTP.Routers[healthzName].Service, healthzName)
|
||||
assert.Equal(t, workspaceConfig.HTTP.Routers[healthzName].Rule, "Path(`/e1/healthz`)")
|
||||
assert.NotContains(t, workspaceConfig.HTTP.Routers[healthzName].Middlewares, healthzName+gateway.AuthMiddlewareSuffix)
|
||||
assert.Contains(t, workspaceConfig.HTTP.Routers[healthzName].Middlewares, healthzName+gateway.StripPrefixMiddlewareSuffix)
|
||||
})
|
||||
}
|
||||
|
||||
func TestUniqueMainEndpointLegacy(t *testing.T) {
|
||||
wsid := "wsid123"
|
||||
|
||||
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
|
||||
|
||||
routing := &dwo.DevWorkspaceRouting{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "routing",
|
||||
Namespace: "ws",
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: "workspace.devfile.io/v1alpha2",
|
||||
Kind: "DevWorkspace",
|
||||
Name: "my-workspace",
|
||||
UID: "uid",
|
||||
},
|
||||
},
|
||||
},
|
||||
Spec: dwo.DevWorkspaceRoutingSpec{
|
||||
DevWorkspaceId: wsid,
|
||||
RoutingClass: "che",
|
||||
Endpoints: map[string]dwo.EndpointList{
|
||||
"m1": {
|
||||
{
|
||||
Name: "e1",
|
||||
TargetPort: 9999,
|
||||
Exposure: dwo.PublicEndpointExposure,
|
||||
Protocol: "https",
|
||||
Path: "/1/",
|
||||
Attributes: dwo.Attributes{
|
||||
urlRewriteSupportedEndpointAttributeName: apiext.JSON{Raw: []byte("\"true\"")},
|
||||
string(dwo.TypeEndpointAttribute): apiext.JSON{Raw: []byte("\"main\"")},
|
||||
uniqueEndpointAttributeName: apiext.JSON{Raw: []byte("\"true\"")},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cl, _, _ := getSpecObjectsForManager(t, &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "che",
|
||||
Namespace: "ns",
|
||||
Finalizers: []string{controller.FinalizerName},
|
||||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Networking: chev2.CheClusterSpecNetworking{
|
||||
Domain: "down.on.earth",
|
||||
Hostname: "over.the.rainbow",
|
||||
},
|
||||
},
|
||||
}, routing)
|
||||
|
||||
cms := &corev1.ConfigMapList{}
|
||||
cl.List(context.TODO(), cms)
|
||||
|
||||
assert.Len(t, cms.Items, 2)
|
||||
|
||||
var workspaceMainCfg *corev1.ConfigMap
|
||||
var workspaceCfg *corev1.ConfigMap
|
||||
for _, cfg := range cms.Items {
|
||||
if cfg.Name == wsid+"-route" && cfg.Namespace == "ns" {
|
||||
workspaceMainCfg = cfg.DeepCopy()
|
||||
}
|
||||
if cfg.Name == wsid+"-route" && cfg.Namespace == "ws" {
|
||||
workspaceCfg = cfg.DeepCopy()
|
||||
}
|
||||
}
|
||||
|
||||
traefikWorkspaceConfig := workspaceCfg.Data["workspace.yml"]
|
||||
workspaceConfig := gateway.TraefikConfig{}
|
||||
assert.NoError(t, yaml.Unmarshal([]byte(traefikWorkspaceConfig), &workspaceConfig))
|
||||
|
||||
traefikMainWorkspaceConfig := workspaceMainCfg.Data[wsid+".yml"]
|
||||
workspaceMainConfig := gateway.TraefikConfig{}
|
||||
assert.NoError(t, yaml.Unmarshal([]byte(traefikMainWorkspaceConfig), &workspaceMainConfig))
|
||||
|
||||
t.Run("testHealthzEndpointInMainWorkspaceRoute", func(t *testing.T) {
|
||||
healthzName := wsid + "-e1-healthz"
|
||||
assert.Contains(t, workspaceMainConfig.HTTP.Routers, healthzName)
|
||||
|
|
@ -583,6 +990,89 @@ func TestCreateSubDomainObjects(t *testing.T) {
|
|||
return objs
|
||||
}
|
||||
|
||||
t.Run("expectedIngresses", func(t *testing.T) {
|
||||
objs := testCommon(infrastructure.Kubernetes)
|
||||
if len(objs.Ingresses) != 3 {
|
||||
t.Error("Expected 3 ingress, found ", len(objs.Ingresses))
|
||||
}
|
||||
if objs.Ingresses[0].Spec.Rules[0].Host != "username.my-workspace.e1.down.on.earth" {
|
||||
t.Error("Expected Ingress host 'username.my-workspace.e1.down.on.earth', but got ", objs.Ingresses[0].Spec.Rules[0].Host)
|
||||
}
|
||||
if objs.Ingresses[1].Spec.Rules[0].Host != "username.my-workspace.e2.down.on.earth" {
|
||||
t.Error("Expected Ingress host 'username.my-workspace.e2.down.on.earth', but got ", objs.Ingresses[1].Spec.Rules[0].Host)
|
||||
}
|
||||
if objs.Ingresses[2].Spec.Rules[0].Host != "username.my-workspace.e3.down.on.earth" {
|
||||
t.Error("Expected Ingress host 'username.my-workspace.e3.down.on.earth', but got ", objs.Ingresses[2].Spec.Rules[0].Host)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("expectedRoutes", func(t *testing.T) {
|
||||
objs := testCommon(infrastructure.OpenShiftv4)
|
||||
if len(objs.Routes) != 3 {
|
||||
t.Error("Expected 3 Routes, found ", len(objs.Routes))
|
||||
}
|
||||
if objs.Routes[0].Spec.Host != "username.my-workspace.e1.down.on.earth" {
|
||||
t.Error("Expected Route host 'username.my-workspace.e1.down.on.earth', but got ", objs.Routes[0].Spec.Host)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestCreateSubDomainObjectsLegacy(t *testing.T) {
|
||||
testCommon := func(infra infrastructure.Type) solvers.RoutingObjects {
|
||||
infrastructure.InitializeForTesting(infra)
|
||||
|
||||
cl, _, objs := getSpecObjectsForManager(t, &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "che",
|
||||
Namespace: "ns",
|
||||
Finalizers: []string{controller.FinalizerName},
|
||||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Networking: chev2.CheClusterSpecNetworking{
|
||||
Domain: "down.on.earth",
|
||||
Hostname: "over.the.rainbow",
|
||||
},
|
||||
},
|
||||
}, subdomainDevWorkspaceRouting())
|
||||
|
||||
t.Run("testPodAdditions", func(t *testing.T) {
|
||||
if len(objs.PodAdditions.Containers) != 1 || objs.PodAdditions.Containers[0].Name != wsGatewayName {
|
||||
t.Error("expected Container pod addition with Workspace Gateway. Got ", objs.PodAdditions)
|
||||
}
|
||||
if len(objs.PodAdditions.Volumes) != 1 || objs.PodAdditions.Volumes[0].Name != wsGatewayName {
|
||||
t.Error("expected Volume pod addition for workspace gateway. Got ", objs.PodAdditions)
|
||||
}
|
||||
})
|
||||
|
||||
for i := range objs.Services {
|
||||
t.Run(fmt.Sprintf("service-%d", i), func(t *testing.T) {
|
||||
svc := &objs.Services[i]
|
||||
if svc.Annotations[defaults.ConfigAnnotationCheManagerName] != "che" {
|
||||
t.Errorf("The name of the associated che manager should have been recorded in the service annotation")
|
||||
}
|
||||
|
||||
if svc.Annotations[defaults.ConfigAnnotationCheManagerNamespace] != "ns" {
|
||||
t.Errorf("The namespace of the associated che manager should have been recorded in the service annotation")
|
||||
}
|
||||
|
||||
if svc.Labels[dwConstants.DevWorkspaceIDLabel] != "wsid" {
|
||||
t.Errorf("The workspace ID should be recorded in the service labels")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("noWorkspaceTraefikConfig", func(t *testing.T) {
|
||||
cms := &corev1.ConfigMapList{}
|
||||
cl.List(context.TODO(), cms)
|
||||
|
||||
if len(cms.Items) != 2 {
|
||||
t.Errorf("there should be 2 configmaps create but found: %d", len(cms.Items))
|
||||
}
|
||||
})
|
||||
|
||||
return objs
|
||||
}
|
||||
|
||||
t.Run("expectedIngresses", func(t *testing.T) {
|
||||
objs := testCommon(infrastructure.Kubernetes)
|
||||
if len(objs.Ingresses) != 3 {
|
||||
|
|
@ -639,6 +1129,72 @@ func TestReportRelocatableExposedEndpoints(t *testing.T) {
|
|||
t.Fatalf("There should have been 3 endpoints for m1.")
|
||||
}
|
||||
|
||||
e1 := m1[0]
|
||||
if e1.Name != "e1" {
|
||||
t.Errorf("The first endpoint should have been e1 but is %s", e1.Name)
|
||||
}
|
||||
if e1.Url != "https://over.the.rainbow/username/my-workspace/9999/1/" {
|
||||
t.Errorf("The e1 endpoint should have the following URL: '%s' but has '%s'.", "https://over.the.rainbow/username/my-workspace/9999/1/", e1.Url)
|
||||
}
|
||||
|
||||
e2 := m1[1]
|
||||
if e2.Name != "e2" {
|
||||
t.Errorf("The second endpoint should have been e2 but is %s", e1.Name)
|
||||
}
|
||||
if e2.Url != "https://over.the.rainbow/username/my-workspace/9999/2.js" {
|
||||
t.Errorf("The e2 endpoint should have the following URL: '%s' but has '%s'.", "https://over.the.rainbow/username/my-workspace/9999/2.js", e2.Url)
|
||||
}
|
||||
|
||||
e3 := m1[2]
|
||||
if e3.Name != "e3" {
|
||||
t.Errorf("The third endpoint should have been e3 but is %s", e1.Name)
|
||||
}
|
||||
if e3.Url != "https://over.the.rainbow/username/my-workspace/9999/" {
|
||||
t.Errorf("The e3 endpoint should have the following URL: '%s' but has '%s'.", "https://over.the.rainbow/username/my-workspace/9999/", e3.Url)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReportRelocatableExposedEndpointsLegacy(t *testing.T) {
|
||||
// kubernetes
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
|
||||
routing := relocatableDevWorkspaceRouting()
|
||||
_, solver, objs := getSpecObjectsForManager(t, &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "che",
|
||||
Namespace: "ns",
|
||||
Finalizers: []string{controller.FinalizerName},
|
||||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Networking: chev2.CheClusterSpecNetworking{
|
||||
Domain: "down.on.earth",
|
||||
Hostname: "over.the.rainbow",
|
||||
},
|
||||
},
|
||||
}, routing)
|
||||
|
||||
exposed, ready, err := solver.GetExposedEndpoints(routing.Spec.Endpoints, objs)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !ready {
|
||||
t.Errorf("The exposed endpoints should have been ready.")
|
||||
}
|
||||
|
||||
if len(exposed) != 1 {
|
||||
t.Errorf("There should have been 1 exposed endpoins but found %d", len(exposed))
|
||||
}
|
||||
|
||||
m1, ok := exposed["m1"]
|
||||
if !ok {
|
||||
t.Errorf("The exposed endpoints should have been defined on the m1 component.")
|
||||
}
|
||||
|
||||
if len(m1) != 3 {
|
||||
t.Fatalf("There should have been 3 endpoints for m1.")
|
||||
}
|
||||
|
||||
e1 := m1[0]
|
||||
if e1.Name != "e1" {
|
||||
t.Errorf("The first endpoint should have been e1 but is %s", e1.Name)
|
||||
|
|
@ -671,6 +1227,14 @@ func TestExposeEndpoints(t *testing.T) {
|
|||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "routing",
|
||||
Namespace: "ws",
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: "workspace.devfile.io/v1alpha2",
|
||||
Kind: "DevWorkspace",
|
||||
Name: "my-workspace",
|
||||
UID: "uid",
|
||||
},
|
||||
},
|
||||
},
|
||||
Spec: dwo.DevWorkspaceRoutingSpec{
|
||||
DevWorkspaceId: "wsid",
|
||||
|
|
@ -761,6 +1325,136 @@ func TestExposeEndpoints(t *testing.T) {
|
|||
assert.Equal(t, "server-int-nr", sinr[0].Name)
|
||||
assert.Equal(t, "http://wsid-service.ws.svc:8084", sinr[0].Url)
|
||||
|
||||
sp, ok := exposed["server-public"]
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, 1, len(sp))
|
||||
assert.Equal(t, "server-pub", sp[0].Name)
|
||||
assert.Equal(t, "https://over.the.rainbow/username/my-workspace/8082/", sp[0].Url)
|
||||
|
||||
spnr, ok := exposed["server-public-no-rewrite"]
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, 1, len(spnr))
|
||||
assert.Equal(t, "server-pub-nr", spnr[0].Name)
|
||||
assert.Equal(t, "http://username.my-workspace.server-pub-nr.down.on.earth/", spnr[0].Url)
|
||||
}
|
||||
|
||||
func TestExposeEndpointsLegacy(t *testing.T) {
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
|
||||
routing := &dwo.DevWorkspaceRouting{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "routing",
|
||||
Namespace: "ws",
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: "workspace.devfile.io/v1alpha2",
|
||||
Kind: "DevWorkspace",
|
||||
Name: "my-workspace",
|
||||
UID: "uid",
|
||||
},
|
||||
},
|
||||
},
|
||||
Spec: dwo.DevWorkspaceRoutingSpec{
|
||||
DevWorkspaceId: "wsid",
|
||||
RoutingClass: "che",
|
||||
Endpoints: map[string]dwo.EndpointList{
|
||||
"server-internal": {
|
||||
{
|
||||
Name: "server-int",
|
||||
TargetPort: 8081,
|
||||
Exposure: dwo.InternalEndpointExposure,
|
||||
Protocol: "http",
|
||||
Attributes: map[string]apiext.JSON{
|
||||
"urlRewriteSupported": apiext.JSON{Raw: []byte("\"true\"")},
|
||||
"cookiesAuthEnabled": apiext.JSON{Raw: []byte("\"true\"")},
|
||||
},
|
||||
},
|
||||
},
|
||||
"server-internal-no-rewrite": {
|
||||
{
|
||||
Name: "server-int-nr",
|
||||
TargetPort: 8084,
|
||||
Exposure: dwo.InternalEndpointExposure,
|
||||
Protocol: "http",
|
||||
},
|
||||
},
|
||||
"server-none": {
|
||||
{
|
||||
Name: "server-int",
|
||||
TargetPort: 8080,
|
||||
Exposure: dwo.NoneEndpointExposure,
|
||||
Protocol: "http",
|
||||
Attributes: map[string]apiext.JSON{
|
||||
"urlRewriteSupported": apiext.JSON{Raw: []byte("\"true\"")},
|
||||
"cookiesAuthEnabled": apiext.JSON{Raw: []byte("\"true\"")},
|
||||
},
|
||||
},
|
||||
},
|
||||
"server-none-no-rewrite": {
|
||||
{
|
||||
Name: "server-none-nr",
|
||||
TargetPort: 8083,
|
||||
Exposure: dwo.NoneEndpointExposure,
|
||||
Protocol: "http",
|
||||
},
|
||||
},
|
||||
"server-public": {
|
||||
{
|
||||
Name: "server-pub",
|
||||
TargetPort: 8082,
|
||||
Exposure: dwo.PublicEndpointExposure,
|
||||
Protocol: "http",
|
||||
Attributes: map[string]apiext.JSON{
|
||||
"urlRewriteSupported": apiext.JSON{Raw: []byte("\"true\"")},
|
||||
"cookiesAuthEnabled": apiext.JSON{Raw: []byte("\"true\"")},
|
||||
},
|
||||
},
|
||||
},
|
||||
"server-public-no-rewrite": {
|
||||
{
|
||||
Name: "server-pub-nr",
|
||||
TargetPort: 8085,
|
||||
Exposure: dwo.PublicEndpointExposure,
|
||||
Protocol: "http",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, solver, objs := getSpecObjectsForManager(t, &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "che",
|
||||
Namespace: "ns",
|
||||
Finalizers: []string{controller.FinalizerName},
|
||||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Networking: chev2.CheClusterSpecNetworking{
|
||||
Domain: "down.on.earth",
|
||||
Hostname: "over.the.rainbow",
|
||||
},
|
||||
},
|
||||
}, routing)
|
||||
|
||||
assert.Equal(t, 1, len(objs.Ingresses))
|
||||
|
||||
exposed, ready, err := solver.GetExposedEndpoints(routing.Spec.Endpoints, objs)
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, ready)
|
||||
assert.Equal(t, 4, len(exposed))
|
||||
|
||||
si, ok := exposed["server-internal"]
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, 1, len(si))
|
||||
assert.Equal(t, "server-int", si[0].Name)
|
||||
assert.Equal(t, "http://wsid-service.ws.svc:8081", si[0].Url)
|
||||
|
||||
sinr, ok := exposed["server-internal-no-rewrite"]
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, 1, len(sinr))
|
||||
assert.Equal(t, "server-int-nr", sinr[0].Name)
|
||||
assert.Equal(t, "http://wsid-service.ws.svc:8084", sinr[0].Url)
|
||||
|
||||
sp, ok := exposed["server-public"]
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, 1, len(sp))
|
||||
|
|
@ -801,6 +1495,70 @@ func TestReportSubdomainExposedEndpoints(t *testing.T) {
|
|||
t.Fatalf("There should have been 3 endpoints for m1.")
|
||||
}
|
||||
|
||||
e1 := m1[0]
|
||||
if e1.Name != "e1" {
|
||||
t.Errorf("The first endpoint should have been e1 but is %s", e1.Name)
|
||||
}
|
||||
if e1.Url != "https://username.my-workspace.e1.down.on.earth/1/" {
|
||||
t.Errorf("The e1 endpoint should have the following URL: '%s' but has '%s'.", "https://username.my-workspace.e1.down.on.earth/1/", e1.Url)
|
||||
}
|
||||
|
||||
e2 := m1[1]
|
||||
if e2.Name != "e2" {
|
||||
t.Errorf("The second endpoint should have been e2 but is %s", e1.Name)
|
||||
}
|
||||
if e2.Url != "https://username.my-workspace.e2.down.on.earth/2.js" {
|
||||
t.Errorf("The e2 endpoint should have the following URL: '%s' but has '%s'.", "https://username.my-workspace.e2.down.on.earth/2.js", e2.Url)
|
||||
}
|
||||
|
||||
e3 := m1[2]
|
||||
if e3.Name != "e3" {
|
||||
t.Errorf("The third endpoint should have been e3 but is %s", e1.Name)
|
||||
}
|
||||
if e3.Url != "http://username.my-workspace.e3.down.on.earth/" {
|
||||
t.Errorf("The e3 endpoint should have the following URL: '%s' but has '%s'.", "http://username.my-workspace.e3.down.on.earth/", e3.Url)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReportSubdomainExposedEndpointsLegacy(t *testing.T) {
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
routing := subdomainDevWorkspaceRouting()
|
||||
_, solver, objs := getSpecObjectsForManager(t, &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "che",
|
||||
Namespace: "ns",
|
||||
Finalizers: []string{controller.FinalizerName},
|
||||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Networking: chev2.CheClusterSpecNetworking{
|
||||
Domain: "down.on.earth",
|
||||
Hostname: "over.the.rainbow",
|
||||
},
|
||||
},
|
||||
}, routing)
|
||||
|
||||
exposed, ready, err := solver.GetExposedEndpoints(routing.Spec.Endpoints, objs)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !ready {
|
||||
t.Errorf("The exposed endpoints should have been ready.")
|
||||
}
|
||||
|
||||
if len(exposed) != 1 {
|
||||
t.Errorf("There should have been 1 exposed endpoins but found %d", len(exposed))
|
||||
}
|
||||
|
||||
m1, ok := exposed["m1"]
|
||||
if !ok {
|
||||
t.Errorf("The exposed endpoints should have been defined on the m1 component.")
|
||||
}
|
||||
|
||||
if len(m1) != 3 {
|
||||
t.Fatalf("There should have been 3 endpoints for m1.")
|
||||
}
|
||||
|
||||
e1 := m1[0]
|
||||
if e1.Name != "e1" {
|
||||
t.Errorf("The first endpoint should have been e1 but is %s", e1.Name)
|
||||
|
|
@ -890,7 +1648,7 @@ func TestUsesIngressAnnotationsForWorkspaceEndpointIngresses(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
_, _, objs := getSpecObjectsForManager(t, mgr, subdomainDevWorkspaceRouting())
|
||||
_, _, objs := getSpecObjectsForManager(t, mgr, subdomainDevWorkspaceRouting(), userProfileSecret())
|
||||
|
||||
if len(objs.Ingresses) != 3 {
|
||||
t.Fatalf("Unexpected number of generated ingresses: %d", len(objs.Ingresses))
|
||||
|
|
@ -925,7 +1683,7 @@ func TestUsesCustomCertificateForWorkspaceEndpointIngresses(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
_, _, objs := getSpecObjectsForManager(t, mgr, subdomainDevWorkspaceRouting(), &corev1.Secret{
|
||||
_, _, objs := getSpecObjectsForManager(t, mgr, subdomainDevWorkspaceRouting(), userProfileSecret(), &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "tlsSecret",
|
||||
Namespace: "ns",
|
||||
|
|
@ -954,7 +1712,7 @@ func TestUsesCustomCertificateForWorkspaceEndpointIngresses(t *testing.T) {
|
|||
t.Fatalf("Unexpected number of host records on the TLS spec: %d", len(ingress.Spec.TLS[0].Hosts))
|
||||
}
|
||||
|
||||
if ingress.Spec.TLS[0].Hosts[0] != "wsid-1.almost.trivial" {
|
||||
if ingress.Spec.TLS[0].Hosts[0] != "username.my-workspace.e1.almost.trivial" {
|
||||
t.Errorf("Unexpected host name of the TLS spec: %s", ingress.Spec.TLS[0].Hosts[0])
|
||||
}
|
||||
|
||||
|
|
@ -972,7 +1730,7 @@ func TestUsesCustomCertificateForWorkspaceEndpointIngresses(t *testing.T) {
|
|||
t.Fatalf("Unexpected number of host records on the TLS spec: %d", len(ingress.Spec.TLS[0].Hosts))
|
||||
}
|
||||
|
||||
if ingress.Spec.TLS[0].Hosts[0] != "wsid-2.almost.trivial" {
|
||||
if ingress.Spec.TLS[0].Hosts[0] != "username.my-workspace.e2.almost.trivial" {
|
||||
t.Errorf("Unexpected host name of the TLS spec: %s", ingress.Spec.TLS[0].Hosts[0])
|
||||
}
|
||||
|
||||
|
|
@ -1001,7 +1759,7 @@ func TestUsesCustomCertificateForWorkspaceEndpointRoutes(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
_, _, objs := getSpecObjectsForManager(t, mgr, subdomainDevWorkspaceRouting(), &corev1.Secret{
|
||||
_, _, objs := getSpecObjectsForManager(t, mgr, subdomainDevWorkspaceRouting(), userProfileSecret(), &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "tlsSecret",
|
||||
Namespace: "ns",
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ func (e *IngressExposer) initFrom(ctx context.Context, cl client.Client, cluster
|
|||
return nil
|
||||
}
|
||||
|
||||
func (e *RouteExposer) getRouteForService(endpoint *EndpointInfo) routev1.Route {
|
||||
func (e *RouteExposer) getRouteForService(endpoint *EndpointInfo, endpointStrategy EndpointStrategy) routev1.Route {
|
||||
targetEndpoint := intstr.FromInt(int(endpoint.port))
|
||||
labels := labels.Merge(
|
||||
e.labels,
|
||||
|
|
@ -159,7 +159,7 @@ func (e *RouteExposer) getRouteForService(endpoint *EndpointInfo) routev1.Route
|
|||
OwnerReferences: endpoint.service.OwnerReferences,
|
||||
},
|
||||
Spec: routev1.RouteSpec{
|
||||
Host: hostName(endpoint.order, e.devWorkspaceID, e.baseDomain),
|
||||
Host: endpointStrategy.getHostname(endpoint, e.baseDomain),
|
||||
To: routev1.RouteTargetReference{
|
||||
Kind: "Service",
|
||||
Name: endpoint.service.Name,
|
||||
|
|
@ -185,8 +185,8 @@ func (e *RouteExposer) getRouteForService(endpoint *EndpointInfo) routev1.Route
|
|||
return route
|
||||
}
|
||||
|
||||
func (e *IngressExposer) getIngressForService(endpoint *EndpointInfo) networkingv1.Ingress {
|
||||
hostname := hostName(endpoint.order, e.devWorkspaceID, e.baseDomain)
|
||||
func (e *IngressExposer) getIngressForService(endpoint *EndpointInfo, endpointStrategy EndpointStrategy) networkingv1.Ingress {
|
||||
hostname := endpointStrategy.getHostname(endpoint, e.baseDomain)
|
||||
ingressPathType := networkingv1.PathTypeImplementationSpecific
|
||||
|
||||
ingress := networkingv1.Ingress{
|
||||
|
|
@ -239,10 +239,6 @@ func (e *IngressExposer) getIngressForService(endpoint *EndpointInfo) networking
|
|||
return ingress
|
||||
}
|
||||
|
||||
func hostName(order int, workspaceID string, baseDomain string) string {
|
||||
return fmt.Sprintf("%s-%d.%s", workspaceID, order, baseDomain)
|
||||
}
|
||||
|
||||
func routeAnnotations(machineName string, endpointName string) map[string]string {
|
||||
return map[string]string{
|
||||
defaults.ConfigAnnotationEndpointName: endpointName,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,113 @@
|
|||
//
|
||||
// Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
// This program and the accompanying materials are made
|
||||
// available under the terms of the Eclipse Public License 2.0
|
||||
// which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0
|
||||
//
|
||||
// Contributors:
|
||||
// Red Hat, Inc. - initial API and implementation
|
||||
//
|
||||
|
||||
package solver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
dwo "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
|
||||
)
|
||||
|
||||
// Interface for different workspace and endpoint url path strategies
|
||||
type EndpointStrategy interface {
|
||||
// get url paths for traefik config
|
||||
getPublicURLPrefix(port int32, uniqueEndpointName string, componentName string) string
|
||||
getMainWorkspacePathPrefix() string
|
||||
getEndpointPath(e *dwo.Endpoint, componentName string) (routeName string, path string)
|
||||
getEndpointPathPrefix(endpointPath string) string
|
||||
|
||||
// get hostname for routes / ingress
|
||||
getHostname(endpointInfo *EndpointInfo, baseDomain string) string
|
||||
}
|
||||
|
||||
// Main workspace URL is exposed on the following path:
|
||||
// <CHE_DOMAIN>/<USERNAME>/<WORKSPACE_NAME>/<PORT>/
|
||||
|
||||
// Public endpoints defined in the devfile are exposed on the following path via route or ingress:
|
||||
// <USERNAME>.<WORKSPACE_NAME>.<ENDPOINT_NAME>.<CLUSTER_INGRESS_DOMAIN>/<ENDPOINT_PATH>
|
||||
type UsernameWkspName struct {
|
||||
username string
|
||||
workspaceName string
|
||||
}
|
||||
|
||||
func (u UsernameWkspName) getPublicURLPrefix(port int32, uniqueEndpointName string, componentName string) string {
|
||||
if uniqueEndpointName == "" {
|
||||
return fmt.Sprintf(endpointURLPrefixPattern, u.username, u.workspaceName, port)
|
||||
}
|
||||
return fmt.Sprintf(uniqueEndpointURLPrefixPattern, u.username, u.workspaceName, uniqueEndpointName)
|
||||
}
|
||||
|
||||
func (u UsernameWkspName) getMainWorkspacePathPrefix() string {
|
||||
return fmt.Sprintf("/%s/%s", u.username, u.workspaceName)
|
||||
}
|
||||
|
||||
func (u UsernameWkspName) getEndpointPath(e *dwo.Endpoint, componentName string) (routeName string, path string) {
|
||||
if e.Attributes.GetString(uniqueEndpointAttributeName, nil) == "true" {
|
||||
routeName = e.Name
|
||||
} else {
|
||||
routeName = strconv.Itoa(e.TargetPort)
|
||||
}
|
||||
path = fmt.Sprintf("/%s", routeName)
|
||||
|
||||
return routeName, path
|
||||
}
|
||||
|
||||
func (u UsernameWkspName) getEndpointPathPrefix(endpointPath string) string {
|
||||
return fmt.Sprintf("/%s/%s%s", u.username, u.workspaceName, endpointPath)
|
||||
}
|
||||
|
||||
func (u UsernameWkspName) getHostname(endpointInfo *EndpointInfo, baseDomain string) string {
|
||||
return fmt.Sprintf("%s.%s.%s.%s", u.username, u.workspaceName, endpointInfo.endpointName, baseDomain)
|
||||
}
|
||||
|
||||
// Main workspace URL is exposed on the following path:
|
||||
// <CHE_DOMAIN>/<WORKSPACE_ID>/<COMPONENT_NAME>/<PORT>/
|
||||
|
||||
// Public endpoints defined in the devfile are exposed on the following path via route or ingress:
|
||||
// <WORKSPACE_ID>-<ENDPOINT_ORDER_NUMBER>.<CLUSTER_INGRESS_DOMAIN>/<ENDPOINT_PATH>
|
||||
type Legacy struct {
|
||||
workspaceID string
|
||||
}
|
||||
|
||||
func (l Legacy) getPublicURLPrefix(port int32, uniqueEndpointName string, componentName string) string {
|
||||
if uniqueEndpointName == "" {
|
||||
return fmt.Sprintf(endpointURLPrefixPattern, l.workspaceID, componentName, port)
|
||||
}
|
||||
return fmt.Sprintf(uniqueEndpointURLPrefixPattern, l.workspaceID, componentName, uniqueEndpointName)
|
||||
}
|
||||
|
||||
func (l Legacy) getMainWorkspacePathPrefix() string {
|
||||
return fmt.Sprintf("/%s", l.workspaceID)
|
||||
}
|
||||
|
||||
func (l Legacy) getEndpointPath(e *dwo.Endpoint, componentName string) (routeName string, path string) {
|
||||
if e.Attributes.GetString(uniqueEndpointAttributeName, nil) == "true" {
|
||||
// if endpoint is unique, we're exposing on /componentName/<endpoint-name>
|
||||
routeName = e.Name
|
||||
} else {
|
||||
// if endpoint is NOT unique, we're exposing on /componentName/<port-number>
|
||||
routeName = strconv.Itoa(e.TargetPort)
|
||||
}
|
||||
path = fmt.Sprintf("/%s/%s", componentName, routeName)
|
||||
|
||||
return routeName, path
|
||||
}
|
||||
|
||||
func (l Legacy) getEndpointPathPrefix(endpointPath string) string {
|
||||
return fmt.Sprintf("/%s%s", l.workspaceID, endpointPath)
|
||||
}
|
||||
|
||||
func (l Legacy) getHostname(endpointInfo *EndpointInfo, baseDomain string) string {
|
||||
return fmt.Sprintf("%s-%d.%s", l.workspaceID, endpointInfo.order, baseDomain)
|
||||
}
|
||||
Loading…
Reference in New Issue