Skip to content

Commit 9b7e2e2

Browse files
authored
Merge pull request #36 from loxilb-io/lb-dport-range
PR : loxilb-io/loxilb#921 Initial support for LB dport range command
2 parents e85c87e + 61143a7 commit 9b7e2e2

File tree

4 files changed

+181
-111
lines changed

4 files changed

+181
-111
lines changed

cmd/create/create_loadbalancer.go

Lines changed: 99 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ func NewCreateLoadBalancerCmd(restOptions *api.RESTOptions) *cobra.Command {
141141
o := CreateLoadBalancerOptions{}
142142

143143
var createLbCmd = &cobra.Command{
144-
Use: "lb IP [--select=<rr|hash|priority|persist>] [--tcp=<port>:<targetPort>] [--udp=<port>:<targetPort>] [--sctp=<port>:<targetPort>] [--icmp] [--mark=<val>] [--secips=<ip>,] [--sources=<ip>,] [--endpoints=<ip>:<weight>,] [--mode=<onearm|fullnat>] [--bgp] [--monitor] [--inatimeout=<to>] [--name=<service-name>] [--attachEP] [--detachEP] [--security=<https|e2ehttps|none>] [--host=<url>] [--ppv2en] [--egress]",
144+
Use: "lb IP [--select=<rr|hash|priority|persist>] [--tcp=<ports>:<targetPorts>] [--udp=<ports>:<targetPorts>] [--sctp=<ports>:<targetPorts>] [--icmp] [--mark=<val>] [--secips=<ip>,] [--sources=<ip>,] [--endpoints=<ip>:<weight>,] [--mode=<onearm|fullnat>] [--bgp] [--monitor] [--inatimeout=<to>] [--name=<service-name>] [--attachEP] [--detachEP] [--security=<https|e2ehttps|none>] [--host=<url>] [--ppv2en] [--egress]",
145145
Short: "Create a LoadBalancer",
146146
Long: `Create a LoadBalancer
147147
@@ -158,7 +158,9 @@ func NewCreateLoadBalancerCmd(restOptions *api.RESTOptions) *cobra.Command {
158158
fullproxy - LB operating as a L7 proxy
159159
hostonearm - LB operating in host one-arm
160160
161-
ex) loxicmd create lb 192.168.0.200 --tcp=80:32015 --endpoints=10.212.0.1:1,10.212.0.2:1,10.212.0.3:1
161+
ex)
162+
loxicmd create lb 192.168.0.200 --tcp=80:32015 --endpoints=10.212.0.1:1,10.212.0.2:1,10.212.0.3:1
163+
loxicmd create lb 192.168.0.200 --tcp=8080-8081:32015 --endpoints=10.212.0.1:1,10.212.0.2:1,10.212.0.3:1
162164
loxicmd create lb 192.168.0.200 --tcp=5000:5201-5300 --endpoints=10.212.0.1:1,10.212.0.2:1,10.212.0.3:1
163165
loxicmd create lb 192.168.0.200 --tcp=80:32015 --endpoints=10.212.0.1:1,10.212.0.2:1,10.212.0.3:1 --security=https
164166
loxicmd create lb 192.168.0.200 --tcp=80:32015 --endpoints=10.212.0.1:1,10.212.0.2:1,10.212.0.3:1 --host=loxilb.io
@@ -222,81 +224,100 @@ ex) loxicmd create lb 192.168.0.200 --tcp=80:32015 --endpoints=10.212.0.1:1,10.2
222224
fmt.Printf("Error: %s\n", err.Error())
223225
return
224226
}
225-
if len(portTargetPorts) <= 0 {
227+
if len(portTargetPorts) <= 0 || len(portTargetPorts) > 2 {
226228
fmt.Printf("portPair: None specified\n")
227229
return
228230
}
229231

230-
for port := range portTargetPorts {
231-
lbModel := api.LoadBalancerModel{}
232-
oper := 0
233-
if o.Attach {
234-
oper = 1
235-
} else if o.Detach {
236-
oper = 2
237-
}
238-
lbService := api.LoadBalancerService{
239-
ExternalIP: o.ExternalIP,
240-
Protocol: proto,
241-
Port: port,
242-
Sel: api.EpSelect(SelectToNum(o.Select)),
243-
BGP: o.BGP,
244-
Monitor: o.Monitor,
245-
Mode: api.LbMode(ModeToNum(o.Mode)),
246-
Timeout: o.Timeout,
247-
Block: o.Mark,
248-
Name: o.Name,
249-
Oper: api.LbOP(oper),
250-
Security: api.LbSec(SecStringToNum(o.Security)),
251-
Host: o.Host,
252-
PpV2: o.PPv2En,
253-
Egress: o.Egress,
254-
}
255-
256-
lbModel.Service = lbService
257-
for endpoint, weight := range endpointPair {
258-
targetPorts := portTargetPorts[port]
259-
for _, targetPort := range targetPorts {
260-
if o.Mode == "dsr" && targetPort != port {
261-
fmt.Printf("Error: No port-translation in dsr mode\n")
262-
return
263-
}
264-
ep := api.LoadBalancerEndpoint{
265-
EndpointIP: endpoint,
266-
TargetPort: targetPort,
267-
Weight: weight,
268-
}
269-
lbModel.Endpoints = append(lbModel.Endpoints, ep)
232+
startSPort := uint16(0)
233+
endSPort := uint16(0)
234+
first := false
235+
236+
for sPort := range portTargetPorts {
237+
if !first {
238+
startSPort = sPort
239+
first = true
240+
} else {
241+
if sPort > startSPort {
242+
endSPort = sPort
243+
} else {
244+
endSPort = startSPort
245+
startSPort = sPort
270246
}
271247
}
248+
}
249+
250+
lbModel := api.LoadBalancerModel{}
251+
oper := 0
252+
if o.Attach {
253+
oper = 1
254+
} else if o.Detach {
255+
oper = 2
256+
}
257+
lbService := api.LoadBalancerService{
258+
ExternalIP: o.ExternalIP,
259+
Protocol: proto,
260+
Port: startSPort,
261+
PortMax: endSPort,
262+
Sel: api.EpSelect(SelectToNum(o.Select)),
263+
BGP: o.BGP,
264+
Monitor: o.Monitor,
265+
Mode: api.LbMode(ModeToNum(o.Mode)),
266+
Timeout: o.Timeout,
267+
Block: o.Mark,
268+
Name: o.Name,
269+
Oper: api.LbOP(oper),
270+
Security: api.LbSec(SecStringToNum(o.Security)),
271+
Host: o.Host,
272+
PpV2: o.PPv2En,
273+
Egress: o.Egress,
274+
}
272275

273-
for _, sip := range o.SecIPs {
274-
sp := api.LoadBalancerSecIp{
275-
SecondaryIP: sip,
276+
lbModel.Service = lbService
277+
for endpoint, weight := range endpointPair {
278+
targetPorts := portTargetPorts[startSPort]
279+
for _, targetPort := range targetPorts {
280+
if o.Mode == "dsr" && targetPort != startSPort {
281+
fmt.Printf("Error: No port-translation in dsr mode\n")
282+
return
276283
}
277-
lbModel.SecondaryIPs = append(lbModel.SecondaryIPs, sp)
284+
ep := api.LoadBalancerEndpoint{
285+
EndpointIP: endpoint,
286+
TargetPort: targetPort,
287+
Weight: weight,
288+
}
289+
lbModel.Endpoints = append(lbModel.Endpoints, ep)
278290
}
291+
}
279292

280-
for _, sip := range o.AllowedSources {
281-
sp := api.LbAllowedSrcIPArg{
282-
Prefix: sip,
283-
}
284-
lbModel.SrcIPs = append(lbModel.SrcIPs, sp)
293+
for _, sip := range o.SecIPs {
294+
sp := api.LoadBalancerSecIp{
295+
SecondaryIP: sip,
285296
}
297+
lbModel.SecondaryIPs = append(lbModel.SecondaryIPs, sp)
298+
}
286299

287-
resp, err := LoadbalancerAPICall(restOptions, lbModel)
288-
if err != nil {
289-
fmt.Printf("Error: %s\n", err.Error())
290-
return
300+
for _, sip := range o.AllowedSources {
301+
sp := api.LbAllowedSrcIPArg{
302+
Prefix: sip,
291303
}
304+
lbModel.SrcIPs = append(lbModel.SrcIPs, sp)
305+
}
306+
307+
resp, err := LoadbalancerAPICall(restOptions, lbModel)
308+
if err != nil {
309+
fmt.Printf("Error: %s\n", err.Error())
310+
return
311+
}
292312

293-
defer resp.Body.Close()
313+
defer resp.Body.Close()
294314

295-
fmt.Printf("Debug: response.StatusCode: %d\n", resp.StatusCode)
296-
if resp.StatusCode == http.StatusOK {
297-
PrintCreateResult(resp, *restOptions)
298-
return
299-
}
315+
//fmt.Printf("Debug: request: %v\n", lbModel)
316+
317+
fmt.Printf("Debug: response.StatusCode: %d\n", resp.StatusCode)
318+
if resp.StatusCode == http.StatusOK {
319+
PrintCreateResult(resp, *restOptions)
320+
return
300321
}
301322
}
302323
},
@@ -357,12 +378,20 @@ func GetPortPairList(portPairStrList []string) (map[uint16][]uint16, error) {
357378
if len(portPair) != 2 {
358379
continue
359380
}
381+
382+
servicePorts := strings.Split(portPair[0], "-")
383+
360384
// 0 is port, 1 is targetPort
361-
port, err := strconv.Atoi(portPair[0])
362-
if err != nil {
363-
return nil, fmt.Errorf("port '%s' is not integer", portPair[0])
385+
var portList []int
386+
for _, servicePort := range servicePorts {
387+
port, err := strconv.Atoi(servicePort)
388+
if err != nil {
389+
return nil, fmt.Errorf("port '%s' is not integer", servicePort)
390+
}
391+
portList = append(portList, port)
364392
}
365393

394+
var err error
366395
startTP := 0
367396
endTP := 0
368397

@@ -389,10 +418,12 @@ func GetPortPairList(portPairStrList []string) (map[uint16][]uint16, error) {
389418
endTP = startTP
390419
}
391420

392-
result[uint16(port)] = make([]uint16, 0)
421+
for _, port := range portList {
422+
result[uint16(port)] = make([]uint16, 0)
393423

394-
for targetPort := startTP; targetPort <= endTP; targetPort++ {
395-
result[uint16(port)] = append(result[uint16(port)], uint16(targetPort))
424+
for targetPort := startTP; targetPort <= endTP; targetPort++ {
425+
result[uint16(port)] = append(result[uint16(port)], uint16(targetPort))
426+
}
396427
}
397428
}
398429
return result, nil

cmd/delete/delete_loadbalancer.go

Lines changed: 61 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ import (
2020
"encoding/json"
2121
"errors"
2222
"fmt"
23-
"github.com/spf13/cobra"
2423
"io"
2524
"loxicmd/pkg/api"
2625
"net/http"
2726
"strconv"
27+
"strings"
2828
"time"
29+
30+
"github.com/spf13/cobra"
2931
)
3032

3133
type DeleteLoadBalancerResult struct {
@@ -44,9 +46,9 @@ func validation(args []string) error {
4446
}
4547

4648
func NewDeleteLoadBalancerCmd(restOptions *api.RESTOptions) *cobra.Command {
47-
var tcpPortNumberList []int
48-
var udpPortNumberList []int
49-
var sctpPortNumberList []int
49+
var tcpPortNumberList string
50+
var udpPortNumberList string
51+
var sctpPortNumberList string
5052
var icmpPortNumberList bool
5153
var BGP bool
5254
var Mark uint16
@@ -98,57 +100,80 @@ func NewDeleteLoadBalancerCmd(restOptions *api.RESTOptions) *cobra.Command {
98100
return
99101
}
100102
externalIP = args[0]
101-
PortNumberList := make(map[string][]int)
103+
PortNumberList := make(map[string][]string)
102104

103105
if len(tcpPortNumberList) > 0 {
104-
PortNumberList["tcp"] = tcpPortNumberList
106+
PortNumberList["tcp"] = strings.Split(tcpPortNumberList, "-")
107+
if len(PortNumberList["tcp"]) > 2 {
108+
fmt.Printf("Error: Too many ports in list to delete LoadBalancer(ExternalIP: %s, tcp, Port:%s)\n", externalIP, tcpPortNumberList)
109+
}
105110
}
106111
if len(udpPortNumberList) > 0 {
107-
PortNumberList["udp"] = udpPortNumberList
112+
PortNumberList["udp"] = strings.Split(udpPortNumberList, "-")
113+
if len(PortNumberList["udp"]) > 2 {
114+
fmt.Printf("Error: Too many ports in list to delete LoadBalancer(ExternalIP: %s, udp, Port:%s)\n", externalIP, udpPortNumberList)
115+
}
108116
}
109117
if len(sctpPortNumberList) > 0 {
110-
PortNumberList["sctp"] = sctpPortNumberList
118+
PortNumberList["sctp"] = strings.Split(sctpPortNumberList, "-")
119+
if len(PortNumberList["sctp"]) > 2 {
120+
fmt.Printf("Error: Too many ports in list to delete LoadBalancer(ExternalIP: %s, sctp, Port:%s)\n", externalIP, sctpPortNumberList)
121+
return
122+
}
111123
}
112124
if icmpPortNumberList {
113-
PortNumberList["icmp"] = []int{0}
125+
PortNumberList["icmp"] = []string{"0", "0"}
114126
}
115127
fmt.Printf("PortNumberList: %v\n", PortNumberList)
116128
if Host == "" {
117129
Host = "any"
118130
}
119131
for proto, portNum := range PortNumberList {
120-
for _, port := range portNum {
121-
subResources := []string{
122-
"hosturl", Host,
123-
"externalipaddress", externalIP,
124-
"port", strconv.Itoa(port),
125-
"protocol", proto,
126-
}
127-
qmap := map[string]string{}
128-
qmap["bgp"] = fmt.Sprintf("%v", BGP)
129-
qmap["block"] = fmt.Sprintf("%v", Mark)
130-
fmt.Printf("subResources: %v\n", subResources)
131-
resp, err := client.LoadBalancer().SubResources(subResources).Query(qmap).Delete(ctx)
132-
if err != nil {
133-
fmt.Printf("Error: Failed to delete LoadBalancer(ExternalIP: %s, Protocol:%s, Port:%d)\n", externalIP, proto, portNum)
134-
return
135-
}
136-
defer resp.Body.Close()
137-
fmt.Printf("Debug: response.StatusCode: %d\n", resp.StatusCode)
138-
if resp.StatusCode == http.StatusOK {
139-
PrintDeleteResult(resp, *restOptions)
140-
return
141-
}
132+
sPortMin := portNum[0]
133+
sPortMax := "0"
134+
if len(portNum) > 1 {
135+
sPortMax = portNum[1]
136+
}
137+
_, err := strconv.Atoi(sPortMin)
138+
if err != nil {
139+
fmt.Printf("Error: Invalid port in list to delete LoadBalancer(ExternalIP: %s,Port:%s)\n", externalIP, sPortMin)
140+
return
141+
}
142+
_, err = strconv.Atoi(sPortMax)
143+
if err != nil {
144+
fmt.Printf("Error: Invalid port in list to delete LoadBalancer(ExternalIP: %s,Port:%s)\n", externalIP, sPortMax)
145+
return
146+
}
147+
subResources := []string{
148+
"hosturl", Host,
149+
"externalipaddress", externalIP,
150+
"port", sPortMin,
151+
"portmax", sPortMax,
152+
"protocol", proto,
153+
}
154+
qmap := map[string]string{}
155+
qmap["bgp"] = fmt.Sprintf("%v", BGP)
156+
qmap["block"] = fmt.Sprintf("%v", Mark)
157+
fmt.Printf("subResources: %v\n", subResources)
158+
resp, err := client.LoadBalancer().SubResources(subResources).Query(qmap).Delete(ctx)
159+
if err != nil {
160+
fmt.Printf("Error: Failed to delete LoadBalancer(ExternalIP: %s, Protocol:%s, Port:%v)\n", externalIP, proto, portNum)
161+
return
162+
}
163+
defer resp.Body.Close()
164+
fmt.Printf("Debug: response.StatusCode: %d\n", resp.StatusCode)
165+
if resp.StatusCode == http.StatusOK {
166+
PrintDeleteResult(resp, *restOptions)
167+
return
142168
}
143-
144169
}
145170
},
146171
}
147172

148-
deleteLbCmd.Flags().IntSliceVar(&tcpPortNumberList, "tcp", tcpPortNumberList, "TCP port list can be specified as '<port>,<port>...'")
149-
deleteLbCmd.Flags().IntSliceVar(&udpPortNumberList, "udp", udpPortNumberList, "UDP port list can be specified as '<port>,<port>...'")
150-
deleteLbCmd.Flags().IntSliceVar(&sctpPortNumberList, "sctp", sctpPortNumberList, "SCTP port list can be specified as '<port>,<port>...'")
151-
deleteLbCmd.Flags().BoolVarP(&icmpPortNumberList, "icmp", "", false, "ICMP port list can be specified as '<port>,<port>...'")
173+
deleteLbCmd.Flags().StringVar(&tcpPortNumberList, "tcp", tcpPortNumberList, "TCP port list can be specified as '<portMin>-<portMax>'")
174+
deleteLbCmd.Flags().StringVar(&udpPortNumberList, "udp", udpPortNumberList, "UDP port list can be specified as '<portMin>-<portMax>...'")
175+
deleteLbCmd.Flags().StringVar(&sctpPortNumberList, "sctp", sctpPortNumberList, "SCTP port list can be specified as '<portMin>-<portMax>...'")
176+
deleteLbCmd.Flags().BoolVarP(&icmpPortNumberList, "icmp", "", false, "ICMP port list can't be specified'")
152177
deleteLbCmd.Flags().BoolVarP(&BGP, "bgp", "", false, "BGP enable information'")
153178
deleteLbCmd.Flags().Uint16VarP(&Mark, "mark", "", 0, "Specify the mark num to segregate a load-balancer VIP service")
154179
deleteLbCmd.Flags().StringVarP(&Name, "name", "", Name, "Name for load balancer rule")

0 commit comments

Comments
 (0)