package testutils import ( "encoding/json" ingressv1alpha1 "github.com/ngrok/ngrok-operator/api/ingress/v1alpha1" ngrokv1alpha1 "github.com/ngrok/ngrok-operator/api/ngrok/v1alpha1" corev1 "k8s.io/api/core/v1" netv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/rand" "k8s.io/utils/ptr" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" ) func NewTestIngressClass(name string, isDefault bool, isNgrok bool) *netv1.IngressClass { i := netv1.IngressClass{ ObjectMeta: metav1.ObjectMeta{ Name: name, Labels: map[string]string{ "app.kubernetes.io/component": "controller", }, }, } if isNgrok { i.Spec.Controller = "k8s.ngrok.com/ingress-controller" } else { i.Spec.Controller = "kubernetes.io/ingress-other" } if isDefault { i.Annotations = map[string]string{ "ingressclass.kubernetes.io/is-default-class": "true", // TODO: Move this into a utility for ingress classes } } return &i } func NewTestIngressV1WithClass(name string, namespace string, ingressClass string) *netv1.Ingress { i := NewTestIngressV1(name, namespace) i.Spec.IngressClassName = &ingressClass return i } func NewTestIngressV1(name string, namespace string) *netv1.Ingress { return &netv1.Ingress{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, }, Spec: netv1.IngressSpec{ Rules: []netv1.IngressRule{ { Host: "example.com", IngressRuleValue: netv1.IngressRuleValue{ HTTP: &netv1.HTTPIngressRuleValue{ Paths: []netv1.HTTPIngressPath{ { Path: "/", Backend: netv1.IngressBackend{ Service: &netv1.IngressServiceBackend{ Name: "example", Port: netv1.ServiceBackendPort{ Number: 80, }, }, }, }, }, }, }, }, }, }, } } func NewTestServiceV1(name string, namespace string) *corev1.Service { return &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, }, Spec: corev1.ServiceSpec{ Ports: []corev1.ServicePort{ { Name: "http", Protocol: "TCP", Port: 80, TargetPort: intstr.FromString("http"), }, }, }, } } func NewDomainV1(name string, namespace string) *ingressv1alpha1.Domain { return &ingressv1alpha1.Domain{ ObjectMeta: metav1.ObjectMeta{ Name: ingressv1alpha1.HyphenatedDomainNameFromURL(name), Namespace: namespace, }, Spec: ingressv1alpha1.DomainSpec{ Domain: name, }, } } // RandomName generates a random name with the given prefix. The random part is 5 characters long. // This is useful for generating unique names for resources in tests. func RandomName(prefix string) string { return prefix + "-" + rand.String(5) } // RandomURL generates a random URL. func RandomURL() string { return "https://" + RandomName("test-url") + ".ngrok.io" } // NewGatewayClass creates a new GatewayClass with a random name to be used in tests. If // isManaged is true, the controller name will be set to the ngrok gateway controller name. // If isManaged is false, the controller name will be set to a different value. func NewGatewayClass(isManaged bool) *gatewayv1.GatewayClass { var controllerName gatewayv1.GatewayController = "ngrok.com/gateway-controller" if !isManaged { controllerName = "k8s.io/some-other-controller" } return &gatewayv1.GatewayClass{ ObjectMeta: metav1.ObjectMeta{ Name: RandomName("gateway-class"), }, Spec: gatewayv1.GatewayClassSpec{ ControllerName: controllerName, }, } } func NewGateway(name string, namespace string) gatewayv1.Gateway { return gatewayv1.Gateway{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, }, Spec: gatewayv1.GatewaySpec{ GatewayClassName: "test-gatewayclass", Listeners: []gatewayv1.Listener{ { Hostname: ptr.To(gatewayv1.Hostname("example.com")), Name: "http", Port: 80, Protocol: gatewayv1.HTTPProtocolType, }, }, }, } } func NewHTTPRoute(name string, namespace string) gatewayv1.HTTPRoute { return gatewayv1.HTTPRoute{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, }, Spec: gatewayv1.HTTPRouteSpec{ Rules: []gatewayv1.HTTPRouteRule{ { Matches: []gatewayv1.HTTPRouteMatch{ { Path: &gatewayv1.HTTPPathMatch{ Type: ptr.To(gatewayv1.PathMatchPathPrefix), Value: ptr.To("/"), }, }, }, }, }, }, } } func NewTLSRoute(name string, namespace string) gatewayv1alpha2.TLSRoute { return gatewayv1alpha2.TLSRoute{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, }, Spec: gatewayv1alpha2.TLSRouteSpec{ Rules: []gatewayv1alpha2.TLSRouteRule{ { BackendRefs: []gatewayv1alpha2.BackendRef{ { BackendObjectReference: gatewayv1alpha2.BackendObjectReference{ Name: "test-service", Port: ptr.To(gatewayv1.PortNumber(8000)), }, }, }, }, }, }, } } func NewTCPRoute(name string, namespace string) gatewayv1alpha2.TCPRoute { return gatewayv1alpha2.TCPRoute{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, }, Spec: gatewayv1alpha2.TCPRouteSpec{ Rules: []gatewayv1alpha2.TCPRouteRule{ { BackendRefs: []gatewayv1alpha2.BackendRef{ { BackendObjectReference: gatewayv1alpha2.BackendObjectReference{ Name: "tcp-service", Port: ptr.To(gatewayv1.PortNumber(8000)), }, }, }, }, }, }, } } func NewReferenceGrant(name string, namespace string) gatewayv1beta1.ReferenceGrant { return gatewayv1beta1.ReferenceGrant{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, }, Spec: gatewayv1beta1.ReferenceGrantSpec{ From: []gatewayv1beta1.ReferenceGrantFrom{ { Group: "gateway.networking.k8s.io", Kind: "HTTPRoute", Namespace: gatewayv1beta1.Namespace("other-namespace"), }, }, To: []gatewayv1beta1.ReferenceGrantTo{ { Group: "core", Kind: "Service", }, }, }, } } func NewTestNgrokTrafficPolicy(name string, namespace string, policyStr string) ngrokv1alpha1.NgrokTrafficPolicy { return ngrokv1alpha1.NgrokTrafficPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, }, Spec: ngrokv1alpha1.NgrokTrafficPolicySpec{ Policy: json.RawMessage(policyStr), }, } } type CloudEndpointOpt func(*ngrokv1alpha1.CloudEndpoint) // NewCloudEndpoint creates a new CloudEndpoint with the given name and namespace. // The URL is set to a random name for testing purposes. // You can pass additional options to customize the CloudEndpoint further. // Example usage: // // NewCloudEndpoint func NewCloudEndpoint(opts ...CloudEndpointOpt) *ngrokv1alpha1.CloudEndpoint { clep := &ngrokv1alpha1.CloudEndpoint{ ObjectMeta: metav1.ObjectMeta{ Name: RandomName("cloud-endpoint"), Namespace: RandomName("namespace"), }, Spec: ngrokv1alpha1.CloudEndpointSpec{ URL: RandomName("url"), }, } for _, opt := range opts { opt(clep) } return clep } type AgentEndpointOpt func(*ngrokv1alpha1.AgentEndpoint) func NewAgentEndpoint(opts ...AgentEndpointOpt) *ngrokv1alpha1.AgentEndpoint { aep := &ngrokv1alpha1.AgentEndpoint{ ObjectMeta: metav1.ObjectMeta{ Name: RandomName("agent-endpoint"), Namespace: RandomName("namespace"), }, Spec: ngrokv1alpha1.AgentEndpointSpec{ URL: RandomURL(), }, } for _, opt := range opts { opt(aep) } return aep }