Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions cmd/entities/hosts/hosts.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ func NewCmd(cmdContext *base.CmdContext) *cobra.Command {
newListDSDriveSlotsCmd,
newListDSConnectionsCmd,
newListDSPTRCmd,
newCreateDSPTRCmd,
newDeleteDSPTRCmd,
newDSAbortReleaseCmd,
newDSScheduleReleaseCmd,
newListDSNetworksCmd,
Expand Down
90 changes: 89 additions & 1 deletion cmd/entities/hosts/ptr.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,92 @@ func newListDSPTRCmd(cmdContext *base.CmdContext) *cobra.Command {
return base.NewListCmd("list-ptr <id>", "Dedicated server PTR records", factory, cmdContext, opts)
}

// TODO add other PTR methods
func newCreateDSPTRCmd(cmdContext *base.CmdContext) *cobra.Command {
var (
ip string
domain string
ttl int
priority int
)

cmd := &cobra.Command{
Use: "add-ptr <server_id>",
Short: "Create a PTR record",
Long: "Create a PTR record for a dedicated server",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
manager := cmdContext.GetManager()

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

base.SetupProxy(cmd, manager)

scClient := cmdContext.GetClient().SetVerbose(manager.GetVerbose(cmd)).GetScClient()

serverID := args[0]

input := &serverscom.PTRRecordCreateInput{
IP: ip,
Domain: domain,
}
if cmd.Flags().Changed("ttl") {
input.TTL = &ttl
}
if cmd.Flags().Changed("priority") {
input.Priority = &priority
}

prtRecord, err := scClient.Hosts.CreatePTRRecordForDedicatedServer(ctx, serverID, *input)
if err != nil {
return err
}

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

cmd.Flags().StringVar(&ip, "ip", "", "An IP address associated with a PTR record (required)")
_ = cmd.MarkFlagRequired("ip")

cmd.Flags().StringVar(&domain, "domain", "", "A domain name for a PTR record (required)")
_ = cmd.MarkFlagRequired("domain")

cmd.Flags().IntVar(&ttl, "ttl", 0, "TTL (time to live) in seconds")
cmd.Flags().IntVar(&priority, "priority", 0, "Priority (lower value means higher priority)")

return cmd
}

func newDeleteDSPTRCmd(cmdContext *base.CmdContext) *cobra.Command {
var recordID string

cmd := &cobra.Command{
Use: "delete-ptr <server_id>",
Short: "Delete a PTR record",
Long: "Delete a PTR record for a dedicated server",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
manager := cmdContext.GetManager()

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

base.SetupProxy(cmd, manager)

scClient := cmdContext.GetClient().SetVerbose(manager.GetVerbose(cmd)).GetScClient()

serverID := args[0]
return scClient.Hosts.DeletePTRRecordForDedicatedServer(ctx, serverID, recordID)
},
}

cmd.Flags().StringVar(&recordID, "ptr-id", "", "Record ID (required)")
_ = cmd.MarkFlagRequired("ptr-id")

return cmd
}
283 changes: 283 additions & 0 deletions cmd/entities/hosts/ptr_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
package hosts

import (
"errors"
"path/filepath"
"testing"

. "github.com/onsi/gomega"
serverscom "github.com/serverscom/serverscom-go-client/pkg"
"github.com/serverscom/srvctl/cmd/testutils"
"github.com/serverscom/srvctl/internal/mocks"
"go.uber.org/mock/gomock"
)

var (
ptrFixtureBasePath = filepath.Join("..", "..", "..", "testdata", "entities", "ptr")
testServerID = "serverId"
testPTRID = "ptrId"

testPTR = serverscom.PTRRecord{
ID: testPTRID,
IP: "192.0.2.5",
Domain: "ptr-test.example.com",
Priority: 10,
TTL: 300,
}
)

func TestListDSPTRCmd(t *testing.T) {
testPTR1 := testPTR
testPTR2 := testPTR
testPTR1.ID += "1"
testPTR2.ID += "2"
testPTR2.Domain = "another.example.com"

testCases := []struct {
name string
output string
args []string
expectedOutput []byte
expectError bool
configureMock func(*mocks.MockCollection[serverscom.PTRRecord])
}{
{
name: "list all ptr records",
output: "json",
args: []string{"-A", testServerID},
expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "list_all.json")),
configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) {
mock.EXPECT().
Collect(gomock.Any()).
Return([]serverscom.PTRRecord{
testPTR1,
testPTR2,
}, nil)
},
},
{
name: "list ptr records",
output: "json",
args: []string{testServerID},
expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "list.json")),
configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) {
mock.EXPECT().
List(gomock.Any()).
Return([]serverscom.PTRRecord{
testPTR1,
}, nil)
},
},
{
name: "list ptr records with template",
args: []string{testServerID, "--template", "{{range .}}ID: {{.ID}} PTR: {{.Domain}}\n{{end}}"},
expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "list_template.txt")),
configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) {
mock.EXPECT().
List(gomock.Any()).
Return([]serverscom.PTRRecord{
testPTR1,
testPTR2,
}, nil)
},
},
{
name: "list ptr records with page-view",
args: []string{testServerID, "--page-view"},
expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "list_pageview.txt")),
configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) {
mock.EXPECT().
List(gomock.Any()).
Return([]serverscom.PTRRecord{
testPTR1,
testPTR2,
}, nil)
},
},
{
name: "list ptr records with error",
args: []string{testServerID},
expectError: true,
configureMock: func(mock *mocks.MockCollection[serverscom.PTRRecord]) {
mock.EXPECT().
List(gomock.Any()).
Return(nil, errors.New("some error"))
},
},
}

mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
hostService := mocks.NewMockHostsService(mockCtrl)
collection := mocks.NewMockCollection[serverscom.PTRRecord](mockCtrl)

hostService.EXPECT().DedicatedServerPTRRecords(gomock.Any()).Return(collection).AnyTimes()
collection.EXPECT().SetParam(gomock.Any(), gomock.Any()).Return(collection).AnyTimes()

scClient := serverscom.NewClientWithEndpoint("", "")
scClient.Hosts = hostService

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
g := NewWithT(t)
if tc.configureMock != nil {
tc.configureMock(collection)
}
testCmdContext := testutils.NewTestCmdContext(scClient)
cmd := NewCmd(testCmdContext)

args := append([]string{"hosts", "ds", "list-ptr"}, tc.args...)
if tc.output != "" {
args = append(args, "--output", tc.output)
}
builder := testutils.NewTestCommandBuilder().
WithCommand(cmd).
WithArgs(args)

c := builder.Build()
err := c.Execute()
if tc.expectError {
g.Expect(err).To(HaveOccurred())
} else {
g.Expect(err).To(BeNil())
g.Expect(builder.GetOutput()).To(BeEquivalentTo(string(tc.expectedOutput)))
}
})
}
}

func TestCreateDSPTRCmd(t *testing.T) {
testCases := []struct {
name string
args []string
output string
expectedOutput []byte
configureMock func(*mocks.MockHostsService)
expectError bool
}{
{
name: "create ds ptr",
args: []string{testServerID, "--ip", testPTR.IP, "--domain", testPTR.Domain, "--ttl", "300", "--priority", "10"},
output: "json",
expectedOutput: testutils.ReadFixture(filepath.Join(ptrFixtureBasePath, "get.json")),
configureMock: func(mock *mocks.MockHostsService) {
in := serverscom.PTRRecordCreateInput{
IP: testPTR.IP,
Domain: testPTR.Domain,
TTL: &testPTR.TTL,
Priority: &testPTR.Priority,
}
mock.EXPECT().
CreatePTRRecordForDedicatedServer(gomock.Any(), testServerID, in).
Return(&testPTR, nil)
},
},
{
name: "create ds ptr error",
args: []string{testServerID, "--ip", testPTR.IP, "--domain", testPTR.Domain},
expectError: true,
configureMock: func(mock *mocks.MockHostsService) {
in := serverscom.PTRRecordCreateInput{
IP: testPTR.IP,
Domain: testPTR.Domain,
}
mock.EXPECT().
CreatePTRRecordForDedicatedServer(gomock.Any(), testServerID, in).
Return(nil, errors.New("some error"))
},
},
}

mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
hostService := mocks.NewMockHostsService(mockCtrl)
scClient := serverscom.NewClientWithEndpoint("", "")
scClient.Hosts = hostService

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
g := NewWithT(t)
if tc.configureMock != nil {
tc.configureMock(hostService)
}
testCmdContext := testutils.NewTestCmdContext(scClient)
cmd := NewCmd(testCmdContext)

args := []string{"hosts", "ds", "add-ptr"}
if len(tc.args) > 0 {
args = append(args, tc.args...)
}
if tc.output != "" {
args = append(args, "--output", tc.output)
}
builder := testutils.NewTestCommandBuilder().
WithCommand(cmd).
WithArgs(args)

c := builder.Build()
err := c.Execute()
if tc.expectError {
g.Expect(err).To(HaveOccurred())
} else {
g.Expect(err).To(BeNil())
g.Expect(builder.GetOutput()).To(BeEquivalentTo(string(tc.expectedOutput)))
}
})
}
}

func TestDeleteDSPTRCmd(t *testing.T) {
testCases := []struct {
name string
serverID string
ptrID string
expectError bool
}{
{
name: "delete ds ptr",
serverID: testServerID,
ptrID: testPTRID,
},
{
name: "delete ds ptr error",
serverID: testServerID,
ptrID: testPTRID,
expectError: true,
},
}

mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
hostService := mocks.NewMockHostsService(mockCtrl)
scClient := serverscom.NewClientWithEndpoint("", "")
scClient.Hosts = hostService

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
g := NewWithT(t)
var err error
if tc.expectError {
err = errors.New("some error")
}
hostService.EXPECT().
DeletePTRRecordForDedicatedServer(gomock.Any(), tc.serverID, tc.ptrID).
Return(err)

testCmdContext := testutils.NewTestCmdContext(scClient)
cmd := NewCmd(testCmdContext)

args := []string{"hosts", "ds", "delete-ptr", tc.serverID, "--ptr-id", tc.ptrID}
builder := testutils.NewTestCommandBuilder().
WithCommand(cmd).
WithArgs(args)

c := builder.Build()
err = c.Execute()
if tc.expectError {
g.Expect(err).To(HaveOccurred())
} else {
g.Expect(err).To(BeNil())
}
})
}
}
7 changes: 7 additions & 0 deletions testdata/entities/ptr/get.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"id": "ptrId",
"ip": "192.0.2.5",
"domain": "ptr-test.example.com",
"priority": 10,
"ttl": 300
}
Loading
Loading