Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 37 additions & 12 deletions cmd/entities/hosts/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ package hosts

import (
"fmt"
"log"
"os"

"maps"
"os"

serverscom "github.com/serverscom/serverscom-go-client/pkg"
"github.com/serverscom/srvctl/cmd/base"
Expand All @@ -14,6 +12,7 @@ import (
)

type AddDSFlags struct {
Skeleton bool
InputPath string
LocationID int
ServerModelID int
Expand All @@ -32,6 +31,11 @@ type AddDSFlags struct {
Labels map[string]string
}

type AddSBMFlags struct {
Skeleton bool
InputPath string
}

func applyFlagsToInput(
input *serverscom.DedicatedServerCreateInput,
flags *AddDSFlags,
Expand Down Expand Up @@ -132,6 +136,11 @@ func newAddDSCmd(cmdContext *base.CmdContext) *cobra.Command {
Short: "Create a dedicated server",
Args: cobra.ArbitraryArgs,
RunE: func(cmd *cobra.Command, args []string) error {
formatter := cmdContext.GetOrCreateFormatter(cmd)

if flags.Skeleton {
return formatter.FormatSkeleton("hosts/add_ds.json")
}

manager := cmdContext.GetManager()
ctx, cancel := base.SetupContext(cmd, manager)
Expand All @@ -145,6 +154,11 @@ func newAddDSCmd(cmdContext *base.CmdContext) *cobra.Command {
if err := base.ReadInputJSON(flags.InputPath, cmd.InOrStdin(), &input); err != nil {
return err
}
} else {
required := []string{"input"}
if err := base.ValidateFlags(cmd, required); err != nil {
return err
}
}

if len(input.Hosts) == 0 && len(args) == 0 {
Expand All @@ -171,7 +185,6 @@ func newAddDSCmd(cmdContext *base.CmdContext) *cobra.Command {
}

if server != nil {
formatter := cmdContext.GetOrCreateFormatter(cmd)
return formatter.Format(server)
}

Expand All @@ -180,6 +193,7 @@ func newAddDSCmd(cmdContext *base.CmdContext) *cobra.Command {
}

cmd.Flags().StringVarP(&flags.InputPath, "input", "i", "", "path to input file or '-' to read from stdin")
cmd.Flags().BoolVarP(&flags.Skeleton, "skeleton", "s", false, "JSON object with structure that is required to be passed")

cmd.Flags().IntVar(&flags.LocationID, "location-id", 0, "Create the server(s) in the specific location ID")
cmd.Flags().IntVar(&flags.ServerModelID, "server-model-id", 0, "Use specific server model ID to create the server")
Expand All @@ -201,12 +215,19 @@ func newAddDSCmd(cmdContext *base.CmdContext) *cobra.Command {
}

func newAddSBMCmd(cmdContext *base.CmdContext) *cobra.Command {
var path string
flags := &AddSBMFlags{}

cmd := &cobra.Command{
Use: "add --input <path>",
Short: "Create an SBM server",
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
formatter := cmdContext.GetOrCreateFormatter(cmd)

if flags.Skeleton {
return formatter.FormatSkeleton("hosts/add_sbm.json")
}

manager := cmdContext.GetManager()
ctx, cancel := base.SetupContext(cmd, manager)
defer cancel()
Expand All @@ -215,8 +236,15 @@ func newAddSBMCmd(cmdContext *base.CmdContext) *cobra.Command {

input := serverscom.SBMServerCreateInput{}

if err := base.ReadInputJSON(path, cmd.InOrStdin(), &input); err != nil {
return err
if flags.InputPath != "" {
if err := base.ReadInputJSON(flags.InputPath, cmd.InOrStdin(), &input); err != nil {
return err
}
} else {
required := []string{"input"}
if err := base.ValidateFlags(cmd, required); err != nil {
return err
}
}

scClient := cmdContext.GetClient().SetVerbose(manager.GetVerbose(cmd)).GetScClient()
Expand All @@ -227,18 +255,15 @@ func newAddSBMCmd(cmdContext *base.CmdContext) *cobra.Command {
}

if server != nil {
formatter := cmdContext.GetOrCreateFormatter(cmd)
return formatter.Format(server)
}

return nil
},
}

cmd.Flags().StringVarP(&path, "input", "i", "", "path to input file or '-' to read from stdin")
if err := cmd.MarkFlagRequired("input"); err != nil {
log.Fatal(err)
}
cmd.Flags().StringVarP(&flags.InputPath, "input", "i", "", "path to input file or '-' to read from stdin")
cmd.Flags().BoolVarP(&flags.Skeleton, "skeleton", "s", false, "JSON object with structure that is required to be passed")

return cmd
}
41 changes: 32 additions & 9 deletions cmd/entities/hosts/hosts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@ import (
)

var (
testId = "testId"
testNetworkId = "testNetId"
fixtureBasePath = filepath.Join("..", "..", "..", "testdata", "entities", "hosts")
fixedTime = time.Date(2025, 1, 1, 12, 0, 0, 0, time.UTC)
testPublicIP = "1.2.3.4"
testLocationCode = "test"
testHost = serverscom.Host{
testId = "testId"
testNetworkId = "testNetId"
fixtureBasePath = filepath.Join("..", "..", "..", "testdata", "entities", "hosts")
skeletonTemplatePath = filepath.Join("..", "..", "..", "internal", "output", "skeletons", "templates", "hosts")
fixedTime = time.Date(2025, 1, 1, 12, 0, 0, 0, time.UTC)
testPublicIP = "1.2.3.4"
testLocationCode = "test"
testHost = serverscom.Host{
ID: testId,
Title: "example.aa",
Status: "active",
Expand Down Expand Up @@ -340,6 +341,17 @@ func TestAddDSCmd(t *testing.T) {
Return([]serverscom.DedicatedServer{testDS}, nil)
},
},
{
name: "skeleton for dedicated server input",
output: "json",
args: []string{"--skeleton"},
expectedOutput: testutils.ReadFixture(filepath.Join(skeletonTemplatePath, "add_ds.json")),
configureMock: func(mock *mocks.MockHostsService) {
mock.EXPECT().
CreateDedicatedServers(gomock.Any(), gomock.Any()).
Times(0)
},
},
{
name: "create dedicated server with error",
expectError: true,
Expand Down Expand Up @@ -385,7 +397,7 @@ func TestAddDSCmd(t *testing.T) {
g.Expect(err).To(HaveOccurred())
} else {
g.Expect(err).To(BeNil())
g.Expect(builder.GetOutput()).To(BeEquivalentTo(string(tc.expectedOutput)))
g.Expect(builder.GetOutput()).To(MatchJSON(tc.expectedOutput))
}
})
}
Expand Down Expand Up @@ -424,6 +436,17 @@ func TestAddSBMCmd(t *testing.T) {
Return([]serverscom.SBMServer{testSBM}, nil)
},
},
{
name: "skeleton for SBM server input",
output: "json",
args: []string{"--skeleton"},
expectedOutput: testutils.ReadFixture(filepath.Join(skeletonTemplatePath, "add_sbm.json")),
configureMock: func(mock *mocks.MockHostsService) {
mock.EXPECT().
CreateSBMServers(gomock.Any(), gomock.Any()).
Times(0)
},
},
{
name: "create SBM server with error",
expectError: true,
Expand Down Expand Up @@ -469,7 +492,7 @@ func TestAddSBMCmd(t *testing.T) {
g.Expect(err).To(HaveOccurred())
} else {
g.Expect(err).To(BeNil())
g.Expect(builder.GetOutput()).To(BeEquivalentTo(string(tc.expectedOutput)))
g.Expect(builder.GetOutput()).To(MatchJSON(tc.expectedOutput))
}
})
}
Expand Down
33 changes: 23 additions & 10 deletions cmd/entities/hosts/reinstall.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ package hosts
import (
"context"
"fmt"
"log"

serverscom "github.com/serverscom/serverscom-go-client/pkg"
"github.com/serverscom/srvctl/cmd/base"
"github.com/spf13/cobra"
)

type AddedFlags struct {
Skeleton bool
InputPath string
}

type HostReinstaller interface {
Reinstall(ctx context.Context, client *serverscom.Client, id string, input any) (any, error)
NewReinstallInput() any
Expand Down Expand Up @@ -44,22 +47,35 @@ func (c *SBMReinstallMgr) NewReinstallInput() any {
}

func newReinstallCmd(cmdContext *base.CmdContext, hostType *HostTypeCmd) *cobra.Command {
var path string
flags := &AddedFlags{}

cmd := &cobra.Command{
Use: "reinstall <id>",
Short: fmt.Sprintf("Reinstall OS for a %s", hostType.entityName),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
formatter := cmdContext.GetOrCreateFormatter(cmd)

if flags.Skeleton {
return formatter.FormatSkeleton("hosts/reinstall.json")
}

manager := cmdContext.GetManager()
ctx, cancel := base.SetupContext(cmd, manager)
defer cancel()
base.SetupProxy(cmd, manager)

input := hostType.managers.reinstallMgr.NewReinstallInput()

if err := base.ReadInputJSON(path, cmd.InOrStdin(), input); err != nil {
return err
if flags.InputPath != "" {
if err := base.ReadInputJSON(flags.InputPath, cmd.InOrStdin(), &input); err != nil {
return err
}
} else {
required := []string{"input"}
if err := base.ValidateFlags(cmd, required); err != nil {
return err
}
}

scClient := cmdContext.GetClient().SetVerbose(manager.GetVerbose(cmd)).GetScClient()
Expand All @@ -71,17 +87,14 @@ func newReinstallCmd(cmdContext *base.CmdContext, hostType *HostTypeCmd) *cobra.
}

if server != nil {
formatter := cmdContext.GetOrCreateFormatter(cmd)
return formatter.Format(server)
}
return nil
},
}

cmd.Flags().StringVarP(&path, "input", "i", "", "path to input file or '-' to read from stdin")
if err := cmd.MarkFlagRequired("input"); err != nil {
log.Fatal(err)
}
cmd.Flags().StringVarP(&flags.InputPath, "input", "i", "", "path to input file or '-' to read from stdin")
cmd.Flags().BoolVarP(&flags.Skeleton, "skeleton", "s", false, "JSON object with structure that is required to be passed")

return cmd
}
11 changes: 9 additions & 2 deletions cmd/entities/l2_segments/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
)

type AddedFlags struct {
Skeleton bool
InputPath string
Name string
Type string
Expand All @@ -26,8 +27,13 @@ func newAddCmd(cmdContext *base.CmdContext) *cobra.Command {
Long: "Add a new L2 segment",
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
manager := cmdContext.GetManager()
formatter := cmdContext.GetOrCreateFormatter(cmd)

if flags.Skeleton {
return formatter.FormatSkeleton("l2-segments/add.json")
}

manager := cmdContext.GetManager()
ctx, cancel := base.SetupContext(cmd, manager)
defer cancel()

Expand Down Expand Up @@ -57,14 +63,15 @@ func newAddCmd(cmdContext *base.CmdContext) *cobra.Command {
}

if l2Segment != nil {
formatter := cmdContext.GetOrCreateFormatter(cmd)
return formatter.Format(l2Segment)
}
return nil
},
}

cmd.Flags().StringVarP(&flags.InputPath, "input", "i", "", "path to input file or '-' to read from stdin")
cmd.Flags().BoolVarP(&flags.Skeleton, "skeleton", "s", false, "JSON object with structure that is required to be passed")

cmd.Flags().StringVarP(&flags.Name, "name", "n", "", "A name of a L2 segment")
cmd.Flags().StringVarP(&flags.Type, "type", "", "", "A type of a L2 segment")
cmd.Flags().Int64VarP(&flags.LocationGroupID, "location-group-id", "", 0, "A private-key of a L2 segment")
Expand Down
Loading
Loading