154 lines
5.9 KiB
Go
154 lines
5.9 KiB
Go
package controller
|
|
|
|
import (
|
|
"testing"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
mikrotikv1alpha1 "code.brunner.ninja/feedc0de/mikrotik-operator/api/v1alpha1"
|
|
"code.brunner.ninja/feedc0de/mikrotik-operator/internal/routeros"
|
|
)
|
|
|
|
func TestDesiredRules(t *testing.T) {
|
|
router := &mikrotikv1alpha1.MikroTikRouter{
|
|
ObjectMeta: metav1.ObjectMeta{Name: "edge"},
|
|
Spec: mikrotikv1alpha1.MikroTikRouterSpec{AllowedNamespaces: []string{"games"}},
|
|
}
|
|
service := corev1.Service{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Namespace: "games", Name: "factorio",
|
|
Annotations: map[string]string{
|
|
AnnotationRouter: "edge", AnnotationServicePort: "game",
|
|
AnnotationDestinationPort: "40000", AnnotationInInterfaceList: "WAN",
|
|
},
|
|
},
|
|
Spec: corev1.ServiceSpec{
|
|
Type: corev1.ServiceTypeLoadBalancer,
|
|
Ports: []corev1.ServicePort{
|
|
{Name: "game", Port: 34197, Protocol: corev1.ProtocolUDP},
|
|
{Name: "rcon", Port: 27015, Protocol: corev1.ProtocolTCP},
|
|
},
|
|
},
|
|
Status: corev1.ServiceStatus{LoadBalancer: corev1.LoadBalancerStatus{Ingress: []corev1.LoadBalancerIngress{
|
|
{IP: "2001:db8::1"}, {IP: "192.168.0.17"},
|
|
}}},
|
|
}
|
|
|
|
rules, preserve, issues := DesiredRules(router, []corev1.Service{service})
|
|
if len(issues) != 0 {
|
|
t.Fatalf("unexpected issues: %#v", issues)
|
|
}
|
|
if len(preserve) != 0 {
|
|
t.Fatalf("unexpected preserve set: %#v", preserve)
|
|
}
|
|
if len(rules) != 1 {
|
|
t.Fatalf("got %d rules, want 1", len(rules))
|
|
}
|
|
want := routeros.Rule{
|
|
Comment: routeros.ManagedComment("games", "factorio"), Protocol: "udp",
|
|
DestinationPort: "40000", InInterfaceList: "WAN",
|
|
ToAddress: "192.168.0.17", ToPort: "34197",
|
|
}
|
|
if rules[0] != want {
|
|
t.Fatalf("rule = %#v, want %#v", rules[0], want)
|
|
}
|
|
}
|
|
|
|
func TestDesiredRulesPreservesRuleWhileLoadBalancerIsPending(t *testing.T) {
|
|
router := &mikrotikv1alpha1.MikroTikRouter{
|
|
ObjectMeta: metav1.ObjectMeta{Name: "edge"},
|
|
Spec: mikrotikv1alpha1.MikroTikRouterSpec{AllowedNamespaces: []string{"games"}},
|
|
}
|
|
service := corev1.Service{
|
|
ObjectMeta: metav1.ObjectMeta{Namespace: "games", Name: "factorio", Annotations: map[string]string{AnnotationRouter: "edge"}},
|
|
Spec: corev1.ServiceSpec{Type: corev1.ServiceTypeLoadBalancer, Ports: []corev1.ServicePort{{Port: 34197, Protocol: corev1.ProtocolUDP}}},
|
|
}
|
|
rules, preserve, issues := DesiredRules(router, []corev1.Service{service})
|
|
if len(rules) != 0 || len(issues) != 1 {
|
|
t.Fatalf("rules=%#v issues=%#v", rules, issues)
|
|
}
|
|
if _, ok := preserve[routeros.ManagedComment("games", "factorio")]; !ok {
|
|
t.Fatal("pending rule was not preserved")
|
|
}
|
|
}
|
|
|
|
func TestDesiredRulesDoesNotHonorUnlistedNamespace(t *testing.T) {
|
|
router := &mikrotikv1alpha1.MikroTikRouter{
|
|
ObjectMeta: metav1.ObjectMeta{Name: "edge"},
|
|
Spec: mikrotikv1alpha1.MikroTikRouterSpec{AllowedNamespaces: []string{"trusted"}},
|
|
}
|
|
service := corev1.Service{ObjectMeta: metav1.ObjectMeta{
|
|
Namespace: "untrusted", Name: "bad", Annotations: map[string]string{AnnotationRouter: "edge"},
|
|
}}
|
|
rules, preserve, issues := DesiredRules(router, []corev1.Service{service})
|
|
if len(rules) != 0 || len(preserve) != 0 || len(issues) != 0 {
|
|
t.Fatalf("unlisted namespace affected reconciliation: rules=%#v preserve=%#v issues=%#v", rules, preserve, issues)
|
|
}
|
|
}
|
|
|
|
func TestDesiredRulesSupportsNamedForwardingsAndRanges(t *testing.T) {
|
|
router := &mikrotikv1alpha1.MikroTikRouter{
|
|
ObjectMeta: metav1.ObjectMeta{Name: "edge"},
|
|
Spec: mikrotikv1alpha1.MikroTikRouterSpec{AllowedNamespaces: []string{"*"}},
|
|
}
|
|
service := corev1.Service{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Namespace: "coturn", Name: "coturn",
|
|
Annotations: map[string]string{
|
|
AnnotationRouter: "edge",
|
|
AnnotationForwardings: `[
|
|
{"name":"turn","servicePort":"turn","dstAddressList":"WANs"},
|
|
{"name":"relay","servicePortRange":"49160-49162","dstAddressList":"WANs"}
|
|
]`,
|
|
},
|
|
},
|
|
Spec: corev1.ServiceSpec{
|
|
Type: corev1.ServiceTypeLoadBalancer,
|
|
Ports: []corev1.ServicePort{
|
|
{Name: "turn", Port: 3478, Protocol: corev1.ProtocolUDP},
|
|
{Name: "relay-49160", Port: 49160, Protocol: corev1.ProtocolUDP},
|
|
{Name: "relay-49161", Port: 49161, Protocol: corev1.ProtocolUDP},
|
|
{Name: "relay-49162", Port: 49162, Protocol: corev1.ProtocolUDP},
|
|
},
|
|
},
|
|
Status: corev1.ServiceStatus{LoadBalancer: corev1.LoadBalancerStatus{Ingress: []corev1.LoadBalancerIngress{{IP: "192.168.0.19"}}}},
|
|
}
|
|
|
|
rules, preserve, issues := DesiredRules(router, []corev1.Service{service})
|
|
if len(issues) != 0 || len(preserve) != 0 {
|
|
t.Fatalf("issues=%#v preserve=%#v", issues, preserve)
|
|
}
|
|
if len(rules) != 2 {
|
|
t.Fatalf("got %d rules, want 2", len(rules))
|
|
}
|
|
want := []routeros.Rule{
|
|
{Comment: routeros.ManagedForwardingComment("coturn", "coturn", "turn"), Protocol: "udp", DestinationPort: "3478", DestinationList: "WANs", ToAddress: "192.168.0.19", ToPort: "3478"},
|
|
{Comment: routeros.ManagedForwardingComment("coturn", "coturn", "relay"), Protocol: "udp", DestinationPort: "49160-49162", DestinationList: "WANs", ToAddress: "192.168.0.19", ToPort: "49160-49162"},
|
|
}
|
|
for i := range want {
|
|
if rules[i] != want[i] {
|
|
t.Fatalf("rule[%d] = %#v, want %#v", i, rules[i], want[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDesiredRulesPreservesAllNamedRulesForInvalidJSON(t *testing.T) {
|
|
router := &mikrotikv1alpha1.MikroTikRouter{
|
|
ObjectMeta: metav1.ObjectMeta{Name: "edge"},
|
|
Spec: mikrotikv1alpha1.MikroTikRouterSpec{AllowedNamespaces: []string{"*"}},
|
|
}
|
|
service := corev1.Service{ObjectMeta: metav1.ObjectMeta{
|
|
Namespace: "default", Name: "traefik", Annotations: map[string]string{
|
|
AnnotationRouter: "edge", AnnotationForwardings: `[{broken]`,
|
|
},
|
|
}}
|
|
rules, preserve, issues := DesiredRules(router, []corev1.Service{service})
|
|
if len(rules) != 0 || len(issues) != 1 {
|
|
t.Fatalf("rules=%#v issues=%#v", rules, issues)
|
|
}
|
|
if _, ok := preserve[routeros.ManagedComment("default", "traefik")+"/"]; !ok {
|
|
t.Fatalf("named forwarding prefix was not preserved: %#v", preserve)
|
|
}
|
|
}
|