|
| 1 | +package aga |
| 2 | + |
| 3 | +import ( |
| 4 | + "context" |
| 5 | + "fmt" |
| 6 | + "github.com/pkg/errors" |
| 7 | + agaapi "sigs.k8s.io/aws-load-balancer-controller/apis/aga/v1beta1" |
| 8 | + agamodel "sigs.k8s.io/aws-load-balancer-controller/pkg/model/aga" |
| 9 | + "sigs.k8s.io/aws-load-balancer-controller/pkg/model/core" |
| 10 | +) |
| 11 | + |
| 12 | +// listenerBuilder builds Listener model resources |
| 13 | +type listenerBuilder interface { |
| 14 | + Build(ctx context.Context, stack core.Stack, accelerator *agamodel.Accelerator, listeners []agaapi.GlobalAcceleratorListener) ([]*agamodel.Listener, error) |
| 15 | +} |
| 16 | + |
| 17 | +// NewListenerBuilder constructs new listenerBuilder |
| 18 | +func NewListenerBuilder() listenerBuilder { |
| 19 | + return &defaultListenerBuilder{} |
| 20 | +} |
| 21 | + |
| 22 | +var _ listenerBuilder = &defaultListenerBuilder{} |
| 23 | + |
| 24 | +type defaultListenerBuilder struct{} |
| 25 | + |
| 26 | +// Build builds Listener model resources |
| 27 | +func (b *defaultListenerBuilder) Build(ctx context.Context, stack core.Stack, accelerator *agamodel.Accelerator, listeners []agaapi.GlobalAcceleratorListener) ([]*agamodel.Listener, error) { |
| 28 | + if listeners == nil || len(listeners) == 0 { |
| 29 | + return nil, nil |
| 30 | + } |
| 31 | + |
| 32 | + var result []*agamodel.Listener |
| 33 | + for i, listener := range listeners { |
| 34 | + listenerModel, err := buildListener(ctx, stack, accelerator, listener, i) |
| 35 | + if err != nil { |
| 36 | + return nil, err |
| 37 | + } |
| 38 | + result = append(result, listenerModel) |
| 39 | + } |
| 40 | + return result, nil |
| 41 | +} |
| 42 | + |
| 43 | +// buildListener builds a single Listener model resource |
| 44 | +func buildListener(ctx context.Context, stack core.Stack, accelerator *agamodel.Accelerator, listener agaapi.GlobalAcceleratorListener, index int) (*agamodel.Listener, error) { |
| 45 | + spec, err := buildListenerSpec(ctx, accelerator, listener) |
| 46 | + if err != nil { |
| 47 | + return nil, err |
| 48 | + } |
| 49 | + |
| 50 | + resourceID := fmt.Sprintf("Listener-%d", index) |
| 51 | + listenerModel := agamodel.NewListener(stack, resourceID, spec, accelerator) |
| 52 | + return listenerModel, nil |
| 53 | +} |
| 54 | + |
| 55 | +// buildListenerSpec builds the ListenerSpec for a single Listener model resource |
| 56 | +func buildListenerSpec(ctx context.Context, accelerator *agamodel.Accelerator, listener agaapi.GlobalAcceleratorListener) (agamodel.ListenerSpec, error) { |
| 57 | + protocol, err := buildListenerProtocol(ctx, listener) |
| 58 | + if err != nil { |
| 59 | + return agamodel.ListenerSpec{}, err |
| 60 | + } |
| 61 | + |
| 62 | + portRanges, err := buildListenerPortRanges(ctx, listener) |
| 63 | + if err != nil { |
| 64 | + return agamodel.ListenerSpec{}, err |
| 65 | + } |
| 66 | + |
| 67 | + clientAffinity := buildListenerClientAffinity(ctx, listener) |
| 68 | + |
| 69 | + return agamodel.ListenerSpec{ |
| 70 | + AcceleratorARN: accelerator.AcceleratorARN(), |
| 71 | + Protocol: protocol, |
| 72 | + PortRanges: portRanges, |
| 73 | + ClientAffinity: clientAffinity, |
| 74 | + }, nil |
| 75 | +} |
| 76 | + |
| 77 | +// buildListenerProtocol determines the protocol for the listener |
| 78 | +func buildListenerProtocol(_ context.Context, listener agaapi.GlobalAcceleratorListener) (agamodel.Protocol, error) { |
| 79 | + if listener.Protocol == nil { |
| 80 | + // TODO: Auto-discovery feature - Auto-determine protocol from endpoints if nil |
| 81 | + // For now, default to TCP |
| 82 | + return agamodel.ProtocolTCP, nil |
| 83 | + } |
| 84 | + |
| 85 | + switch *listener.Protocol { |
| 86 | + case agaapi.GlobalAcceleratorProtocolTCP: |
| 87 | + return agamodel.ProtocolTCP, nil |
| 88 | + case agaapi.GlobalAcceleratorProtocolUDP: |
| 89 | + return agamodel.ProtocolUDP, nil |
| 90 | + default: |
| 91 | + return "", errors.Errorf("unsupported protocol: %s", *listener.Protocol) |
| 92 | + } |
| 93 | +} |
| 94 | + |
| 95 | +// buildListenerPortRanges determines the port ranges for the listener |
| 96 | +func buildListenerPortRanges(_ context.Context, listener agaapi.GlobalAcceleratorListener) ([]agamodel.PortRange, error) { |
| 97 | + if listener.PortRanges == nil { |
| 98 | + // TODO: Auto-discovery feature - Auto-determine port ranges from endpoints if nil |
| 99 | + // For now, default to port 80 |
| 100 | + return []agamodel.PortRange{{ |
| 101 | + FromPort: 80, |
| 102 | + ToPort: 80, |
| 103 | + }}, nil |
| 104 | + } |
| 105 | + |
| 106 | + var portRanges []agamodel.PortRange |
| 107 | + for _, pr := range *listener.PortRanges { |
| 108 | + // Required validations are already done webhooks and CEL |
| 109 | + portRanges = append(portRanges, agamodel.PortRange{ |
| 110 | + FromPort: pr.FromPort, |
| 111 | + ToPort: pr.ToPort, |
| 112 | + }) |
| 113 | + } |
| 114 | + return portRanges, nil |
| 115 | +} |
| 116 | + |
| 117 | +// buildListenerClientAffinity determines the client affinity for the listener |
| 118 | +func buildListenerClientAffinity(_ context.Context, listener agaapi.GlobalAcceleratorListener) agamodel.ClientAffinity { |
| 119 | + switch listener.ClientAffinity { |
| 120 | + case agaapi.ClientAffinitySourceIP: |
| 121 | + return agamodel.ClientAffinitySourceIP |
| 122 | + case agaapi.ClientAffinityNone: |
| 123 | + return agamodel.ClientAffinityNone |
| 124 | + default: |
| 125 | + // Default to NONE as per AWS Global Accelerator behavior |
| 126 | + return agamodel.ClientAffinityNone |
| 127 | + } |
| 128 | +} |
0 commit comments