Skip to content

Commit c3c4765

Browse files
authored
Onboard IaaS server network interface commands (#519)
Supported commands: attach, detach, list Signed-off-by: Alexander Dahmen <[email protected]>
1 parent 6100860 commit c3c4765

14 files changed

+1574
-0
lines changed

docs/stackit_beta_server.md

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ stackit beta server [flags]
3535
* [stackit beta server delete](./stackit_beta_server_delete.md) - Deletes a server
3636
* [stackit beta server describe](./stackit_beta_server_describe.md) - Shows details of a server
3737
* [stackit beta server list](./stackit_beta_server_list.md) - Lists all servers of a project
38+
* [stackit beta server network-interface](./stackit_beta_server_network-interface.md) - Allows attaching/detaching network interfaces to servers
3839
* [stackit beta server public-ip](./stackit_beta_server_public-ip.md) - Allows attaching/detaching public IPs to servers
3940
* [stackit beta server update](./stackit_beta_server_update.md) - Updates a server
4041
* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for server volumes
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
## stackit beta server network-interface
2+
3+
Allows attaching/detaching network interfaces to servers
4+
5+
### Synopsis
6+
7+
Allows attaching/detaching network interfaces to servers.
8+
9+
```
10+
stackit beta server network-interface [flags]
11+
```
12+
13+
### Options
14+
15+
```
16+
-h, --help Help for "stackit beta server network-interface"
17+
```
18+
19+
### Options inherited from parent commands
20+
21+
```
22+
-y, --assume-yes If set, skips all confirmation prompts
23+
--async If set, runs the command asynchronously
24+
-o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"]
25+
-p, --project-id string Project ID
26+
--verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info")
27+
```
28+
29+
### SEE ALSO
30+
31+
* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers
32+
* [stackit beta server network-interface attach](./stackit_beta_server_network-interface_attach.md) - Attaches a network interface to a server
33+
* [stackit beta server network-interface detach](./stackit_beta_server_network-interface_detach.md) - Detaches a network interface from a server
34+
* [stackit beta server network-interface list](./stackit_beta_server_network-interface_list.md) - Lists all attached network interfaces of a server
35+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
## stackit beta server network-interface attach
2+
3+
Attaches a network interface to a server
4+
5+
### Synopsis
6+
7+
Attaches a network interface to a server.
8+
9+
```
10+
stackit beta server network-interface attach [flags]
11+
```
12+
13+
### Examples
14+
15+
```
16+
Attach a network interface with ID "xxx" to a server with ID "yyy"
17+
$ stackit beta server network-interface attach --network-interface-id xxx --server-id yyy
18+
19+
Create a network interface for network with ID "xxx" and attach it to a server with ID "yyy"
20+
$ stackit beta server network-interface attach --network-id xxx --server-id yyy --create
21+
```
22+
23+
### Options
24+
25+
```
26+
-b, --create If this is set a network interface will be created. (default false)
27+
-h, --help Help for "stackit beta server network-interface attach"
28+
--network-id string Network ID
29+
--network-interface-id string Network Interface ID
30+
--server-id string Server ID
31+
```
32+
33+
### Options inherited from parent commands
34+
35+
```
36+
-y, --assume-yes If set, skips all confirmation prompts
37+
--async If set, runs the command asynchronously
38+
-o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"]
39+
-p, --project-id string Project ID
40+
--verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info")
41+
```
42+
43+
### SEE ALSO
44+
45+
* [stackit beta server network-interface](./stackit_beta_server_network-interface.md) - Allows attaching/detaching network interfaces to servers
46+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
## stackit beta server network-interface detach
2+
3+
Detaches a network interface from a server
4+
5+
### Synopsis
6+
7+
Detaches a network interface from a server.
8+
9+
```
10+
stackit beta server network-interface detach [flags]
11+
```
12+
13+
### Examples
14+
15+
```
16+
Detach a network interface with ID "xxx" from a server with ID "yyy"
17+
$ stackit beta server network-interface detach --network-interface-id xxx --server-id yyy
18+
19+
Detach and delete all network interfaces for network with ID "xxx" and detach them from a server with ID "yyy"
20+
$ stackit beta server network-interface detach --network-id xxx --server-id yyy --delete
21+
```
22+
23+
### Options
24+
25+
```
26+
-b, --delete If this is set all network interfaces will be deleted. (default false)
27+
-h, --help Help for "stackit beta server network-interface detach"
28+
--network-id string Network ID
29+
--network-interface-id string Network Interface ID
30+
--server-id string Server ID
31+
```
32+
33+
### Options inherited from parent commands
34+
35+
```
36+
-y, --assume-yes If set, skips all confirmation prompts
37+
--async If set, runs the command asynchronously
38+
-o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"]
39+
-p, --project-id string Project ID
40+
--verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info")
41+
```
42+
43+
### SEE ALSO
44+
45+
* [stackit beta server network-interface](./stackit_beta_server_network-interface.md) - Allows attaching/detaching network interfaces to servers
46+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
## stackit beta server network-interface list
2+
3+
Lists all attached network interfaces of a server
4+
5+
### Synopsis
6+
7+
Lists all attached network interfaces of a server.
8+
9+
```
10+
stackit beta server network-interface list [flags]
11+
```
12+
13+
### Examples
14+
15+
```
16+
Lists all attached network interfaces of server with ID "xxx"
17+
$ stackit beta server network-interface list --server-id xxx
18+
19+
Lists all attached network interfaces of server with ID "xxx" in JSON format
20+
$ stackit beta server network-interface list --server-id xxx --output-format json
21+
22+
Lists up to 10 attached network interfaces of server with ID "xxx"
23+
$ stackit beta server network-interface list --server-id xxx --limit 10
24+
```
25+
26+
### Options
27+
28+
```
29+
-h, --help Help for "stackit beta server network-interface list"
30+
--limit int Maximum number of entries to list
31+
--server-id string Server ID
32+
```
33+
34+
### Options inherited from parent commands
35+
36+
```
37+
-y, --assume-yes If set, skips all confirmation prompts
38+
--async If set, runs the command asynchronously
39+
-o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"]
40+
-p, --project-id string Project ID
41+
--verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info")
42+
```
43+
44+
### SEE ALSO
45+
46+
* [stackit beta server network-interface](./stackit_beta_server_network-interface.md) - Allows attaching/detaching network interfaces to servers
47+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
package attach
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/spf13/cobra"
8+
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
9+
"github.com/stackitcloud/stackit-cli/internal/pkg/errors"
10+
cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors"
11+
"github.com/stackitcloud/stackit-cli/internal/pkg/examples"
12+
"github.com/stackitcloud/stackit-cli/internal/pkg/flags"
13+
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
14+
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
15+
"github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client"
16+
iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils"
17+
"github.com/stackitcloud/stackit-sdk-go/services/iaas"
18+
)
19+
20+
const (
21+
serverIdFlag = "server-id"
22+
networkInterfaceIdFlag = "network-interface-id"
23+
createFlag = "create"
24+
networkIdFlag = "network-id"
25+
26+
defaultCreateFlag = false
27+
)
28+
29+
type inputModel struct {
30+
*globalflags.GlobalFlagModel
31+
ServerId *string
32+
NicId *string
33+
NetworkId *string
34+
Create *bool
35+
}
36+
37+
func NewCmd(p *print.Printer) *cobra.Command {
38+
cmd := &cobra.Command{
39+
Use: "attach",
40+
Short: "Attaches a network interface to a server",
41+
Long: "Attaches a network interface to a server.",
42+
Args: args.NoArgs,
43+
Example: examples.Build(
44+
examples.NewExample(
45+
`Attach a network interface with ID "xxx" to a server with ID "yyy"`,
46+
`$ stackit beta server network-interface attach --network-interface-id xxx --server-id yyy`,
47+
),
48+
examples.NewExample(
49+
`Create a network interface for network with ID "xxx" and attach it to a server with ID "yyy"`,
50+
`$ stackit beta server network-interface attach --network-id xxx --server-id yyy --create`,
51+
),
52+
),
53+
RunE: func(cmd *cobra.Command, _ []string) error {
54+
ctx := context.Background()
55+
model, err := parseInput(p, cmd)
56+
if err != nil {
57+
return err
58+
}
59+
60+
// Configure API client
61+
apiClient, err := client.ConfigureClient(p)
62+
if err != nil {
63+
return err
64+
}
65+
66+
serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId)
67+
if err != nil {
68+
p.Debug(print.ErrorLevel, "get server name: %v", err)
69+
serverLabel = *model.ServerId
70+
}
71+
72+
// if the create flag is provided a network interface will be created and attached
73+
if model.Create != nil && *model.Create {
74+
networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, *model.NetworkId)
75+
if err != nil {
76+
p.Debug(print.ErrorLevel, "get network name: %v", err)
77+
networkLabel = *model.NetworkId
78+
}
79+
if !model.AssumeYes {
80+
prompt := fmt.Sprintf("Are you sure you want to create a network interface for network %q and attach it to server %q?", networkLabel, serverLabel)
81+
err = p.PromptForConfirmation(prompt)
82+
if err != nil {
83+
return err
84+
}
85+
}
86+
// Call API
87+
req := buildRequestCreateAndAttach(ctx, model, apiClient)
88+
err = req.Execute()
89+
if err != nil {
90+
return fmt.Errorf("create and attach network interface: %w", err)
91+
}
92+
p.Info("Created a network interface for network %q and attached it to server %q\n", networkLabel, serverLabel)
93+
return nil
94+
}
95+
96+
if !model.AssumeYes {
97+
prompt := fmt.Sprintf("Are you sure you want to attach network interface %q to server %q?", *model.NicId, serverLabel)
98+
err = p.PromptForConfirmation(prompt)
99+
if err != nil {
100+
return err
101+
}
102+
}
103+
// Call API
104+
req := buildRequestAttach(ctx, model, apiClient)
105+
err = req.Execute()
106+
if err != nil {
107+
return fmt.Errorf("attach network interface: %w", err)
108+
}
109+
p.Info("Attached network interface %q to server %q\n", *model.NicId, serverLabel)
110+
111+
return nil
112+
},
113+
}
114+
configureFlags(cmd)
115+
return cmd
116+
}
117+
118+
func configureFlags(cmd *cobra.Command) {
119+
cmd.Flags().Var(flags.UUIDFlag(), serverIdFlag, "Server ID")
120+
cmd.Flags().Var(flags.UUIDFlag(), networkInterfaceIdFlag, "Network Interface ID")
121+
cmd.Flags().Var(flags.UUIDFlag(), networkIdFlag, "Network ID")
122+
cmd.Flags().BoolP(createFlag, "b", defaultCreateFlag, "If this is set a network interface will be created. (default false)")
123+
124+
cmd.MarkFlagsRequiredTogether(createFlag, networkIdFlag)
125+
cmd.MarkFlagsMutuallyExclusive(createFlag, networkInterfaceIdFlag)
126+
cmd.MarkFlagsMutuallyExclusive(networkIdFlag, networkInterfaceIdFlag)
127+
128+
err := flags.MarkFlagsRequired(cmd, serverIdFlag)
129+
cobra.CheckErr(err)
130+
}
131+
132+
func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) {
133+
globalFlags := globalflags.Parse(p, cmd)
134+
if globalFlags.ProjectId == "" {
135+
return nil, &errors.ProjectIdError{}
136+
}
137+
138+
// if create is not provided then network-interface-id is needed
139+
networkInterfaceId := flags.FlagToStringPointer(p, cmd, networkInterfaceIdFlag)
140+
create := flags.FlagToBoolPointer(p, cmd, createFlag)
141+
if create == nil && networkInterfaceId == nil {
142+
return nil, &cliErr.ServerNicAttachMissingNicIdError{Cmd: cmd}
143+
}
144+
145+
model := inputModel{
146+
GlobalFlagModel: globalFlags,
147+
ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag),
148+
NetworkId: flags.FlagToStringPointer(p, cmd, networkIdFlag),
149+
NicId: networkInterfaceId,
150+
Create: create,
151+
}
152+
153+
if p.IsVerbosityDebug() {
154+
modelStr, err := print.BuildDebugStrFromInputModel(model)
155+
if err != nil {
156+
p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err)
157+
} else {
158+
p.Debug(print.DebugLevel, "parsed input values: %s", modelStr)
159+
}
160+
}
161+
162+
return &model, nil
163+
}
164+
165+
func buildRequestAttach(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiAddNicToServerRequest {
166+
return apiClient.AddNicToServer(ctx, model.ProjectId, *model.ServerId, *model.NicId)
167+
}
168+
169+
func buildRequestCreateAndAttach(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiAddNetworkToServerRequest {
170+
return apiClient.AddNetworkToServer(ctx, model.ProjectId, *model.ServerId, *model.NetworkId)
171+
}

0 commit comments

Comments
 (0)