Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLOUDP-238932: Validate maxDate and minDate before running command #2794

Merged
merged 8 commits into from Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
79 changes: 43 additions & 36 deletions internal/cli/atlas/events/list.go
Expand Up @@ -17,6 +17,7 @@
import (
"context"
"fmt"
"time"

"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli"
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli/require"
Expand Down Expand Up @@ -62,33 +63,43 @@
var err error

if opts.orgID != "" {
listEventsAPIParams := opts.NewOrgListOptions()
r, err = opts.store.OrganizationEvents(&listEventsAPIParams)
listEventsAPIParams, lErr := opts.NewOrgListOptions()
if lErr != nil {
return lErr
}

if r, err = opts.store.OrganizationEvents(&listEventsAPIParams); err != nil {
return err
}
} else if opts.projectID != "" {
listEventsAPIParams := opts.NewProjectListOptions()
r, err = opts.store.ProjectEvents(&listEventsAPIParams)
}
if err != nil {
return err
listEventsAPIParams, lErr := opts.NewProjectListOptions()
if lErr != nil {
return lErr
}
if r, err = opts.store.ProjectEvents(&listEventsAPIParams); err != nil {
return err
}
}

return opts.Print(r)
}

func (opts *ListOpts) NewOrgListOptions() admin.ListOrganizationEventsApiParams {
func (opts *ListOpts) NewOrgListOptions() (admin.ListOrganizationEventsApiParams, error) {
var eventType *[]string
var err error

if len(opts.EventType) > 0 {
eventType = &opts.EventType
}
p := admin.ListOrganizationEventsApiParams{
OrgId: opts.orgID,
EventType: eventType,
}
if maxDate, err := convert.ParseTimestamp(opts.MaxDate); err == nil {
p.MaxDate = pointer.Get(maxDate)
if p.MaxDate, err = opts.ParseDate(opts.MaxDate); err != nil {
return p, err
}
if minDate, err := convert.ParseTimestamp(opts.MinDate); err == nil {
p.MinDate = pointer.Get(minDate)
if p.MinDate, err = opts.ParseDate(opts.MinDate); err != nil {
return p, err
}
if opts.ItemsPerPage > 0 {
p.ItemsPerPage = &opts.ItemsPerPage
Expand All @@ -99,24 +110,28 @@
if opts.OmitCount {
p.IncludeCount = pointer.Get(false)
}
return p
return p, nil
}

func (opts *ListOpts) NewProjectListOptions() admin.ListProjectEventsApiParams {
func (opts *ListOpts) NewProjectListOptions() (admin.ListProjectEventsApiParams, error) {
var eventType *[]string
var err error
if len(opts.EventType) > 0 {
eventType = &opts.EventType
}
p := admin.ListProjectEventsApiParams{
GroupId: opts.projectID,
EventType: eventType,
}
if maxDate, err := convert.ParseTimestamp(opts.MaxDate); err == nil {
p.MaxDate = pointer.Get(maxDate)

if p.MaxDate, err = opts.ParseDate(opts.MaxDate); err != nil {
return p, err
}
if minDate, err := convert.ParseTimestamp(opts.MinDate); err == nil {
p.MinDate = pointer.Get(minDate)

if p.MinDate, err = opts.ParseDate(opts.MinDate); err != nil {
return p, err
}

if opts.ItemsPerPage > 0 {
p.ItemsPerPage = &opts.ItemsPerPage
}
Expand All @@ -127,23 +142,19 @@
p.IncludeCount = pointer.Get(false)
}

return p
return p, nil
}

func (opts *EventListOpts) ValidateMaxAndMinDates() func() error {
return func() error {
if opts.MaxDate != "" {
if _, err := convert.ParseTimestamp(opts.MaxDate); err != nil {
return fmt.Errorf("invalid maxDate format, %w", err)
}
}
if opts.MinDate != "" {
if _, err := convert.ParseTimestamp(opts.MinDate); err != nil {
return fmt.Errorf("invalid minDate format, %w", err)
}
}
return nil
func (opts *EventListOpts) ParseDate(date string) (*time.Time, error) {

Check warning on line 148 in internal/cli/atlas/events/list.go

View workflow job for this annotation

GitHub Actions / lint

unused-receiver: method receiver 'opts' is not referenced in method's body, consider removing or renaming it as _ (revive)
if date == "" {
return nil, nil
}

parsedDate, err := convert.ParseTimestamp(date)
if err != nil {
return nil, err
}
return pointer.Get(parsedDate), nil
blva marked this conversation as resolved.
Show resolved Hide resolved
}

// ListBuilder
Expand Down Expand Up @@ -181,10 +192,6 @@
}
opts.OutWriter = cmd.OutOrStdout()

if err := opts.ValidateMaxAndMinDates()(); err != nil {
return err
}

return opts.initStore(cmd.Context())()
},
RunE: func(_ *cobra.Command, _ []string) error {
Expand Down
99 changes: 99 additions & 0 deletions internal/cli/atlas/events/list_test.go
Expand Up @@ -15,12 +15,14 @@
package events

import (
"strings"
"testing"

"github.com/golang/mock/gomock"
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/flag"
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/mocks"
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/test"
"github.com/stretchr/testify/assert"
"go.mongodb.org/atlas-sdk/v20231115008/admin"
)

Expand Down Expand Up @@ -63,6 +65,103 @@ func TestList_Run(t *testing.T) {
t.Fatalf("Run() unexpected error: %v", err)
}
})

t.Run("for a org with dates", func(t *testing.T) {
expected := &admin.OrgPaginatedEvent{}
listOpts := &ListOpts{
store: mockStore,
EventListOpts: EventListOpts{
MaxDate: "2024-03-18T15:00:03-0000",
MinDate: "2024-03-18T14:40:03-0000",
},
}
listOpts.orgID = "1"
anyMock := gomock.Any()
mockStore.
EXPECT().OrganizationEvents(anyMock).
Return(expected, nil).
Times(1)

err := listOpts.Run()
if err != nil {
t.Fatalf("Run() unexpected error: %v", err)
}
})
t.Run("for an project with dates", func(t *testing.T) {
expected := &admin.GroupPaginatedEvent{}
listOpts := &ListOpts{
store: mockStore,
EventListOpts: EventListOpts{
MaxDate: "2024-03-18T15:00:03-0000",
MinDate: "2024-03-18T14:40:03-0000",
},
}

anyMock := gomock.Any()
listOpts.projectID = "1"
mockStore.
EXPECT().ProjectEvents(anyMock).
Return(expected, nil).
Times(1)

err := listOpts.Run()
if err != nil {
t.Fatalf("Run() unexpected error: %v", err)
}
})

t.Run("for a org with invalid dates", func(t *testing.T) {
listOpts := &ListOpts{
store: mockStore,
EventListOpts: EventListOpts{
MaxDate: "2024-03-18T15:00:03+00:00Z",
MinDate: "2024-03-18T13:00:03+00:00Z",
},
}
listOpts.orgID = "1"

err := listOpts.Run()
if err == nil {
t.Fatal("Run() expected an error, but got none")
}
assert.True(t, strings.Contains(err.Error(), "parsing time"))
})
t.Run("for an project with invalid dates", func(t *testing.T) {
listOpts := &ListOpts{
store: mockStore,
EventListOpts: EventListOpts{
MaxDate: "2024-03-18T15:00:03+00:00Z",
MinDate: "2024-03-18T13:00:03+00:00Z",
},
}

listOpts.projectID = "1"
err := listOpts.Run()
if err == nil {
t.Fatal("Run() expected an error, but got none")
}
assert.True(t, strings.Contains(err.Error(), "parsing time"))
})
}

func TestParseDate(t *testing.T) {
eventsOpts := &EventListOpts{}

t.Run("valid date", func(t *testing.T) {
date := "2024-03-18T15:00:03-0000"
_, err := eventsOpts.ParseDate(date)
if err != nil {
t.Fatalf("parseDate() unexpected error: %v", err)
}
})
t.Run("invalid date", func(t *testing.T) {
date := "2024-03-18T15:00:03+00:00Z"
_, err := eventsOpts.ParseDate(date)
if err == nil {
t.Fatalf("expected error from parseDate() but got none")
}
assert.True(t, strings.Contains(err.Error(), "parsing time"))
})
}

func TestListBuilder(t *testing.T) {
Expand Down
26 changes: 16 additions & 10 deletions internal/cli/atlas/events/orgs_list.go
Expand Up @@ -20,7 +20,6 @@ import (
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli"
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli/require"
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/config"
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/convert"
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/flag"
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/pointer"
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/store"
Expand All @@ -46,8 +45,11 @@ func (opts *orgListOpts) initStore(ctx context.Context) func() error {

func (opts *orgListOpts) Run() error {
var r interface{}
blva marked this conversation as resolved.
Show resolved Hide resolved
var err error
listEventsAPIParams := opts.NewOrgListOptions()

listEventsAPIParams, err := opts.NewOrgListOptions()
if err != nil {
return err
}
r, err = opts.store.OrganizationEvents(&listEventsAPIParams)
blva marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return err
Expand All @@ -56,8 +58,10 @@ func (opts *orgListOpts) Run() error {
return opts.Print(r)
}

func (opts *orgListOpts) NewOrgListOptions() admin.ListOrganizationEventsApiParams {
func (opts *orgListOpts) NewOrgListOptions() (admin.ListOrganizationEventsApiParams, error) {
blva marked this conversation as resolved.
Show resolved Hide resolved
var eventType []string
var err error

if len(opts.EventType) > 0 {
eventType = opts.EventType
}
Expand All @@ -74,13 +78,16 @@ func (opts *orgListOpts) NewOrgListOptions() admin.ListOrganizationEventsApiPara
if opts.OmitCount {
p.IncludeCount = pointer.Get(false)
}
if maxDate, err := convert.ParseTimestamp(opts.MaxDate); err == nil {
p.MaxDate = pointer.Get(maxDate)

if p.MaxDate, err = opts.ParseDate(opts.MaxDate); err != nil {
return p, err
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if p.MaxDate, err = opts.ParseDate(opts.MaxDate); err != nil {
return p, err
}
if opts.MaxDate != "" {
if p.MaxDate, err = opts.ParseDate(opts.MaxDate); err != nil {
return nil, err
}
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh I see ParseDate is now empty safe, then this may not be needed

if minDate, err := convert.ParseTimestamp(opts.MinDate); err == nil {
p.MinDate = pointer.Get(minDate)

if p.MinDate, err = opts.ParseDate(opts.MinDate); err != nil {
return p, err
}
return p

return p, nil
}

// OrgListBuilder
Expand All @@ -106,7 +113,6 @@ func OrgListBuilder() *cobra.Command {
opts.ValidateOrgID,
opts.initStore(cmd.Context()),
opts.InitOutput(cmd.OutOrStdout(), listTemplate),
opts.ValidateMaxAndMinDates(),
)
},
RunE: func(_ *cobra.Command, _ []string) error {
Expand Down
41 changes: 41 additions & 0 deletions internal/cli/atlas/events/orgs_list_test.go
Expand Up @@ -44,6 +44,47 @@ func Test_orgListOpts_Run(t *testing.T) {
}
}

func Test_orgListOpts_Run_WithDate(t *testing.T) {
ctrl := gomock.NewController(t)
mockStore := mocks.NewMockOrganizationEventLister(ctrl)

expected := &admin.OrgPaginatedEvent{}
listOpts := &orgListOpts{
store: mockStore,
EventListOpts: EventListOpts{
MaxDate: "2024-03-18T15:00:03-0000",
MinDate: "2024-03-18T14:40:03-0000",
},
}
listOpts.OrgID = "1"
anyMock := gomock.Any()
mockStore.
EXPECT().OrganizationEvents(anyMock).
Return(expected, nil).
Times(1)

if err := listOpts.Run(); err != nil {
t.Fatalf("Run() unexpected error: %v", err)
}
}

func Test_orgListOpts_Run_WithInvalidDate(t *testing.T) {
ctrl := gomock.NewController(t)
mockStore := mocks.NewMockOrganizationEventLister(ctrl)

listOpts := &orgListOpts{
store: mockStore,
EventListOpts: EventListOpts{
MaxDate: "2024-03-18T15:00:03+00:00Z",
MinDate: "2024-03-18T13:00:03+00:00Z",
},
}
listOpts.OrgID = "1"

if err := listOpts.Run(); err == nil {
t.Fatalf("Expected inavlid date error from Run() got none")
}
}
func TestOrgListBuilder(t *testing.T) {
blva marked this conversation as resolved.
Show resolved Hide resolved
test.CmdValidator(
t,
Expand Down