Skip to content

Commit 796aea1

Browse files
committed
feat(iaas): List NICs for Project
relates to STACKITCLI-307 and #1214 tests added network ids included in list of project NICs
1 parent daf75d6 commit 796aea1

File tree

2 files changed

+155
-30
lines changed

2 files changed

+155
-30
lines changed

internal/cmd/network-interface/list/list.go

Lines changed: 69 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package list
22

33
import (
4+
"bytes"
45
"context"
56
"fmt"
7+
"sort"
68

9+
"github.com/stackitcloud/stackit-cli/internal/pkg/projectname"
710
"github.com/stackitcloud/stackit-cli/internal/pkg/types"
811

912
"github.com/spf13/cobra"
@@ -33,10 +36,6 @@ type inputModel struct {
3336
NetworkId string
3437
}
3538

36-
type ExecutableRequest interface {
37-
Execute() (*iaas.NICListResponse, error)
38-
}
39-
4039
func NewCmd(params *types.CmdParams) *cobra.Command {
4140
cmd := &cobra.Command{
4241
Use: "list",
@@ -79,23 +78,39 @@ func NewCmd(params *types.CmdParams) *cobra.Command {
7978
}
8079

8180
// Call API
82-
var req ExecutableRequest
83-
var networkLabel = ""
8481
if model.NetworkId == "" {
8582
// Return all NICs in the Project
86-
req = buildProjectRequest(ctx, model, apiClient)
87-
} else {
88-
// Return the NICs for one Network
89-
req = buildRequest(ctx, model, apiClient)
83+
req := buildProjectRequest(ctx, model, apiClient)
84+
projectLabel, err := projectname.GetProjectName(ctx, params.Printer, params.CliVersion, cmd)
85+
if err != nil {
86+
projectLabel = model.ProjectId
87+
}
9088

91-
networkLabel, err = iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, model.Region, model.NetworkId)
89+
resp, err := req.Execute()
9290
if err != nil {
93-
params.Printer.Debug(print.ErrorLevel, "get network name: %v", err)
94-
networkLabel = model.NetworkId
95-
} else if networkLabel == "" {
96-
networkLabel = model.NetworkId
91+
return fmt.Errorf("list network interfaces: %w", err)
92+
}
93+
94+
// Truncate output
95+
items := *resp.Items
96+
if model.Limit != nil && len(items) > int(*model.Limit) {
97+
items = items[:*model.Limit]
9798
}
99+
100+
return outputProjectResult(params.Printer, model.OutputFormat, items, projectLabel)
101+
}
102+
103+
// Return the NICs for one Network
104+
req := buildNetworkRequest(ctx, model, apiClient)
105+
106+
networkLabel, err := iaasUtils.GetNetworkName(ctx, apiClient, model.ProjectId, model.Region, model.NetworkId)
107+
if err != nil {
108+
params.Printer.Debug(print.ErrorLevel, "get network name: %v", err)
109+
networkLabel = model.NetworkId
110+
} else if networkLabel == "" {
111+
networkLabel = model.NetworkId
98112
}
113+
99114
resp, err := req.Execute()
100115
if err != nil {
101116
return fmt.Errorf("list network interfaces: %w", err)
@@ -107,7 +122,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command {
107122
items = items[:*model.Limit]
108123
}
109124

110-
return outputResult(params.Printer, model.OutputFormat, items, networkLabel)
125+
return outputNetworkResult(params.Printer, model.OutputFormat, items, networkLabel)
111126
},
112127
}
113128
configureFlags(cmd)
@@ -145,7 +160,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel,
145160
return &model, nil
146161
}
147162

148-
func buildProjectRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) ExecutableRequest {
163+
func buildProjectRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListProjectNICsRequest {
149164
req := apiClient.ListProjectNICs(ctx, model.ProjectId, model.Region)
150165
if model.LabelSelector != nil {
151166
req = req.LabelSelector(*model.LabelSelector)
@@ -154,7 +169,7 @@ func buildProjectRequest(ctx context.Context, model *inputModel, apiClient *iaas
154169
return req
155170
}
156171

157-
func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) ExecutableRequest {
172+
func buildNetworkRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiListNicsRequest {
158173
req := apiClient.ListNics(ctx, model.ProjectId, model.Region, model.NetworkId)
159174
if model.LabelSelector != nil {
160175
req = req.LabelSelector(*model.LabelSelector)
@@ -163,14 +178,44 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli
163178
return req
164179
}
165180

166-
func outputResult(p *print.Printer, outputFormat string, nics []iaas.NIC, networkLabel string) error {
181+
func outputProjectResult(p *print.Printer, outputFormat string, nics []iaas.NIC, projectLabel string) error {
167182
return p.OutputResult(outputFormat, nics, func() error {
168183
if len(nics) == 0 {
169-
if networkLabel == "" {
170-
p.Outputf("No network interfaces found for your current project\n")
171-
} else {
172-
p.Outputf("No network interfaces found for network %q\n", networkLabel)
173-
}
184+
p.Outputf("No network interfaces found for project %q\n", projectLabel)
185+
return nil
186+
}
187+
188+
sort.SliceStable(nics, func(i, j int) bool {
189+
result := bytes.Compare([]byte(*nics[i].NetworkId), []byte(*nics[j].NetworkId))
190+
return result == -1
191+
})
192+
193+
table := tables.NewTable()
194+
table.SetHeader("ID", "NAME", "NETWORK ID", "NIC SECURITY", "DEVICE ID", "IPv4 ADDRESS", "STATUS", "TYPE")
195+
196+
for _, nic := range nics {
197+
table.AddRow(
198+
utils.PtrString(nic.Id),
199+
utils.PtrString(nic.Name),
200+
utils.PtrString(nic.NetworkId),
201+
utils.PtrString(nic.NicSecurity),
202+
utils.PtrString(nic.Device),
203+
utils.PtrString(nic.Ipv4),
204+
utils.PtrString(nic.Status),
205+
utils.PtrString(nic.Type),
206+
)
207+
table.AddSeparator()
208+
}
209+
210+
p.Outputln(table.Render())
211+
return nil
212+
})
213+
}
214+
215+
func outputNetworkResult(p *print.Printer, outputFormat string, nics []iaas.NIC, networkLabel string) error {
216+
return p.OutputResult(outputFormat, nics, func() error {
217+
if len(nics) == 0 {
218+
p.Outputf("No network interfaces found for network %q\n", networkLabel)
174219
return nil
175220
}
176221

internal/cmd/network-interface/list/list_test.go

Lines changed: 86 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,16 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel {
6161
return model
6262
}
6363

64-
func fixtureRequest(mods ...func(request *iaas.ApiListNicsRequest)) iaas.ApiListNicsRequest {
64+
func fixtureProjectRequest(mods ...func(request *iaas.ApiListProjectNICsRequest)) iaas.ApiListProjectNICsRequest {
65+
request := testClient.ListProjectNICs(testCtx, testProjectId, testRegion)
66+
request = request.LabelSelector(testLabelSelector)
67+
for _, mod := range mods {
68+
mod(&request)
69+
}
70+
return request
71+
}
72+
73+
func fixtureNetworkRequest(mods ...func(request *iaas.ApiListNicsRequest)) iaas.ApiListNicsRequest {
6574
request := testClient.ListNics(testCtx, testProjectId, testRegion, testNetworkId)
6675
request = request.LabelSelector(testLabelSelector)
6776
for _, mod := range mods {
@@ -148,7 +157,35 @@ func TestParseInput(t *testing.T) {
148157
}
149158
}
150159

151-
func TestBuildRequest(t *testing.T) {
160+
func TestBuildProjectRequest(t *testing.T) {
161+
tests := []struct {
162+
description string
163+
model *inputModel
164+
expectedRequest iaas.ApiListProjectNICsRequest
165+
}{
166+
{
167+
description: "base",
168+
model: fixtureInputModel(),
169+
expectedRequest: fixtureProjectRequest(),
170+
},
171+
}
172+
173+
for _, tt := range tests {
174+
t.Run(tt.description, func(t *testing.T) {
175+
request := buildProjectRequest(testCtx, tt.model, testClient)
176+
177+
diff := cmp.Diff(request, tt.expectedRequest,
178+
cmp.AllowUnexported(tt.expectedRequest),
179+
cmpopts.EquateComparable(testCtx),
180+
)
181+
if diff != "" {
182+
t.Fatalf("Data does not match: %s", diff)
183+
}
184+
})
185+
}
186+
}
187+
188+
func TestBuildNetworkRequest(t *testing.T) {
152189
tests := []struct {
153190
description string
154191
model *inputModel
@@ -157,13 +194,13 @@ func TestBuildRequest(t *testing.T) {
157194
{
158195
description: "base",
159196
model: fixtureInputModel(),
160-
expectedRequest: fixtureRequest(),
197+
expectedRequest: fixtureNetworkRequest(),
161198
},
162199
}
163200

164201
for _, tt := range tests {
165202
t.Run(tt.description, func(t *testing.T) {
166-
request := buildRequest(testCtx, tt.model, testClient)
203+
request := buildNetworkRequest(testCtx, tt.model, testClient)
167204

168205
diff := cmp.Diff(request, tt.expectedRequest,
169206
cmp.AllowUnexported(tt.expectedRequest),
@@ -176,7 +213,7 @@ func TestBuildRequest(t *testing.T) {
176213
}
177214
}
178215

179-
func TestOutputResult(t *testing.T) {
216+
func TestOutputProjectResult(t *testing.T) {
180217
type args struct {
181218
outputFormat string
182219
nics []iaas.NIC
@@ -191,12 +228,55 @@ func TestOutputResult(t *testing.T) {
191228
args: args{},
192229
wantErr: false,
193230
},
231+
{
232+
name: "empty NIC in NIC-slice",
233+
args: args{
234+
outputFormat: print.PrettyOutputFormat,
235+
nics: []iaas.NIC{{}},
236+
},
237+
wantErr: false,
238+
},
239+
}
240+
p := print.NewPrinter()
241+
p.Cmd = NewCmd(&types.CmdParams{Printer: p})
242+
for _, tt := range tests {
243+
t.Run(tt.name, func(t *testing.T) {
244+
if err := outputProjectResult(p, tt.args.outputFormat, tt.args.nics, "Label"); (err != nil) != tt.wantErr {
245+
t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr)
246+
}
247+
})
248+
}
249+
}
250+
251+
func TestOutputNetworkResult(t *testing.T) {
252+
type args struct {
253+
outputFormat string
254+
nics []iaas.NIC
255+
}
256+
tests := []struct {
257+
name string
258+
args args
259+
wantErr bool
260+
}{
261+
{
262+
name: "empty",
263+
args: args{},
264+
wantErr: false,
265+
},
266+
{
267+
name: "empty NIC in NIC-slice",
268+
args: args{
269+
outputFormat: print.PrettyOutputFormat,
270+
nics: []iaas.NIC{{}},
271+
},
272+
wantErr: false,
273+
},
194274
}
195275
p := print.NewPrinter()
196276
p.Cmd = NewCmd(&types.CmdParams{Printer: p})
197277
for _, tt := range tests {
198278
t.Run(tt.name, func(t *testing.T) {
199-
if err := outputResult(p, tt.args.outputFormat, tt.args.nics, "Label"); (err != nil) != tt.wantErr {
279+
if err := outputNetworkResult(p, tt.args.outputFormat, tt.args.nics, "Label"); (err != nil) != tt.wantErr {
200280
t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr)
201281
}
202282
})

0 commit comments

Comments
 (0)