Skip to content

Commit 55bd16b

Browse files
committed
feat(dbdr/net-peering) [STORY-3557] Add commands to configure net peerings of DB-DR
1 parent 8e323f6 commit 55bd16b

File tree

11 files changed

+414
-10
lines changed

11 files changed

+414
-10
lines changed

cmd/commands.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,12 @@ var (
330330
&databaseFirewallRulesAddCommand,
331331
&databaseFirewallRulesRemoveCommand,
332332
&databaseFirewallManagedRangesCommand,
333+
334+
// Network
335+
&databaseNetPeeringsListCommand,
336+
&databaseNetPeeringsAddCommand,
337+
&databaseNetPeeringsRemoveCommand,
338+
&databaseNetworkConfigurationShowCommand,
333339
}
334340

335341
globalCommands = []*cli.Command{

cmd/databases_networking.go

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
package cmd
2+
3+
import (
4+
"context"
5+
6+
"github.com/urfave/cli/v3"
7+
8+
"github.com/Scalingo/cli/cmd/autocomplete"
9+
"github.com/Scalingo/cli/dbng"
10+
"github.com/Scalingo/cli/detect"
11+
"github.com/Scalingo/cli/utils"
12+
"github.com/Scalingo/go-scalingo/v11"
13+
)
14+
15+
var (
16+
databaseNetPeeringsListCommand = cli.Command{
17+
Name: "database-net-peerings",
18+
Category: "Databases DR",
19+
Usage: "List net peerings of a database",
20+
ArgsUsage: "database-id",
21+
Flags: []cli.Flag{databaseFlag()},
22+
Description: CommandDescription{
23+
Description: "List all net peerings of a database",
24+
Examples: []string{
25+
"scalingo database-net-peerings my-db-id",
26+
"scalingo --database my-db database-net-peerings",
27+
},
28+
SeeAlso: []string{"database-net-peerings-add", "database-net-peerings-remove", "database-network-configuration"},
29+
}.Render(),
30+
Action: func(ctx context.Context, c *cli.Command) error {
31+
databaseID := detect.ExtractDatabaseNameFromCommandLineOrEnv(c)
32+
if databaseID == "" {
33+
return cli.ShowCommandHelp(ctx, c, "database-net-peerings")
34+
}
35+
utils.CheckForConsent(ctx, databaseID, utils.ConsentTypeDBs)
36+
37+
err := dbng.DatabaseNetPeeringsList(ctx, databaseID)
38+
if err != nil {
39+
errorQuit(ctx, err)
40+
}
41+
42+
return nil
43+
},
44+
ShellComplete: func(ctx context.Context, c *cli.Command) {
45+
_ = autocomplete.CmdFlagsAutoComplete(c, "database-net-peerings")
46+
_ = autocomplete.DatabasesNgListAutoComplete(ctx)
47+
},
48+
}
49+
50+
databaseNetPeeringsAddCommand = cli.Command{
51+
Name: "database-net-peerings-add",
52+
Category: "Databases DR",
53+
Usage: "Add a net peering to a database",
54+
ArgsUsage: "database-id",
55+
Flags: []cli.Flag{
56+
databaseFlag(),
57+
&cli.StringFlag{
58+
Name: "outscale-net-peering-id",
59+
Usage: "Outscale net peering ID",
60+
Required: true,
61+
},
62+
},
63+
Description: CommandDescription{
64+
Description: "Initiate the creation of a net peering for a database",
65+
Examples: []string{
66+
"scalingo database-net-peerings-add my-db-id --outscale-net-peering-id pcx-123456789",
67+
"scalingo --database my-db database-net-peerings-add --outscale-net-peering-id pcx-123456789",
68+
},
69+
SeeAlso: []string{"database-net-peerings", "database-net-peerings-remove", "database-network-configuration"},
70+
}.Render(),
71+
Action: func(ctx context.Context, c *cli.Command) error {
72+
databaseID := detect.ExtractDatabaseNameFromCommandLineOrEnv(c)
73+
if databaseID == "" {
74+
return cli.ShowCommandHelp(ctx, c, "database-net-peerings-add")
75+
}
76+
77+
utils.CheckForConsent(ctx, databaseID, utils.ConsentTypeDBs)
78+
79+
params := scalingo.DatabaseNetPeeringCreateParams{
80+
OutscaleNetPeeringID: c.String("outscale-net-peering-id"),
81+
}
82+
83+
err := dbng.DatabaseNetPeeringsAdd(ctx, databaseID, params)
84+
if err != nil {
85+
errorQuit(ctx, err)
86+
}
87+
88+
return nil
89+
},
90+
ShellComplete: func(ctx context.Context, c *cli.Command) {
91+
_ = autocomplete.CmdFlagsAutoComplete(c, "database-net-peerings-add")
92+
_ = autocomplete.DatabasesNgListAutoComplete(ctx)
93+
},
94+
}
95+
96+
databaseNetPeeringsRemoveCommand = cli.Command{
97+
Name: "database-net-peerings-remove",
98+
Category: "Databases DR",
99+
Usage: "Remove a net peering from a database",
100+
ArgsUsage: "database-id net-peering-id",
101+
Flags: []cli.Flag{
102+
databaseFlag(),
103+
&cli.StringFlag{
104+
Name: "net-peering",
105+
Aliases: []string{"np"},
106+
Usage: "Net peering ID to remove",
107+
},
108+
},
109+
Description: CommandDescription{
110+
Description: "Delete an existing net peering from a database",
111+
Examples: []string{
112+
"scalingo database-net-peerings-remove my-db-id np-id",
113+
"scalingo --database my-db database-net-peerings-remove np-id",
114+
},
115+
SeeAlso: []string{"database-net-peerings", "database-net-peerings-add", "database-network-configuration"},
116+
}.Render(),
117+
Action: func(ctx context.Context, c *cli.Command) error {
118+
databaseID := detect.ExtractDatabaseNameFromCommandLineOrEnv(c)
119+
if databaseID == "" {
120+
return cli.ShowCommandHelp(ctx, c, "database-net-peerings-remove")
121+
}
122+
123+
utils.CheckForConsent(ctx, databaseID, utils.ConsentTypeDBs)
124+
125+
err := dbng.DatabaseNetPeeringsRemove(ctx, databaseID, c.String("net-peering"))
126+
if err != nil {
127+
errorQuit(ctx, err)
128+
}
129+
130+
return nil
131+
},
132+
ShellComplete: func(ctx context.Context, c *cli.Command) {
133+
_ = autocomplete.CmdFlagsAutoComplete(c, "database-net-peerings-remove")
134+
_ = autocomplete.DatabasesNgListAutoComplete(ctx)
135+
},
136+
}
137+
138+
databaseNetworkConfigurationShowCommand = cli.Command{
139+
Name: "database-network-configuration",
140+
Category: "Databases DR",
141+
Usage: "Show network configuration of a database",
142+
ArgsUsage: "database-id",
143+
Flags: []cli.Flag{databaseFlag()},
144+
Description: CommandDescription{
145+
Description: "Get network configuration of a database",
146+
Examples: []string{
147+
"scalingo database-network-configuration my-db-id",
148+
"scalingo --database my-db database-network-configuration",
149+
},
150+
SeeAlso: []string{"database-net-peerings", "database-net-peerings-add", "database-net-peerings-remove"},
151+
}.Render(),
152+
Action: func(ctx context.Context, c *cli.Command) error {
153+
databaseID := detect.ExtractDatabaseNameFromCommandLineOrEnv(c)
154+
if databaseID == "" {
155+
return cli.ShowCommandHelp(ctx, c, "database-network-configuration")
156+
}
157+
158+
utils.CheckForConsent(ctx, databaseID, utils.ConsentTypeDBs)
159+
160+
err := dbng.DatabaseNetworkConfigurationShow(ctx, databaseID)
161+
if err != nil {
162+
errorQuit(ctx, err)
163+
}
164+
165+
return nil
166+
},
167+
ShellComplete: func(ctx context.Context, c *cli.Command) {
168+
_ = autocomplete.CmdFlagsAutoComplete(c, "database-network-configuration")
169+
_ = autocomplete.DatabasesNgListAutoComplete(ctx)
170+
},
171+
}
172+
)

cmd/error.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ func displayRequestFailedError(requestFailedErr *httpclient.RequestFailedError,
135135
fmt.Println(io.Indent(err.Error(), 7))
136136
}
137137

138+
case http.StatusConflict: // 409
139+
// In case of conflict error, we only want to display the API error.
140+
io.Errorf("%s\n", strings.ReplaceAll(requestFailedErr.Error(), `\n`, "\n"))
138141
case http.StatusUnprocessableEntity:
139142
unprocessableEntityErr, ok := requestFailedErr.APIError.(httpclient.UnprocessableEntity)
140143
if !ok {

cmd/firewall_rules.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717
var (
1818
databaseFirewallRulesListCommand = cli.Command{
1919
Name: "database-firewall-rules",
20-
Category: "Databases NG",
20+
Category: "Databases DR",
2121
Usage: "List firewall rules of a database",
2222
ArgsUsage: "database-id",
2323
Flags: []cli.Flag{databaseFlag()},
@@ -56,7 +56,7 @@ var (
5656

5757
databaseFirewallRulesAddCommand = cli.Command{
5858
Name: "database-firewall-rules-add",
59-
Category: "Databases NG",
59+
Category: "Databases DR",
6060
Usage: "Add a firewall rule to a database",
6161
ArgsUsage: "database-id",
6262
Flags: []cli.Flag{
@@ -133,7 +133,7 @@ var (
133133

134134
databaseFirewallRulesRemoveCommand = cli.Command{
135135
Name: "database-firewall-rules-remove",
136-
Category: "Databases NG",
136+
Category: "Databases DR",
137137
Usage: "Remove a firewall rule from a database",
138138
ArgsUsage: "database-id rule-id",
139139
Flags: []cli.Flag{databaseFlag()},
@@ -194,7 +194,7 @@ var (
194194

195195
databaseFirewallManagedRangesCommand = cli.Command{
196196
Name: "database-firewall-managed-ranges",
197-
Category: "Databases NG",
197+
Category: "Databases DR",
198198
Usage: "List available managed ranges for a database",
199199
ArgsUsage: "database-id",
200200
Flags: []cli.Flag{databaseFlag()},

dbng/networking.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package dbng
2+
3+
import (
4+
"context"
5+
"os"
6+
7+
"github.com/olekukonko/tablewriter"
8+
9+
"github.com/Scalingo/cli/config"
10+
"github.com/Scalingo/cli/io"
11+
"github.com/Scalingo/go-scalingo/v11"
12+
"github.com/Scalingo/go-utils/errors/v3"
13+
)
14+
15+
func DatabaseNetPeeringsList(ctx context.Context, databaseID string) error {
16+
c, err := config.ScalingoClient(ctx)
17+
if err != nil {
18+
return errors.Wrap(ctx, err, "get Scalingo client")
19+
}
20+
21+
netPeerings, err := c.Preview().DatabaseNetPeeringsList(ctx, databaseID)
22+
if err != nil {
23+
return errors.Wrap(ctx, err, "list database net peerings")
24+
}
25+
26+
if len(netPeerings) == 0 {
27+
io.Status("No net peering configured for this database.")
28+
return nil
29+
}
30+
31+
t := tablewriter.NewWriter(os.Stdout)
32+
t.Header([]string{"ID", "Status", "Outscale Net Peering ID", "Source Net ID", "Source Net IP Range", "Source Account ID"})
33+
34+
for _, netPeering := range netPeerings {
35+
_ = t.Append([]string{
36+
netPeering.ID,
37+
netPeering.Status,
38+
netPeering.OutscaleNetPeeringID,
39+
netPeering.OutscaleSourceNetID,
40+
netPeering.OutscaleSourceNetIPRange,
41+
netPeering.OutscaleSourceAccountID,
42+
})
43+
}
44+
45+
_ = t.Render()
46+
47+
return nil
48+
}
49+
50+
func DatabaseNetPeeringsAdd(ctx context.Context, databaseID string, params scalingo.DatabaseNetPeeringCreateParams) error {
51+
c, err := config.ScalingoClient(ctx)
52+
if err != nil {
53+
return errors.Wrap(ctx, err, "get Scalingo client")
54+
}
55+
56+
netPeering, err := c.Preview().DatabaseNetPeeringCreate(ctx, databaseID, params)
57+
if err != nil {
58+
return errors.Wrap(ctx, err, "add database net peering")
59+
}
60+
61+
io.Statusf("Net peering '%s' creation has been initiated for database '%s'.\n", netPeering.ID, databaseID)
62+
io.Warning("Expect some delay for the net peering to be applied.")
63+
64+
return nil
65+
}
66+
67+
func DatabaseNetPeeringsRemove(ctx context.Context, databaseID, netPeeringID string) error {
68+
c, err := config.ScalingoClient(ctx)
69+
if err != nil {
70+
return errors.Wrap(ctx, err, "get Scalingo client")
71+
}
72+
73+
err = c.Preview().DatabaseNetPeeringDestroy(ctx, databaseID, netPeeringID)
74+
if err != nil {
75+
return errors.Wrap(ctx, err, "remove database net peering")
76+
}
77+
78+
io.Statusf("Net peering '%s' has been removed from database '%s'.\n", netPeeringID, databaseID)
79+
io.Warning("Expect some delay for the net peering removal to be applied.")
80+
81+
return nil
82+
}
83+
84+
func DatabaseNetworkConfigurationShow(ctx context.Context, databaseID string) error {
85+
c, err := config.ScalingoClient(ctx)
86+
if err != nil {
87+
return errors.Wrap(ctx, err, "get Scalingo client")
88+
}
89+
90+
networkConfiguration, err := c.Preview().DatabaseNetworkConfigurationShow(ctx, databaseID)
91+
if err != nil {
92+
return errors.Wrap(ctx, err, "show database network configuration")
93+
}
94+
95+
t := tablewriter.NewWriter(os.Stdout)
96+
_ = t.Bulk([][]string{
97+
{"Outscale account ID", networkConfiguration.OutscaleAccountID},
98+
{"Outscale net ID", networkConfiguration.OutscaleNetID},
99+
{"IP range", networkConfiguration.IPRange},
100+
})
101+
_ = t.Render()
102+
103+
return nil
104+
}

detect/app.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ func CurrentApp(ctx context.Context, c *cli.Command) string {
159159
// It returns an empty string and errDatabaseNotFound error if the database name
160160
// is not provided or resource ID not found.
161161
func currentDatabaseNameAndUUID(ctx context.Context, c *cli.Command) (string, string, error) {
162-
dbName := extractDatabaseNameFromCommandLineOrEnv(c)
162+
dbName := ExtractDatabaseNameFromCommandLineOrEnv(c)
163163
if dbName == "" {
164164
return "", "", errDatabaseNotFound
165165
}
@@ -251,7 +251,7 @@ func extractAppName(ctx context.Context, c *cli.Command) string {
251251
return appName
252252
}
253253

254-
func extractDatabaseNameFromCommandLineOrEnv(c *cli.Command) string {
254+
func ExtractDatabaseNameFromCommandLineOrEnv(c *cli.Command) string {
255255
if os.Getenv("SCALINGO_PREVIEW_FEATURES") != "true" {
256256
return ""
257257
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.25.0
44

55
require (
66
github.com/AlecAivazis/survey/v2 v2.3.7
7-
github.com/Scalingo/go-scalingo/v11 v11.0.0
7+
github.com/Scalingo/go-scalingo/v11 v11.0.1-0.20260324141225-65ad50946664
88
github.com/Scalingo/go-utils/errors/v3 v3.2.0
99
github.com/Scalingo/go-utils/logger v1.12.0
1010
github.com/Scalingo/go-utils/pagination v1.2.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63n
99
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
1010
github.com/ProtonMail/go-crypto v1.4.0 h1:Zq/pbM3F5DFgJiMouxEdSVY44MVoQNEKp5d5QxIQceQ=
1111
github.com/ProtonMail/go-crypto v1.4.0/go.mod h1:e1OaTyu5SYVrO9gKOEhTc+5UcXtTUa+P3uLudwcgPqo=
12-
github.com/Scalingo/go-scalingo/v11 v11.0.0 h1:URWRLO4mK+06WMfA6065vVwKIL0k4146RCiZuxARWp4=
13-
github.com/Scalingo/go-scalingo/v11 v11.0.0/go.mod h1:SKmfy5pA4i9jb6Zxx5n2X9uh9Q7Hwkr1sCDICA/3Z4U=
12+
github.com/Scalingo/go-scalingo/v11 v11.0.1-0.20260324141225-65ad50946664 h1:lQZq8sA/yWk9SqHagP4p6xRqlnQf501SrBbcTbXbCmM=
13+
github.com/Scalingo/go-scalingo/v11 v11.0.1-0.20260324141225-65ad50946664/go.mod h1:SKmfy5pA4i9jb6Zxx5n2X9uh9Q7Hwkr1sCDICA/3Z4U=
1414
github.com/Scalingo/go-utils/errors/v3 v3.2.0 h1:Ks+v2oRwv3VZfe+xVB+kpfmZouXHVCPHHtwL5W60prc=
1515
github.com/Scalingo/go-utils/errors/v3 v3.2.0/go.mod h1:jVVNoOdYFjuNkR/BeEZWNWJVvu4jmyLY4udlsQQyBss=
1616
github.com/Scalingo/go-utils/logger v1.12.0 h1:tK1LwRz7ijYLGe7/c4SzAtNEJCbSPQnOo859O1FsOLM=

vendor/github.com/Scalingo/go-scalingo/v11/AGENTS.md

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)