Skip to content

Commit f233ef9

Browse files
committed
Support for SIP update APIs.
1 parent b704c38 commit f233ef9

File tree

4 files changed

+299
-7
lines changed

4 files changed

+299
-7
lines changed

.nanpa/sip-update.kdl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
minor type="added" "support for SIP update APIs"

cmd/lk/sip.go

Lines changed: 292 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package main
1616

1717
import (
1818
"context"
19+
"errors"
1920
"fmt"
2021
"maps"
2122
"slices"
@@ -52,6 +53,34 @@ var (
5253
Action: createSIPInboundTrunk,
5354
ArgsUsage: RequestDesc[livekit.CreateSIPInboundTrunkRequest](),
5455
},
56+
{
57+
Name: "update",
58+
Usage: "Update an inbound SIP Trunk",
59+
Action: updateSIPInboundTrunk,
60+
ArgsUsage: RequestDesc[livekit.UpdateSIPInboundTrunkRequest](),
61+
Flags: []cli.Flag{
62+
&cli.StringFlag{
63+
Name: "id",
64+
Usage: "ID for the trunk to update",
65+
},
66+
&cli.StringFlag{
67+
Name: "name",
68+
Usage: "Sets a new name for the trunk",
69+
},
70+
&cli.StringSliceFlag{
71+
Name: "numbers",
72+
Usage: "Sets a new list of numbers for the trunk",
73+
},
74+
&cli.StringFlag{
75+
Name: "auth-user",
76+
Usage: "Set username for authentication",
77+
},
78+
&cli.StringFlag{
79+
Name: "auth-pass",
80+
Usage: "Set password for authentication",
81+
},
82+
},
83+
},
5584
{
5685
Name: "delete",
5786
Usage: "Delete a SIP Trunk",
@@ -73,10 +102,46 @@ var (
73102
},
74103
{
75104
Name: "create",
76-
Usage: "Create a outbound SIP Trunk",
105+
Usage: "Create an outbound SIP Trunk",
77106
Action: createSIPOutboundTrunk,
78107
ArgsUsage: RequestDesc[livekit.CreateSIPOutboundTrunkRequest](),
79108
},
109+
{
110+
Name: "update",
111+
Usage: "Update an outbound SIP Trunk",
112+
Action: updateSIPOutboundTrunk,
113+
ArgsUsage: RequestDesc[livekit.UpdateSIPOutboundTrunkRequest](),
114+
Flags: []cli.Flag{
115+
&cli.StringFlag{
116+
Name: "id",
117+
Usage: "ID for the trunk to update",
118+
},
119+
&cli.StringFlag{
120+
Name: "name",
121+
Usage: "Sets a new name for the trunk",
122+
},
123+
&cli.StringFlag{
124+
Name: "address",
125+
Usage: "Sets a new destination address for the trunk",
126+
},
127+
&cli.StringFlag{
128+
Name: "transport",
129+
Usage: "Sets a new transport for the trunk",
130+
},
131+
&cli.StringSliceFlag{
132+
Name: "numbers",
133+
Usage: "Sets a new list of numbers for the trunk",
134+
},
135+
&cli.StringFlag{
136+
Name: "auth-user",
137+
Usage: "Set username for authentication",
138+
},
139+
&cli.StringFlag{
140+
Name: "auth-pass",
141+
Usage: "Set password for authentication",
142+
},
143+
},
144+
},
80145
{
81146
Name: "delete",
82147
Usage: "Delete SIP Trunk",
@@ -102,6 +167,26 @@ var (
102167
Action: createSIPDispatchRule,
103168
ArgsUsage: RequestDesc[livekit.CreateSIPDispatchRuleRequest](),
104169
},
170+
{
171+
Name: "update",
172+
Usage: "Update a SIP Dispatch Rule",
173+
Action: updateSIPDispatchRule,
174+
ArgsUsage: RequestDesc[livekit.UpdateSIPDispatchRuleRequest](),
175+
Flags: []cli.Flag{
176+
&cli.StringFlag{
177+
Name: "id",
178+
Usage: "ID for the rule to update",
179+
},
180+
&cli.StringFlag{
181+
Name: "name",
182+
Usage: "Sets a new name for the rule",
183+
},
184+
&cli.StringSliceFlag{
185+
Name: "trunks",
186+
Usage: "Sets a new list of trunk IDs",
187+
},
188+
},
189+
},
105190
{
106191
Name: "delete",
107192
Usage: "Delete SIP Dispatch Rule",
@@ -230,6 +315,17 @@ var (
230315
}
231316
)
232317

318+
func listUpdateFlag(cmd *cli.Command, setName string) *livekit.ListUpdate {
319+
if !cmd.IsSet(setName) {
320+
return nil
321+
}
322+
val := cmd.StringSlice(setName)
323+
if len(val) == 1 && val[0] == "" {
324+
val = []string{}
325+
}
326+
return &livekit.ListUpdate{Set: val}
327+
}
328+
233329
func createSIPClient(cmd *cli.Command) (*lksdk.SIPClient, error) {
234330
pc, err := loadProjectDetails(cmd)
235331
if err != nil {
@@ -246,6 +342,68 @@ func createSIPInboundTrunk(ctx context.Context, cmd *cli.Command) error {
246342
return createAndPrintReqs(ctx, cmd, nil, cli.CreateSIPInboundTrunk, printSIPInboundTrunkID)
247343
}
248344

345+
func updateSIPInboundTrunk(ctx context.Context, cmd *cli.Command) error {
346+
cli, err := createSIPClient(cmd)
347+
if err != nil {
348+
return err
349+
}
350+
id := cmd.String("id")
351+
if cmd.Args().Len() > 1 {
352+
return errors.New("expected one JSON file or flags")
353+
}
354+
if cmd.Args().Len() == 1 {
355+
// Update from the JSON
356+
req, err := ReadRequestFileOrLiteral[livekit.SIPInboundTrunkInfo](cmd.Args().First())
357+
if err != nil {
358+
return fmt.Errorf("could not read request: %w", err)
359+
}
360+
if id == "" {
361+
id = req.SipTrunkId
362+
}
363+
req.SipTrunkId = ""
364+
if id == "" {
365+
return errors.New("no ID specified, use flag or set it in JSON")
366+
}
367+
info, err := cli.UpdateSIPInboundTrunk(ctx, &livekit.UpdateSIPInboundTrunkRequest{
368+
SipTrunkId: id,
369+
Action: &livekit.UpdateSIPInboundTrunkRequest_Replace{
370+
Replace: req,
371+
},
372+
})
373+
if err != nil {
374+
return err
375+
}
376+
printSIPInboundTrunkID(info)
377+
return err
378+
}
379+
// Update from flags
380+
if id == "" {
381+
return errors.New("no ID specified")
382+
}
383+
req := &livekit.SIPInboundTrunkUpdate{}
384+
if val := cmd.String("name"); val != "" {
385+
req.Name = &val
386+
}
387+
if val := cmd.String("auth-user"); val != "" {
388+
req.AuthUsername = &val
389+
}
390+
if val := cmd.String("auth-pass"); val != "" {
391+
req.AuthPassword = &val
392+
}
393+
req.Numbers = listUpdateFlag(cmd, "numbers")
394+
info, err := cli.UpdateSIPInboundTrunk(ctx, &livekit.UpdateSIPInboundTrunkRequest{
395+
SipTrunkId: id,
396+
Action: &livekit.UpdateSIPInboundTrunkRequest_Update{
397+
Update: req,
398+
},
399+
})
400+
if err != nil {
401+
return err
402+
}
403+
printSIPInboundTrunkID(info)
404+
return err
405+
}
406+
249407
func createSIPOutboundTrunk(ctx context.Context, cmd *cli.Command) error {
250408
cli, err := createSIPClient(cmd)
251409
if err != nil {
@@ -254,6 +412,83 @@ func createSIPOutboundTrunk(ctx context.Context, cmd *cli.Command) error {
254412
return createAndPrintReqs(ctx, cmd, nil, cli.CreateSIPOutboundTrunk, printSIPOutboundTrunkID)
255413
}
256414

415+
func updateSIPOutboundTrunk(ctx context.Context, cmd *cli.Command) error {
416+
cli, err := createSIPClient(cmd)
417+
if err != nil {
418+
return err
419+
}
420+
id := cmd.String("id")
421+
if cmd.Args().Len() > 1 {
422+
return errors.New("expected one JSON file or flags")
423+
}
424+
if cmd.Args().Len() == 1 {
425+
// Update from the JSON
426+
req, err := ReadRequestFileOrLiteral[livekit.SIPOutboundTrunkInfo](cmd.Args().First())
427+
if err != nil {
428+
return fmt.Errorf("could not read request: %w", err)
429+
}
430+
if id == "" {
431+
id = req.SipTrunkId
432+
}
433+
req.SipTrunkId = ""
434+
if id == "" {
435+
return errors.New("no ID specified, use flag or set it in JSON")
436+
}
437+
info, err := cli.UpdateSIPOutboundTrunk(ctx, &livekit.UpdateSIPOutboundTrunkRequest{
438+
SipTrunkId: id,
439+
Action: &livekit.UpdateSIPOutboundTrunkRequest_Replace{
440+
Replace: req,
441+
},
442+
})
443+
if err != nil {
444+
return err
445+
}
446+
printSIPOutboundTrunkID(info)
447+
return err
448+
}
449+
// Update from flags
450+
if id == "" {
451+
return errors.New("no ID specified")
452+
}
453+
req := &livekit.SIPOutboundTrunkUpdate{}
454+
if val := cmd.String("name"); val != "" {
455+
req.Name = &val
456+
}
457+
if val := cmd.String("address"); val != "" {
458+
req.Address = &val
459+
}
460+
if val := cmd.String("transport"); val != "" {
461+
val = strings.ToUpper(val)
462+
if !strings.HasPrefix(val, "SIP_TRANSPORT_") {
463+
val = "SIP_TRANSPORT_" + val
464+
}
465+
trv, ok := livekit.SIPTransport_value[val]
466+
if !ok {
467+
return fmt.Errorf("unsupported transport: %q", val)
468+
}
469+
tr := livekit.SIPTransport(trv)
470+
req.Transport = &tr
471+
}
472+
if val := cmd.String("auth-user"); val != "" {
473+
req.AuthUsername = &val
474+
}
475+
if val := cmd.String("auth-pass"); val != "" {
476+
req.AuthPassword = &val
477+
}
478+
req.Numbers = listUpdateFlag(cmd, "numbers")
479+
info, err := cli.UpdateSIPOutboundTrunk(ctx, &livekit.UpdateSIPOutboundTrunkRequest{
480+
SipTrunkId: id,
481+
Action: &livekit.UpdateSIPOutboundTrunkRequest_Update{
482+
Update: req,
483+
},
484+
})
485+
if err != nil {
486+
return err
487+
}
488+
printSIPOutboundTrunkID(info)
489+
return err
490+
}
491+
257492
func userPass(user string, hasPass bool) string {
258493
if user == "" && !hasPass {
259494
return ""
@@ -434,6 +669,62 @@ func createSIPDispatchRuleLegacy(ctx context.Context, cmd *cli.Command) error {
434669
return createAndPrintLegacy(ctx, cmd, cli.CreateSIPDispatchRule, printSIPDispatchRuleID)
435670
}
436671

672+
func updateSIPDispatchRule(ctx context.Context, cmd *cli.Command) error {
673+
cli, err := createSIPClient(cmd)
674+
if err != nil {
675+
return err
676+
}
677+
id := cmd.String("id")
678+
if cmd.Args().Len() > 1 {
679+
return errors.New("expected one JSON file or flags")
680+
}
681+
if cmd.Args().Len() == 1 {
682+
// Update from the JSON
683+
req, err := ReadRequestFileOrLiteral[livekit.SIPDispatchRuleInfo](cmd.Args().First())
684+
if err != nil {
685+
return fmt.Errorf("could not read request: %w", err)
686+
}
687+
if id == "" {
688+
id = req.SipDispatchRuleId
689+
}
690+
req.SipDispatchRuleId = ""
691+
if id == "" {
692+
return errors.New("no ID specified, use flag or set it in JSON")
693+
}
694+
info, err := cli.UpdateSIPDispatchRule(ctx, &livekit.UpdateSIPDispatchRuleRequest{
695+
SipDispatchRuleId: id,
696+
Action: &livekit.UpdateSIPDispatchRuleRequest_Replace{
697+
Replace: req,
698+
},
699+
})
700+
if err != nil {
701+
return err
702+
}
703+
printSIPDispatchRuleID(info)
704+
return err
705+
}
706+
// Update from flags
707+
if id == "" {
708+
return errors.New("no ID specified")
709+
}
710+
req := &livekit.SIPDispatchRuleUpdate{}
711+
if val := cmd.String("name"); val != "" {
712+
req.Name = &val
713+
}
714+
req.TrunkIds = listUpdateFlag(cmd, "trunks")
715+
info, err := cli.UpdateSIPDispatchRule(ctx, &livekit.UpdateSIPDispatchRuleRequest{
716+
SipDispatchRuleId: id,
717+
Action: &livekit.UpdateSIPDispatchRuleRequest_Update{
718+
Update: req,
719+
},
720+
})
721+
if err != nil {
722+
return err
723+
}
724+
printSIPDispatchRuleID(info)
725+
return err
726+
}
727+
437728
func listSipDispatchRule(ctx context.Context, cmd *cli.Command) error {
438729
cli, err := createSIPClient(cmd)
439730
if err != nil {

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ require (
1414
github.com/go-logr/logr v1.4.2
1515
github.com/go-task/task/v3 v3.41.0
1616
github.com/joho/godotenv v1.5.1
17-
github.com/livekit/protocol v1.35.1-0.20250319165056-fdacb1a293e5
18-
github.com/livekit/server-sdk-go/v2 v2.5.1-0.20250319165849-a5f5f6eb2bde
17+
github.com/livekit/protocol v1.35.1-0.20250320161708-6d044a0462b3
18+
github.com/livekit/server-sdk-go/v2 v2.5.1-0.20250321175649-e38544bea187
1919
github.com/moby/buildkit v0.20.1
2020
github.com/pion/rtcp v1.2.15
2121
github.com/pion/rtp v1.8.13

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -260,12 +260,12 @@ github.com/livekit/mageutil v0.0.0-20230125210925-54e8a70427c1 h1:jm09419p0lqTkD
260260
github.com/livekit/mageutil v0.0.0-20230125210925-54e8a70427c1/go.mod h1:Rs3MhFwutWhGwmY1VQsygw28z5bWcnEYmS1OG9OxjOQ=
261261
github.com/livekit/mediatransportutil v0.0.0-20250310153736-45596af895b6 h1:6ZhtnY9I9knfm3ieIPpznQSEU2rDECO8yliW/ANLQ7U=
262262
github.com/livekit/mediatransportutil v0.0.0-20250310153736-45596af895b6/go.mod h1:36s+wwmU3O40IAhE+MjBWP3W71QRiEE9SfooSBvtBqY=
263-
github.com/livekit/protocol v1.35.1-0.20250319165056-fdacb1a293e5 h1:onBZ5milSh7iAnapx1ju/z51bvb5RgLmlVBPdNJbg2Y=
264-
github.com/livekit/protocol v1.35.1-0.20250319165056-fdacb1a293e5/go.mod h1:WrT/CYRxtMNOVUjnIPm5OjWtEkmreffTeE1PRZwlRg4=
263+
github.com/livekit/protocol v1.35.1-0.20250320161708-6d044a0462b3 h1:RsVnIuxnj3wRzWILhpnguyrq3vrK6Cccb762GpLH3Xg=
264+
github.com/livekit/protocol v1.35.1-0.20250320161708-6d044a0462b3/go.mod h1:WrT/CYRxtMNOVUjnIPm5OjWtEkmreffTeE1PRZwlRg4=
265265
github.com/livekit/psrpc v0.6.1-0.20250205181828-a0beed2e4126 h1:fzuYpAQbCid7ySPpQWWePfQOWUrs8x6dJ0T3Wl07n+Y=
266266
github.com/livekit/psrpc v0.6.1-0.20250205181828-a0beed2e4126/go.mod h1:X5WtEZ7OnEs72Fi5/J+i0on3964F1aynQpCalcgMqRo=
267-
github.com/livekit/server-sdk-go/v2 v2.5.1-0.20250319165849-a5f5f6eb2bde h1:J/fLwtZM07vS8IfXM0aWCMvOki7QMCbvlAm37nObM0g=
268-
github.com/livekit/server-sdk-go/v2 v2.5.1-0.20250319165849-a5f5f6eb2bde/go.mod h1:egApdq6lVge9rOvsJuvkyRClq18yytLNLiriY38p8WI=
267+
github.com/livekit/server-sdk-go/v2 v2.5.1-0.20250321175649-e38544bea187 h1:TNQSR/4p23qmfGbt0Pku0TMsN/pwud0ZSsxeZJUGF+s=
268+
github.com/livekit/server-sdk-go/v2 v2.5.1-0.20250321175649-e38544bea187/go.mod h1:4Kt0/NmSvMW0Jg4fo1YK0rk4EAmaf3LDi8DKzYrmDIc=
269269
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
270270
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
271271
github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg=

0 commit comments

Comments
 (0)