-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
allow to configure specific annotations #1070
base: main
Are you sure you want to change the base?
Changes from all commits
1000cd3
b5023ec
4321e9c
240e0c9
a8992c0
e28c740
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,20 +22,33 @@ import ( | |
"github.com/devfile/devworkspace-operator/pkg/infrastructure" | ||
) | ||
|
||
var routeAnnotations = func(endpointName string) map[string]string { | ||
return map[string]string{ | ||
"haproxy.router.openshift.io/rewrite-target": "/", | ||
constants.DevWorkspaceEndpointNameAnnotation: endpointName, | ||
func appendMap[K, V comparable](dst map[K]V, m map[K]V) { | ||
for k, v := range m { | ||
dst[k] = v | ||
} | ||
} | ||
|
||
var nginxIngressAnnotations = func(endpointName string) map[string]string { | ||
return map[string]string{ | ||
"kubernetes.io/ingress.class": "nginx", | ||
"nginx.ingress.kubernetes.io/rewrite-target": "/", | ||
"nginx.ingress.kubernetes.io/ssl-redirect": "false", | ||
var routeAnnotations = map[string]string{ | ||
"haproxy.router.openshift.io/rewrite-target": "/", | ||
} | ||
|
||
var nginxIngressAnnotations = map[string]string{ | ||
"kubernetes.io/ingress.class": "nginx", | ||
"nginx.ingress.kubernetes.io/rewrite-target": "/", | ||
"nginx.ingress.kubernetes.io/ssl-redirect": "false", | ||
} | ||
|
||
func createAnnotations(endpointName string, routingAnnotations map[string]string, defaultAnnotations map[string]string) map[string]string { | ||
annotations := map[string]string{ | ||
constants.DevWorkspaceEndpointNameAnnotation: endpointName, | ||
} | ||
|
||
if routingAnnotations == nil || len(routingAnnotations) == 0 { | ||
appendMap(annotations, defaultAnnotations) | ||
} else { | ||
appendMap(annotations, routingAnnotations) | ||
} | ||
return annotations | ||
Comment on lines
-32
to
+51
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A better approach for setting a default value if the configuration is unspecified would be similar to what we do in the config package -- this avoids needing functions that take an optional value and a default. |
||
} | ||
|
||
// Basic solver exposes endpoints without any authentication | ||
|
@@ -67,12 +80,13 @@ func (s *BasicSolver) GetSpecObjects(routing *controllerv1alpha1.DevWorkspaceRou | |
services := getServicesForEndpoints(spec.Endpoints, workspaceMeta) | ||
services = append(services, GetDiscoverableServicesForEndpoints(spec.Endpoints, workspaceMeta)...) | ||
routingObjects.Services = services | ||
// TODO: Use workspace-scoped routing annotations to allow overriding | ||
routingAnnotations := config.GetGlobalConfig().Routing.Annotations | ||
gbonnefille marked this conversation as resolved.
Show resolved
Hide resolved
Comment on lines
+83
to
+84
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It will likely not be possible to get workspace-scoped annotations, as this is within the context of the DevWorkspaceRouting reconciler. In fact, we should avoid using In an ideal world, the configuration of DWO is propagated into the DevWorkspaceRouting CR directly in some way. However, some choices made in the past make this very difficult -- likely the only way to do this is to serialize the map to JSON and add it as an annotation on the routing CR. |
||
if infrastructure.IsOpenShift() { | ||
routingObjects.Routes = getRoutesForSpec(routingSuffix, spec.Endpoints, workspaceMeta) | ||
routingObjects.Routes = getRoutesForSpec(routingSuffix, spec.Endpoints, workspaceMeta, routingAnnotations) | ||
} else { | ||
routingObjects.Ingresses = getIngressesForSpec(routingSuffix, spec.Endpoints, workspaceMeta) | ||
routingObjects.Ingresses = getIngressesForSpec(routingSuffix, spec.Endpoints, workspaceMeta, routingAnnotations) | ||
} | ||
|
||
return routingObjects, nil | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -153,33 +153,33 @@ func getServicesForEndpoints(endpoints map[string]controllerv1alpha1.EndpointLis | |
} | ||
} | ||
|
||
func getRoutesForSpec(routingSuffix string, endpoints map[string]controllerv1alpha1.EndpointList, meta DevWorkspaceMetadata) []routeV1.Route { | ||
func getRoutesForSpec(routingSuffix string, endpoints map[string]controllerv1alpha1.EndpointList, meta DevWorkspaceMetadata, annotations map[string]string) []routeV1.Route { | ||
var routes []routeV1.Route | ||
for _, machineEndpoints := range endpoints { | ||
for _, endpoint := range machineEndpoints { | ||
if endpoint.Exposure != controllerv1alpha1.PublicEndpointExposure { | ||
continue | ||
} | ||
routes = append(routes, getRouteForEndpoint(routingSuffix, endpoint, meta)) | ||
routes = append(routes, getRouteForEndpoint(routingSuffix, endpoint, meta, annotations)) | ||
} | ||
} | ||
return routes | ||
} | ||
|
||
func getIngressesForSpec(routingSuffix string, endpoints map[string]controllerv1alpha1.EndpointList, meta DevWorkspaceMetadata) []networkingv1.Ingress { | ||
func getIngressesForSpec(routingSuffix string, endpoints map[string]controllerv1alpha1.EndpointList, meta DevWorkspaceMetadata, annotations map[string]string) []networkingv1.Ingress { | ||
var ingresses []networkingv1.Ingress | ||
for _, machineEndpoints := range endpoints { | ||
for _, endpoint := range machineEndpoints { | ||
if endpoint.Exposure != controllerv1alpha1.PublicEndpointExposure { | ||
continue | ||
} | ||
ingresses = append(ingresses, getIngressForEndpoint(routingSuffix, endpoint, meta)) | ||
ingresses = append(ingresses, getIngressForEndpoint(routingSuffix, endpoint, meta, annotations)) | ||
} | ||
} | ||
return ingresses | ||
} | ||
|
||
func getRouteForEndpoint(routingSuffix string, endpoint controllerv1alpha1.Endpoint, meta DevWorkspaceMetadata) routeV1.Route { | ||
func getRouteForEndpoint(routingSuffix string, endpoint controllerv1alpha1.Endpoint, meta DevWorkspaceMetadata, annotations map[string]string) routeV1.Route { | ||
targetEndpoint := intstr.FromInt(endpoint.TargetPort) | ||
endpointName := common.EndpointName(endpoint.Name) | ||
return routeV1.Route{ | ||
|
@@ -189,7 +189,7 @@ func getRouteForEndpoint(routingSuffix string, endpoint controllerv1alpha1.Endpo | |
Labels: map[string]string{ | ||
constants.DevWorkspaceIDLabel: meta.DevWorkspaceId, | ||
}, | ||
Annotations: routeAnnotations(endpointName), | ||
Annotations: createAnnotations(endpoint.Name, annotations, routeAnnotations), | ||
}, | ||
Spec: routeV1.RouteSpec{ | ||
Host: common.WorkspaceHostname(routingSuffix, meta.DevWorkspaceId), | ||
|
@@ -209,7 +209,7 @@ func getRouteForEndpoint(routingSuffix string, endpoint controllerv1alpha1.Endpo | |
} | ||
} | ||
|
||
func getIngressForEndpoint(routingSuffix string, endpoint controllerv1alpha1.Endpoint, meta DevWorkspaceMetadata) networkingv1.Ingress { | ||
func getIngressForEndpoint(routingSuffix string, endpoint controllerv1alpha1.Endpoint, meta DevWorkspaceMetadata, annotations map[string]string) networkingv1.Ingress { | ||
endpointName := common.EndpointName(endpoint.Name) | ||
hostname := common.EndpointHostname(routingSuffix, meta.DevWorkspaceId, endpointName, endpoint.TargetPort) | ||
ingressPathType := networkingv1.PathTypeImplementationSpecific | ||
|
@@ -220,7 +220,7 @@ func getIngressForEndpoint(routingSuffix string, endpoint controllerv1alpha1.End | |
Labels: map[string]string{ | ||
constants.DevWorkspaceIDLabel: meta.DevWorkspaceId, | ||
}, | ||
Annotations: nginxIngressAnnotations(endpoint.Name), | ||
Annotations: createAnnotations(endpoint.Name, annotations, nginxIngressAnnotations), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure about this approach; there's a pretty distant link between where if routingAnnotations == nil || len(routingAnnotations) == 0 {
appendMap(annotations, defaultAnnotations)
} else {
appendMap(annotations, routingAnnotations)
} |
||
}, | ||
Spec: networkingv1.IngressSpec{ | ||
Rules: []networkingv1.IngressRule{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package solvers | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/devfile/devworkspace-operator/apis/controller/v1alpha1" | ||
"github.com/google/go-cmp/cmp" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestGetRouteForEndpointAnnotations(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
|
||
annotations map[string]string | ||
|
||
expectedAnnotations map[string]string | ||
}{ | ||
{ | ||
name: "Gets default OpenShift route annotation when annotations aren't defined", | ||
|
||
annotations: nil, | ||
|
||
expectedAnnotations: map[string]string{ | ||
"controller.devfile.io/endpoint_name": "Endpoint", | ||
"haproxy.router.openshift.io/rewrite-target": "/", | ||
}, | ||
}, | ||
{ | ||
name: "Gets default OpenShift route annotation when annotations are empty", | ||
|
||
annotations: map[string]string{}, | ||
|
||
expectedAnnotations: map[string]string{ | ||
"controller.devfile.io/endpoint_name": "Endpoint", | ||
"haproxy.router.openshift.io/rewrite-target": "/", | ||
}, | ||
}, | ||
{ | ||
name: "Gets default OpenShift route annotation when annotations are defined", | ||
|
||
annotations: map[string]string{ | ||
"example.com/extra": "val", | ||
}, | ||
|
||
expectedAnnotations: map[string]string{ | ||
"controller.devfile.io/endpoint_name": "Endpoint", | ||
"example.com/extra": "val", | ||
}, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
route := getRouteForEndpoint("routingSuffix", v1alpha1.Endpoint{Name: "Endpoint"}, DevWorkspaceMetadata{DevWorkspaceId: "WorkspaceTest"}, tt.annotations) | ||
assert.Equal(t, tt.expectedAnnotations, route.Annotations, "Annotations should match: Diff: %s", cmp.Diff(tt.expectedAnnotations, route.Annotations)) | ||
}) | ||
} | ||
} | ||
|
||
func TestGetIngressForEndpointAnnotations(t *testing.T) { | ||
gbonnefille marked this conversation as resolved.
Show resolved
Hide resolved
|
||
tests := []struct { | ||
name string | ||
|
||
annotations map[string]string | ||
|
||
expectedAnnotations map[string]string | ||
}{ | ||
{ | ||
name: "Gets default Kubernetes ingress annotation when annotations aren't defined", | ||
|
||
annotations: nil, | ||
|
||
expectedAnnotations: map[string]string{ | ||
"controller.devfile.io/endpoint_name": "Endpoint", | ||
"kubernetes.io/ingress.class": "nginx", | ||
"nginx.ingress.kubernetes.io/rewrite-target": "/", | ||
"nginx.ingress.kubernetes.io/ssl-redirect": "false", | ||
}, | ||
}, | ||
{ | ||
name: "Gets default Kubernetes ingress annotation when annotations are empty", | ||
|
||
annotations: map[string]string{}, | ||
|
||
expectedAnnotations: map[string]string{ | ||
"controller.devfile.io/endpoint_name": "Endpoint", | ||
"kubernetes.io/ingress.class": "nginx", | ||
"nginx.ingress.kubernetes.io/rewrite-target": "/", | ||
"nginx.ingress.kubernetes.io/ssl-redirect": "false", | ||
}, | ||
}, | ||
{ | ||
name: "Gets default Kubernetes ingress annotation when annotations are defined", | ||
|
||
annotations: map[string]string{ | ||
"kubernetes.io/ingress.class": "traefik", | ||
}, | ||
|
||
expectedAnnotations: map[string]string{ | ||
"controller.devfile.io/endpoint_name": "Endpoint", | ||
"kubernetes.io/ingress.class": "traefik", | ||
}, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
ingress := getIngressForEndpoint("routingSuffix", v1alpha1.Endpoint{Name: "Endpoint"}, DevWorkspaceMetadata{DevWorkspaceId: "WorkspaceTest"}, tt.annotations) | ||
assert.Equal(t, tt.expectedAnnotations, ingress.Annotations, "Annotations should match: Diff: %s", cmp.Diff(tt.expectedAnnotations, ingress.Annotations)) | ||
}) | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might need to find a more descriptive name here -- perhaps
RoutingAnnotations
? I feel that annotations is too generic here (though I'm open to being swayed on this one).