Skip to content

Commit 9306160

Browse files
committed
feat: json yaml and text outputs
1 parent 758fd75 commit 9306160

12 files changed

Lines changed: 148 additions & 53 deletions

File tree

cmd/array.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,18 @@ import (
44
"fmt"
55

66
"github.com/spf13/cobra"
7+
"github.com/unshade/unraidctl/internal"
78
"github.com/unshade/unraidctl/internal/controllers"
89
)
910

1011
// arrayCmd represents the array command
1112
var arrayCmd = &cobra.Command{
1213
Use: "array",
1314
Short: "Interact with unraid array",
14-
Long: `Interact with unraid array`,
15+
Long: `Interact with unraid array`,
1516
Run: func(cmd *cobra.Command, args []string) {
16-
controller := controllers.NewArrayController(unraidClient)
17+
formater := internal.OutputFormaterSwitcher(internal.OutputFormat(outputFormat))
18+
controller := controllers.NewArrayController(unraidClient, formater)
1719
switch args[0] {
1820
case "stop":
1921
controller.StopArray(cmd.Context())
@@ -31,4 +33,5 @@ func init() {
3133
rootCmd.AddCommand(arrayCmd)
3234
arrayCmd.Args = cobra.MinimumNArgs(1)
3335
arrayCmd.ValidArgs = []string{"stop", "start", "show"}
36+
arrayCmd.Flags().StringVarP(&outputFormat, "output", "o", "text", "Output format: json|yaml|text")
3437
}

cmd/docker.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cmd
22

33
import (
44
"github.com/spf13/cobra"
5+
"github.com/unshade/unraidctl/internal"
56
"github.com/unshade/unraidctl/internal/controllers"
67
)
78

@@ -10,7 +11,8 @@ var dockerCmd = &cobra.Command{
1011
Short: "Interact with unraid Docker engine",
1112
Long: `Interact with unraid Docker engine`,
1213
Run: func(cmd *cobra.Command, args []string) {
13-
controller := controllers.NewDockerController(unraidClient)
14+
formater := internal.OutputFormaterSwitcher(internal.OutputFormat(outputFormat))
15+
controller := controllers.NewDockerController(unraidClient, formater)
1416
switch args[0] {
1517
case "list":
1618
controller.ListContainers(cmd.Context())
@@ -27,4 +29,5 @@ func init() {
2729

2830
dockerCmd.Args = cobra.MinimumNArgs(1)
2931
dockerCmd.ValidArgs = []string{"stop", "restart", "start", "list"}
32+
dockerCmd.Flags().StringVarP(&outputFormat, "output", "o", "text", "Output format: json|yaml|text")
3033
}

cmd/root.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ import (
99
"github.com/unshade/unraidctl/pkg/client"
1010
)
1111

12-
var unraidClient *client.UnraidClient
12+
var (
13+
outputFormat string
14+
unraidClient *client.UnraidClient
15+
)
1316

1417
// rootCmd represents the base command when called without any subcommands
1518
var rootCmd = &cobra.Command{

cmd/vm.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cmd
22

33
import (
44
"github.com/spf13/cobra"
5+
"github.com/unshade/unraidctl/internal"
56
"github.com/unshade/unraidctl/internal/controllers"
67
)
78

@@ -11,7 +12,8 @@ var vmCmd = &cobra.Command{
1112
Short: "Interact with unraid virtual machines",
1213
Long: `Interact with unraid virtual machines. This command allows you to manage your VMs, including starting, stopping, and listing them`,
1314
Run: func(cmd *cobra.Command, args []string) {
14-
controller := controllers.NewVmController(unraidClient)
15+
formater := internal.OutputFormaterSwitcher(internal.OutputFormat(outputFormat))
16+
controller := controllers.NewVmController(unraidClient, formater)
1517
switch args[0] {
1618
case "list":
1719
controller.ListVMs(cmd.Context())
@@ -26,6 +28,7 @@ var vmCmd = &cobra.Command{
2628
func init() {
2729
rootCmd.AddCommand(vmCmd)
2830

29-
dockerCmd.Args = cobra.MinimumNArgs(1)
30-
dockerCmd.ValidArgs = []string{"force-stop", "pause", "reboot", "reset", "resume", "start", "stop"}
31+
vmCmd.Args = cobra.MinimumNArgs(1)
32+
vmCmd.ValidArgs = []string{"force-stop", "pause", "reboot", "reset", "resume", "start", "stop"}
33+
vmCmd.Flags().StringVarP(&outputFormat, "output", "o", "text", "Output format: json|yaml|text")
3134
}

internal/controllers/array.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,46 @@ package controllers
33
import (
44
"context"
55
"fmt"
6-
"strings"
76

7+
"github.com/unshade/unraidctl/internal"
88
"github.com/unshade/unraidctl/pkg/client"
99
)
1010

1111
type ArrayController struct {
1212
unraidClient *client.UnraidClient
13+
formater internal.OutputFormater
1314
}
1415

15-
func NewArrayController(unraidClient *client.UnraidClient) *ArrayController {
16+
func NewArrayController(unraidClient *client.UnraidClient, formater internal.OutputFormater) *ArrayController {
1617
return &ArrayController{
1718
unraidClient: unraidClient,
19+
formater: formater,
1820
}
1921
}
2022

2123
func (c *ArrayController) ShowArray(ctx context.Context) {
22-
respData, err := c.unraidClient.Array.ShowArray(ctx)
24+
response, err := c.unraidClient.Array.ShowArray(ctx)
2325
if err != nil {
2426
fmt.Printf("Error showing array: %v\n", err)
2527
return
2628
}
27-
fmt.Printf("Array State: %s\n", strings.ToLower(respData.Array.State))
29+
internal.PrintFormat(c.formater.Format(response))
2830
}
2931

3032
func (c *ArrayController) StopArray(ctx context.Context) {
31-
_, err := c.unraidClient.Array.MutateArray(ctx, client.ArrayStateStop)
33+
response, err := c.unraidClient.Array.MutateArray(ctx, client.ArrayStateStop)
3234
if err != nil {
3335
fmt.Printf("Error stopping array: %v\n", err)
3436
return
3537
}
38+
internal.PrintFormat(c.formater.Format(response))
3639
}
3740

3841
func (c *ArrayController) StartArray(ctx context.Context) {
39-
_, err := c.unraidClient.Array.MutateArray(ctx, client.ArrayStateStart)
42+
response, err := c.unraidClient.Array.MutateArray(ctx, client.ArrayStateStart)
4043
if err != nil {
4144
fmt.Printf("Error starting array: %v\n", err)
4245
return
4346
}
47+
internal.PrintFormat(c.formater.Format(response))
4448
}

internal/controllers/docker.go

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,49 +3,44 @@ package controllers
33
import (
44
"context"
55
"fmt"
6-
"strings"
76

7+
"github.com/unshade/unraidctl/internal"
88
"github.com/unshade/unraidctl/pkg/client"
99
)
1010

1111
type DockerController struct {
1212
unraidClient *client.UnraidClient
13+
formater internal.OutputFormater
1314
}
1415

15-
func NewDockerController(unraidClient *client.UnraidClient) *DockerController {
16+
func NewDockerController(unraidClient *client.UnraidClient, formater internal.OutputFormater) *DockerController {
1617
return &DockerController{
1718
unraidClient: unraidClient,
19+
formater: formater,
1820
}
1921
}
2022

2123
func (c *DockerController) ListContainers(ctx context.Context) {
22-
respData, err := c.unraidClient.Docker.ListContainers(ctx)
24+
response, err := c.unraidClient.Docker.ListContainers(ctx)
2325
if err != nil {
2426
fmt.Printf("Error listing containers: %v\n", err)
2527
return
2628
}
27-
for _, container := range respData.Docker.Containers {
28-
idParts := strings.Split(container.ID, ":")
29-
compactID := idParts[len(idParts)-1]
30-
31-
if len(compactID) > 12 {
32-
compactID = compactID[:12]
33-
}
34-
35-
fmt.Printf("ID: %s | Image: %s | State: %s\n", compactID, container.Image, container.State)
36-
}
29+
internal.PrintFormat(c.formater.Format(response))
3730
}
3831

3932
func (c *DockerController) StartContainer(ctx context.Context, containerid string) {
40-
_, err := c.unraidClient.Docker.StartContainer(ctx, containerid)
33+
response, err := c.unraidClient.Docker.StartContainer(ctx, containerid)
4134
if err != nil {
4235
fmt.Printf("Could not start container: %v", err)
4336
}
37+
internal.PrintFormat(c.formater.Format(response))
4438
}
4539

4640
func (c *DockerController) StopContainer(ctx context.Context, containerid string) {
47-
_, err := c.unraidClient.Docker.StopContainer(ctx, containerid)
41+
response, err := c.unraidClient.Docker.StopContainer(ctx, containerid)
4842
if err != nil {
4943
fmt.Printf("Could not stop container: %v", err)
5044
}
45+
internal.PrintFormat(c.formater.Format(response))
5146
}

internal/controllers/vm.go

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,45 +3,42 @@ package controllers
33
import (
44
"context"
55
"fmt"
6-
"strings"
76

7+
"github.com/unshade/unraidctl/internal"
88
"github.com/unshade/unraidctl/pkg/client"
99
)
1010

1111
type VmController struct {
1212
unraidClient *client.UnraidClient
13+
formater internal.OutputFormater
1314
}
1415

15-
func NewVmController(unraidClient *client.UnraidClient) *VmController {
16+
func NewVmController(unraidClient *client.UnraidClient, formater internal.OutputFormater) *VmController {
1617
return &VmController{
1718
unraidClient: unraidClient,
19+
formater: formater,
1820
}
1921
}
2022

2123
func (c *VmController) ListVMs(ctx context.Context) {
22-
respData, err := c.unraidClient.VM.ListVMs(ctx)
24+
response, err := c.unraidClient.VM.ListVMs(ctx)
2325
if err != nil {
2426
fmt.Printf("Error listing VMs: %v\n", err)
2527
return
2628
}
27-
for _, vm := range respData.VMs.Domains {
28-
idParts := strings.Split(vm.Id, ":")
29-
compactID := idParts[len(idParts)-1]
30-
31-
fmt.Printf("ID: %s | Name: %s | State: %s\n", compactID, vm.Name, vm.State)
32-
}
29+
internal.PrintFormat(c.formater.Format(response))
3330
}
3431

3532
func (c *VmController) Start(ctx context.Context, vmId string) {
3633
_, err := c.unraidClient.VM.Start(ctx, vmId)
3734
if err != nil {
3835
fmt.Printf("Could not start vm: %v", err)
3936
}
40-
}
37+
}
4138

4239
func (c *VmController) Stop(ctx context.Context, vmId string) {
4340
_, err := c.unraidClient.VM.Start(ctx, vmId)
4441
if err != nil {
4542
fmt.Printf("Could not start vm: %v", err)
4643
}
47-
}
44+
}

internal/formaters.go

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,18 @@ package internal
22

33
import (
44
"encoding/json"
5+
"fmt"
56

67
"go.yaml.in/yaml/v2"
78
)
89

9-
type OutputFormater[T any] interface {
10-
Format(input T) (string, error)
10+
type OutputFormater interface {
11+
Format(input any) (string, error)
1112
}
1213

1314
type YamlOutputFormater struct{}
1415

15-
var _ OutputFormater[any] = (*YamlOutputFormater)(nil)
16+
var _ OutputFormater = (*YamlOutputFormater)(nil)
1617

1718
func (f *YamlOutputFormater) Format(input any) (string, error) {
1819
yamled, err := yaml.Marshal(input)
@@ -24,28 +25,31 @@ func (f *YamlOutputFormater) Format(input any) (string, error) {
2425

2526
type JsonOutputFormater struct{}
2627

27-
var _ OutputFormater[any] = (*JsonOutputFormater)(nil)
28+
var _ OutputFormater = (*JsonOutputFormater)(nil)
2829

2930
func (f *JsonOutputFormater) Format(input any) (string, error) {
30-
jsoned, err := json.MarshalIndent(input, "", "\t")
31+
jsoned, err := json.MarshalIndent(input, "", " ")
3132
if err != nil {
3233
return "", err
3334
}
3435
return string(jsoned), nil
3536
}
3637

37-
type ArrayOutputFormater struct{}
38+
type TextOutputFormater struct{}
3839

39-
var _ OutputFormater[ArrayInput] = (*ArrayOutputFormater)(nil)
40+
var _ OutputFormater = (*TextOutputFormater)(nil)
4041

41-
type ArrayInput struct {
42-
Header []string
43-
Content [][]string
42+
func (f *TextOutputFormater) Format(input any) (string, error) {
43+
if stringer, ok := input.(fmt.Stringer); ok {
44+
return stringer.String(), nil
45+
}
46+
return "", fmt.Errorf("input does not implement fmt.Stringer")
4447
}
45-
func (f *ArrayOutputFormater) Format(input ArrayInput) (string, error) {
46-
jsoned, err := json.MarshalIndent(input, "", "\t")
48+
49+
func PrintFormat(stringed string, err error) {
4750
if err != nil {
48-
return "", err
51+
fmt.Printf("Error formatting output: %v\n", err)
52+
return
4953
}
50-
return string(jsoned), nil
54+
fmt.Println(stringed)
5155
}

internal/models/array.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ type ShowArrayModel struct {
66
} `json:"array"`
77
}
88

9+
func (m *ShowArrayModel) String() string {
10+
return "Array State: " + m.Array.State
11+
}
12+
913
type MutateArrayModel struct {
1014
Id string `json:"id"`
1115
}
16+
17+
func (m *MutateArrayModel) String() string {
18+
return "Array ID: " + m.Id
19+
}

internal/models/docker.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
package models
22

3+
import (
4+
"fmt"
5+
"strings"
6+
)
7+
38
type ListContainersModel struct {
49
Docker struct {
510
Containers []struct {
@@ -10,6 +15,21 @@ type ListContainersModel struct {
1015
} `json:"docker"`
1116
}
1217

18+
func (m *ListContainersModel) String() string {
19+
builder := strings.Builder{}
20+
for _, container := range m.Docker.Containers {
21+
idParts := strings.Split(container.ID, ":")
22+
compactID := idParts[len(idParts)-1]
23+
24+
if len(compactID) > 12 {
25+
compactID = compactID[:12]
26+
}
27+
28+
builder.WriteString(fmt.Sprintf("ID: %s | Image: %s | State: %s\n", compactID, container.Image, container.State))
29+
}
30+
return builder.String()
31+
}
32+
1333
type StartContainerModel struct {
1434
Docker struct {
1535
Start struct {
@@ -18,6 +38,9 @@ type StartContainerModel struct {
1838
} `json:"docker"`
1939
}
2040

41+
func (m *StartContainerModel) String() string {
42+
return "Started Container ID: " + m.Docker.Start.ID
43+
}
2144

2245
type StopContainerModel struct {
2346
Docker struct {
@@ -26,3 +49,7 @@ type StopContainerModel struct {
2649
} `json:"stop"`
2750
} `json:"docker"`
2851
}
52+
53+
func (m *StopContainerModel) String() string {
54+
return "Stopped Container ID: " + m.Docker.Stop.ID
55+
}

0 commit comments

Comments
 (0)