Skip to content

Commit

Permalink
Onboard IaaS server network interface commands (#519)
Browse files Browse the repository at this point in the history
Supported commands: attach, detach, list

Signed-off-by: Alexander Dahmen <[email protected]>
  • Loading branch information
Fyusel authored Dec 9, 2024
1 parent 6100860 commit c3c4765
Show file tree
Hide file tree
Showing 14 changed files with 1,574 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/stackit_beta_server.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ stackit beta server [flags]
* [stackit beta server delete](./stackit_beta_server_delete.md) - Deletes a server
* [stackit beta server describe](./stackit_beta_server_describe.md) - Shows details of a server
* [stackit beta server list](./stackit_beta_server_list.md) - Lists all servers of a project
* [stackit beta server network-interface](./stackit_beta_server_network-interface.md) - Allows attaching/detaching network interfaces to servers
* [stackit beta server public-ip](./stackit_beta_server_public-ip.md) - Allows attaching/detaching public IPs to servers
* [stackit beta server update](./stackit_beta_server_update.md) - Updates a server
* [stackit beta server volume](./stackit_beta_server_volume.md) - Provides functionality for server volumes
Expand Down
35 changes: 35 additions & 0 deletions docs/stackit_beta_server_network-interface.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
## stackit beta server network-interface

Allows attaching/detaching network interfaces to servers

### Synopsis

Allows attaching/detaching network interfaces to servers.

```
stackit beta server network-interface [flags]
```

### Options

```
-h, --help Help for "stackit beta server network-interface"
```

### Options inherited from parent commands

```
-y, --assume-yes If set, skips all confirmation prompts
--async If set, runs the command asynchronously
-o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"]
-p, --project-id string Project ID
--verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info")
```

### SEE ALSO

* [stackit beta server](./stackit_beta_server.md) - Provides functionality for servers
* [stackit beta server network-interface attach](./stackit_beta_server_network-interface_attach.md) - Attaches a network interface to a server
* [stackit beta server network-interface detach](./stackit_beta_server_network-interface_detach.md) - Detaches a network interface from a server
* [stackit beta server network-interface list](./stackit_beta_server_network-interface_list.md) - Lists all attached network interfaces of a server

46 changes: 46 additions & 0 deletions docs/stackit_beta_server_network-interface_attach.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
## stackit beta server network-interface attach

Attaches a network interface to a server

### Synopsis

Attaches a network interface to a server.

```
stackit beta server network-interface attach [flags]
```

### Examples

```
Attach a network interface with ID "xxx" to a server with ID "yyy"
$ stackit beta server network-interface attach --network-interface-id xxx --server-id yyy
Create a network interface for network with ID "xxx" and attach it to a server with ID "yyy"
$ stackit beta server network-interface attach --network-id xxx --server-id yyy --create
```

### Options

```
-b, --create If this is set a network interface will be created. (default false)
-h, --help Help for "stackit beta server network-interface attach"
--network-id string Network ID
--network-interface-id string Network Interface ID
--server-id string Server ID
```

### Options inherited from parent commands

```
-y, --assume-yes If set, skips all confirmation prompts
--async If set, runs the command asynchronously
-o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"]
-p, --project-id string Project ID
--verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info")
```

### SEE ALSO

* [stackit beta server network-interface](./stackit_beta_server_network-interface.md) - Allows attaching/detaching network interfaces to servers

46 changes: 46 additions & 0 deletions docs/stackit_beta_server_network-interface_detach.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
## stackit beta server network-interface detach

Detaches a network interface from a server

### Synopsis

Detaches a network interface from a server.

```
stackit beta server network-interface detach [flags]
```

### Examples

```
Detach a network interface with ID "xxx" from a server with ID "yyy"
$ stackit beta server network-interface detach --network-interface-id xxx --server-id yyy
Detach and delete all network interfaces for network with ID "xxx" and detach them from a server with ID "yyy"
$ stackit beta server network-interface detach --network-id xxx --server-id yyy --delete
```

### Options

```
-b, --delete If this is set all network interfaces will be deleted. (default false)
-h, --help Help for "stackit beta server network-interface detach"
--network-id string Network ID
--network-interface-id string Network Interface ID
--server-id string Server ID
```

### Options inherited from parent commands

```
-y, --assume-yes If set, skips all confirmation prompts
--async If set, runs the command asynchronously
-o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"]
-p, --project-id string Project ID
--verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info")
```

### SEE ALSO

* [stackit beta server network-interface](./stackit_beta_server_network-interface.md) - Allows attaching/detaching network interfaces to servers

47 changes: 47 additions & 0 deletions docs/stackit_beta_server_network-interface_list.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
## stackit beta server network-interface list

Lists all attached network interfaces of a server

### Synopsis

Lists all attached network interfaces of a server.

```
stackit beta server network-interface list [flags]
```

### Examples

```
Lists all attached network interfaces of server with ID "xxx"
$ stackit beta server network-interface list --server-id xxx
Lists all attached network interfaces of server with ID "xxx" in JSON format
$ stackit beta server network-interface list --server-id xxx --output-format json
Lists up to 10 attached network interfaces of server with ID "xxx"
$ stackit beta server network-interface list --server-id xxx --limit 10
```

### Options

```
-h, --help Help for "stackit beta server network-interface list"
--limit int Maximum number of entries to list
--server-id string Server ID
```

### Options inherited from parent commands

```
-y, --assume-yes If set, skips all confirmation prompts
--async If set, runs the command asynchronously
-o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"]
-p, --project-id string Project ID
--verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info")
```

### SEE ALSO

* [stackit beta server network-interface](./stackit_beta_server_network-interface.md) - Allows attaching/detaching network interfaces to servers

171 changes: 171 additions & 0 deletions internal/cmd/beta/server/network-interface/attach/attach.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package attach

import (
"context"
"fmt"

"github.com/spf13/cobra"
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
"github.com/stackitcloud/stackit-cli/internal/pkg/errors"
cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors"
"github.com/stackitcloud/stackit-cli/internal/pkg/examples"
"github.com/stackitcloud/stackit-cli/internal/pkg/flags"
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
"github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client"
iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils"
"github.com/stackitcloud/stackit-sdk-go/services/iaas"
)

const (
serverIdFlag = "server-id"
networkInterfaceIdFlag = "network-interface-id"
createFlag = "create"
networkIdFlag = "network-id"

defaultCreateFlag = false
)

type inputModel struct {
*globalflags.GlobalFlagModel
ServerId *string
NicId *string
NetworkId *string
Create *bool
}

func NewCmd(p *print.Printer) *cobra.Command {
cmd := &cobra.Command{
Use: "attach",
Short: "Attaches a network interface to a server",
Long: "Attaches a network interface to a server.",
Args: args.NoArgs,
Example: examples.Build(
examples.NewExample(
`Attach a network interface with ID "xxx" to a server with ID "yyy"`,
`$ stackit beta server network-interface attach --network-interface-id xxx --server-id yyy`,
),
examples.NewExample(
`Create a network interface for network with ID "xxx" and attach it to a server with ID "yyy"`,
`$ stackit beta server network-interface attach --network-id xxx --server-id yyy --create`,
),
),
RunE: func(cmd *cobra.Command, _ []string) error {
ctx := context.Background()
model, err := parseInput(p, cmd)
if err != nil {
return err
}

// Configure API client
apiClient, err := client.ConfigureClient(p)
if err != nil {
return err
}

serverLabel, err := iaasUtils.GetServerName(ctx, apiClient, model.ProjectId, *model.ServerId)
if err != nil {
p.Debug(print.ErrorLevel, "get server name: %v", err)
serverLabel = *model.ServerId
}

// if the create flag is provided a network interface will be created and attached
if model.Create != nil && *model.Create {
networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, *model.NetworkId)
if err != nil {
p.Debug(print.ErrorLevel, "get network name: %v", err)
networkLabel = *model.NetworkId
}
if !model.AssumeYes {
prompt := fmt.Sprintf("Are you sure you want to create a network interface for network %q and attach it to server %q?", networkLabel, serverLabel)
err = p.PromptForConfirmation(prompt)
if err != nil {
return err
}
}
// Call API
req := buildRequestCreateAndAttach(ctx, model, apiClient)
err = req.Execute()
if err != nil {
return fmt.Errorf("create and attach network interface: %w", err)
}
p.Info("Created a network interface for network %q and attached it to server %q\n", networkLabel, serverLabel)
return nil
}

if !model.AssumeYes {
prompt := fmt.Sprintf("Are you sure you want to attach network interface %q to server %q?", *model.NicId, serverLabel)
err = p.PromptForConfirmation(prompt)
if err != nil {
return err
}
}
// Call API
req := buildRequestAttach(ctx, model, apiClient)
err = req.Execute()
if err != nil {
return fmt.Errorf("attach network interface: %w", err)
}
p.Info("Attached network interface %q to server %q\n", *model.NicId, serverLabel)

return nil
},
}
configureFlags(cmd)
return cmd
}

func configureFlags(cmd *cobra.Command) {
cmd.Flags().Var(flags.UUIDFlag(), serverIdFlag, "Server ID")
cmd.Flags().Var(flags.UUIDFlag(), networkInterfaceIdFlag, "Network Interface ID")
cmd.Flags().Var(flags.UUIDFlag(), networkIdFlag, "Network ID")
cmd.Flags().BoolP(createFlag, "b", defaultCreateFlag, "If this is set a network interface will be created. (default false)")

cmd.MarkFlagsRequiredTogether(createFlag, networkIdFlag)
cmd.MarkFlagsMutuallyExclusive(createFlag, networkInterfaceIdFlag)
cmd.MarkFlagsMutuallyExclusive(networkIdFlag, networkInterfaceIdFlag)

err := flags.MarkFlagsRequired(cmd, serverIdFlag)
cobra.CheckErr(err)
}

func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) {
globalFlags := globalflags.Parse(p, cmd)
if globalFlags.ProjectId == "" {
return nil, &errors.ProjectIdError{}
}

// if create is not provided then network-interface-id is needed
networkInterfaceId := flags.FlagToStringPointer(p, cmd, networkInterfaceIdFlag)
create := flags.FlagToBoolPointer(p, cmd, createFlag)
if create == nil && networkInterfaceId == nil {
return nil, &cliErr.ServerNicAttachMissingNicIdError{Cmd: cmd}
}

model := inputModel{
GlobalFlagModel: globalFlags,
ServerId: flags.FlagToStringPointer(p, cmd, serverIdFlag),
NetworkId: flags.FlagToStringPointer(p, cmd, networkIdFlag),
NicId: networkInterfaceId,
Create: create,
}

if p.IsVerbosityDebug() {
modelStr, err := print.BuildDebugStrFromInputModel(model)
if err != nil {
p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err)
} else {
p.Debug(print.DebugLevel, "parsed input values: %s", modelStr)
}
}

return &model, nil
}

func buildRequestAttach(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiAddNicToServerRequest {
return apiClient.AddNicToServer(ctx, model.ProjectId, *model.ServerId, *model.NicId)
}

func buildRequestCreateAndAttach(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiAddNetworkToServerRequest {
return apiClient.AddNetworkToServer(ctx, model.ProjectId, *model.ServerId, *model.NetworkId)
}
Loading

0 comments on commit c3c4765

Please sign in to comment.