Files
Server/portforwarding/portforwarding.go
2025-12-29 16:42:49 +01:00

126 lines
4.1 KiB
Go

package portforwarding
import (
"context"
"time"
"connectrpc.com/connect"
"git.kocoder.xyz/kocoder/portforwarder/api/types/v1alpha1"
csv1 "git.kocoder.xyz/kocoder/portforwarder/clientset/v1alpha1"
portforwardingv1 "git.kocoder.xyz/kocoder/portforwarder/gen/portforwarding"
"git.kocoder.xyz/kocoder/portforwarder/gen/portforwarding/portforwardingv1connect"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type PortforwardingService struct {
ir csv1.IngressrouteInterface
ns string
svc string
basedomain string
tlssecret string
}
func NewPortforwardingService(ingressroutehandler csv1.IngressrouteInterface, namespace string, servicename string, basedomain string, secretname string) portforwardingv1connect.PortForwardingServiceHandler {
return &PortforwardingService{ir: ingressroutehandler, ns: namespace, svc: servicename, basedomain: basedomain, tlssecret: secretname}
}
// CreatePortforwarding implements portforwardingv1connect.PortForwardingServiceHandler.
func (p *PortforwardingService) CreatePortforwarding(ctx context.Context, req *portforwardingv1.CreatePortforwardingRequest) (*portforwardingv1.CreatePortforwardingResponse, error) {
ir := &v1alpha1.IngressRoute{
ObjectMeta: v1.ObjectMeta{
Name: req.Alias,
Labels: map[string]string{"alias": req.Alias, "mangedBy": "heek-portforwarder"},
},
Spec: v1alpha1.IngressRouteSpec{
EntryPoints: []string{"websecure", "web"},
Routes: []v1alpha1.Route{
{
Kind: "Rule",
Match: "Host(`" + req.Alias + p.basedomain + "`)",
Services: []v1alpha1.Service{
{
Kind: "Service",
Name: p.svc,
Namespace: p.ns,
PassHostHeader: true,
Port: int(req.TargetPort),
ResponseForwarding: v1alpha1.ResponseForwarding{FlushInterval: "10ms"},
Scheme: "http",
Sticky: v1alpha1.Sticky{Cookie: v1alpha1.Cookie{HttpOnly: false, Name: "", Secure: false}},
Strategy: "wrr",
Weight: 10,
},
},
Middlewares: []v1alpha1.Middleware{},
Observability: v1alpha1.Observability{AccessLogs: false, Metrics: false, Tracing: false},
Priority: 10,
},
},
},
}
downstreamContext, cancel := context.WithDeadline(ctx, time.Now().Add(time.Second*2))
ir, err := p.ir.Create(downstreamContext, ir)
cancel()
if err != nil {
return nil, connect.NewError(connect.CodeInternal, err)
}
return &portforwardingv1.CreatePortforwardingResponse{
Success: true,
Pf: &portforwardingv1.Portforwarding{
Alias: ir.Name,
TargetPort: int32(ir.Spec.Routes[0].Services[0].Port),
},
}, nil
}
// DeletePortforwarding implements portforwardingv1connect.PortForwardingServiceHandler.
func (p *PortforwardingService) DeletePortforwarding(ctx context.Context, req *portforwardingv1.DeletePortforwardingRequest) (*portforwardingv1.DeletePortforwardingResponse, error) {
downstreamContext, cancel := context.WithDeadline(ctx, time.Now().Add(time.Second*2))
opts := *v1.NewDeleteOptions(1)
err := p.ir.Delete(downstreamContext, req.Alias, opts)
cancel()
if err != nil {
return nil, connect.NewError(connect.CodeInternal, err)
}
return &portforwardingv1.DeletePortforwardingResponse{
Success: true,
}, nil
}
// ListPortforwardings implements portforwardingv1connect.PortForwardingServiceHandler.
func (p *PortforwardingService) ListPortforwardings(ctx context.Context, req *portforwardingv1.ListPortforwardingsRequest) (*portforwardingv1.ListPortforwardingsResponse, error) {
downstreamContext, cancel := context.WithDeadline(ctx, time.Now().Add(time.Second*2))
opts := v1.ListOptions{}
res, err := p.ir.List(downstreamContext, opts)
cancel()
if err != nil {
return nil, connect.NewError(connect.CodeInternal, err)
}
items := res.Items
pf := make([]*portforwardingv1.Portforwarding, len(items))
for i, v := range items {
pf[i] = &portforwardingv1.Portforwarding{
Alias: v.Name,
TargetPort: int32(v.Spec.Routes[0].Services[0].Port),
}
}
return &portforwardingv1.ListPortforwardingsResponse{
Pf: pf,
}, nil
}