From a32adb915ee427bfd71df53e57894a5d38139924 Mon Sep 17 00:00:00 2001 From: anjor Date: Tue, 31 Mar 2026 20:57:53 +0100 Subject: [PATCH 1/4] Add --group filter to schedule list command Wire the existing group label to schedule list so users can filter schedules by group. The ListHandler now accepts a ListRequest with an optional Group field. Empty group returns all schedules. --- api/api_test.go | 2 +- cmd/deal/schedule/list.go | 11 ++++++++++- cmd/schedule_test.go | 2 +- handler/deal/schedule/interface.go | 5 +++-- handler/deal/schedule/list.go | 20 +++++++++++--------- handler/deal/schedule/list_test.go | 13 ++++++++++++- 6 files changed, 38 insertions(+), 15 deletions(-) diff --git a/api/api_test.go b/api/api_test.go index a7fd2c87d..6aaf5c0f7 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -107,7 +107,7 @@ func setupMockSchedule() schedule.Handler { m := new(schedule.MockSchedule) m.On("CreateHandler", mock.Anything, mock.Anything, mock.Anything, mock.Anything). Return(&model.Schedule{}, nil) - m.On("ListHandler", mock.Anything, mock.Anything). + m.On("ListHandler", mock.Anything, mock.Anything, mock.Anything). Return([]model.Schedule{{}}, nil) m.On("PauseHandler", mock.Anything, mock.Anything, uint32(1)). Return(&model.Schedule{}, nil) diff --git a/cmd/deal/schedule/list.go b/cmd/deal/schedule/list.go index da30b43ed..2d5b7b65c 100644 --- a/cmd/deal/schedule/list.go +++ b/cmd/deal/schedule/list.go @@ -11,13 +11,22 @@ import ( var ListCmd = &cli.Command{ Name: "list", Usage: "List all deal making schedules", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "group", + Category: "Filtering", + Usage: "Filter schedules by group label", + }, + }, Action: func(c *cli.Context) error { db, closer, err := database.OpenFromCLI(c) if err != nil { return errors.WithStack(err) } defer closer.Close() - schedules, err := schedule.Default.ListHandler(c.Context, db) + schedules, err := schedule.Default.ListHandler(c.Context, db, schedule.ListRequest{ + Group: c.String("group"), + }) if err != nil { return errors.WithStack(err) } diff --git a/cmd/schedule_test.go b/cmd/schedule_test.go index 8b489f7df..0106b06b6 100644 --- a/cmd/schedule_test.go +++ b/cmd/schedule_test.go @@ -88,7 +88,7 @@ func TestScheduleListHandler(t *testing.T) { defer runner.Save(t) mockHandler := new(schedule.MockSchedule) defer swapScheduleHandler(mockHandler)() - mockHandler.On("ListHandler", mock.Anything, mock.Anything).Return([]model.Schedule{testSchedule}, nil) + mockHandler.On("ListHandler", mock.Anything, mock.Anything, mock.Anything).Return([]model.Schedule{testSchedule}, nil) _, _, err := runner.Run(ctx, "singularity deal schedule list") require.NoError(t, err) diff --git a/handler/deal/schedule/interface.go b/handler/deal/schedule/interface.go index a6ab86ec8..c5359535b 100644 --- a/handler/deal/schedule/interface.go +++ b/handler/deal/schedule/interface.go @@ -26,6 +26,7 @@ type Handler interface { ListHandler( ctx context.Context, db *gorm.DB, + request ListRequest, ) ([]model.Schedule, error) PauseHandler( ctx context.Context, @@ -69,8 +70,8 @@ func (m *MockSchedule) CreateHandler(ctx context.Context, db *gorm.DB, lotusClie return args.Get(0).(*model.Schedule), args.Error(1) } -func (m *MockSchedule) ListHandler(ctx context.Context, db *gorm.DB) ([]model.Schedule, error) { - args := m.Called(ctx, db) +func (m *MockSchedule) ListHandler(ctx context.Context, db *gorm.DB, request ListRequest) ([]model.Schedule, error) { + args := m.Called(ctx, db, request) return args.Get(0).([]model.Schedule), args.Error(1) } diff --git a/handler/deal/schedule/list.go b/handler/deal/schedule/list.go index b4e844607..0ca6d18d6 100644 --- a/handler/deal/schedule/list.go +++ b/handler/deal/schedule/list.go @@ -8,30 +8,32 @@ import ( "gorm.io/gorm" ) +// ListRequest holds optional filters for listing schedules. +type ListRequest struct { + Group string `json:"group"` // Filter by group label (empty = all) +} + // @ID ListSchedules // @Summary List all deal making schedules // @Tags Deal Schedule // @Produce json +// @Param group query string false "Filter by group label" // @Success 200 {array} model.Schedule // @Failure 400 {object} api.HTTPError // @Failure 500 {object} api.HTTPError // @Router /schedule [get] func _() {} -// ListHandler retrieves all the schedules from the database. -// -// Parameters: -// - ctx: The context for the operation, which can include cancellation signals, timeout details, etc. -// - db: The database connection used for CRUD operations. -// -// Returns: -// - A slice of Schedule models if successful. -// - An error if there are issues during the operation. +// ListHandler retrieves schedules from the database, optionally filtered by group. func (DefaultHandler) ListHandler( ctx context.Context, db *gorm.DB, + request ListRequest, ) ([]model.Schedule, error) { db = db.WithContext(ctx) + if request.Group != "" { + db = db.Where("`group` = ?", request.Group) + } var schedules []model.Schedule err := db.Find(&schedules).Error if err != nil { diff --git a/handler/deal/schedule/list_test.go b/handler/deal/schedule/list_test.go index 5358c8e19..a056e30a2 100644 --- a/handler/deal/schedule/list_test.go +++ b/handler/deal/schedule/list_test.go @@ -22,8 +22,19 @@ func TestListHandler(t *testing.T) { PreparationID: 1, }).Error require.NoError(t, err) - schedules, err := Default.ListHandler(ctx, db) + schedules, err := Default.ListHandler(ctx, db, ListRequest{}) require.NoError(t, err) require.Len(t, schedules, 1) + + // Test filtering by group + err = db.Model(&model.Schedule{}).Where("id = ?", 1).Update("`group`", "test-group").Error + require.NoError(t, err) + filtered, err := Default.ListHandler(ctx, db, ListRequest{Group: "test-group"}) + require.NoError(t, err) + require.Len(t, filtered, 1) + + empty, err := Default.ListHandler(ctx, db, ListRequest{Group: "nonexistent"}) + require.NoError(t, err) + require.Len(t, empty, 0) }) } From b7dd32a36c6f35ac2bb53f93e82ae0246f38c0fc Mon Sep 17 00:00:00 2001 From: anjor Date: Tue, 31 Mar 2026 21:24:53 +0100 Subject: [PATCH 2/4] Regenerate swagger, client, and CLI docs for group filter --- .../list_schedules_parameters.go | 35 +++++++++++++++++++ docs/en/cli-reference/deal/schedule/list.md | 5 +++ docs/en/cli-reference/storage/create/ftp.md | 2 +- docs/en/cli-reference/storage/create/sftp.md | 2 +- docs/en/cli-reference/storage/create/smb.md | 2 +- docs/en/cli-reference/storage/update/ftp.md | 2 +- docs/en/cli-reference/storage/update/sftp.md | 2 +- docs/en/cli-reference/storage/update/smb.md | 2 +- docs/swagger/docs.go | 8 +++++ docs/swagger/swagger.json | 8 +++++ docs/swagger/swagger.yaml | 5 +++ 11 files changed, 67 insertions(+), 6 deletions(-) diff --git a/client/swagger/http/deal_schedule/list_schedules_parameters.go b/client/swagger/http/deal_schedule/list_schedules_parameters.go index e1a0ce2ed..4909f0953 100644 --- a/client/swagger/http/deal_schedule/list_schedules_parameters.go +++ b/client/swagger/http/deal_schedule/list_schedules_parameters.go @@ -60,6 +60,13 @@ ListSchedulesParams contains all the parameters to send to the API endpoint Typically these are written to a http.Request. */ type ListSchedulesParams struct { + + /* Group. + + Filter by group label + */ + Group *string + timeout time.Duration Context context.Context HTTPClient *http.Client @@ -113,6 +120,17 @@ func (o *ListSchedulesParams) SetHTTPClient(client *http.Client) { o.HTTPClient = client } +// WithGroup adds the group to the list schedules params +func (o *ListSchedulesParams) WithGroup(group *string) *ListSchedulesParams { + o.SetGroup(group) + return o +} + +// SetGroup adds the group to the list schedules params +func (o *ListSchedulesParams) SetGroup(group *string) { + o.Group = group +} + // WriteToRequest writes these params to a swagger request func (o *ListSchedulesParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error { @@ -121,6 +139,23 @@ func (o *ListSchedulesParams) WriteToRequest(r runtime.ClientRequest, reg strfmt } var res []error + if o.Group != nil { + + // query param group + var qrGroup string + + if o.Group != nil { + qrGroup = *o.Group + } + qGroup := qrGroup + if qGroup != "" { + + if err := r.SetQueryParam("group", qGroup); err != nil { + return err + } + } + } + if len(res) > 0 { return errors.CompositeValidationError(res...) } diff --git a/docs/en/cli-reference/deal/schedule/list.md b/docs/en/cli-reference/deal/schedule/list.md index c626afd16..f4342973a 100644 --- a/docs/en/cli-reference/deal/schedule/list.md +++ b/docs/en/cli-reference/deal/schedule/list.md @@ -10,5 +10,10 @@ USAGE: OPTIONS: --help, -h show help + + Filtering + + --group value Filter schedules by group label + ``` {% endcode %} diff --git a/docs/en/cli-reference/storage/create/ftp.md b/docs/en/cli-reference/storage/create/ftp.md index 73f7bd0f6..0a0aa7c32 100644 --- a/docs/en/cli-reference/storage/create/ftp.md +++ b/docs/en/cli-reference/storage/create/ftp.md @@ -169,7 +169,7 @@ OPTIONS: --pass value FTP password. [$PASS] --port value FTP port number. (default: 21) [$PORT] --tls Use Implicit FTPS (FTP over TLS). (default: false) [$TLS] - --user value FTP username. (default: "$USER") [$USER] + --user value FTP username. (default: "anjor") [$USER] Advanced diff --git a/docs/en/cli-reference/storage/create/sftp.md b/docs/en/cli-reference/storage/create/sftp.md index 26f92a393..8dd3c887e 100644 --- a/docs/en/cli-reference/storage/create/sftp.md +++ b/docs/en/cli-reference/storage/create/sftp.md @@ -456,7 +456,7 @@ OPTIONS: --pubkey-file value Optional path to public key file. [$PUBKEY_FILE] --ssh value Path and arguments to external ssh binary. [$SSH] --use-insecure-cipher Enable the use of insecure ciphers and key exchange methods. (default: false) [$USE_INSECURE_CIPHER] - --user value SSH username. (default: "$USER") [$USER] + --user value SSH username. (default: "anjor") [$USER] Advanced diff --git a/docs/en/cli-reference/storage/create/smb.md b/docs/en/cli-reference/storage/create/smb.md index 26a630af0..4b6757dbe 100644 --- a/docs/en/cli-reference/storage/create/smb.md +++ b/docs/en/cli-reference/storage/create/smb.md @@ -93,7 +93,7 @@ OPTIONS: --port value SMB port number. (default: 445) [$PORT] --spn value Service principal name. [$SPN] --use-kerberos Use Kerberos authentication. (default: false) [$USE_KERBEROS] - --user value SMB username. (default: "$USER") [$USER] + --user value SMB username. (default: "anjor") [$USER] Advanced diff --git a/docs/en/cli-reference/storage/update/ftp.md b/docs/en/cli-reference/storage/update/ftp.md index 3b989343d..a4490f562 100644 --- a/docs/en/cli-reference/storage/update/ftp.md +++ b/docs/en/cli-reference/storage/update/ftp.md @@ -169,7 +169,7 @@ OPTIONS: --pass value FTP password. [$PASS] --port value FTP port number. (default: 21) [$PORT] --tls Use Implicit FTPS (FTP over TLS). (default: false) [$TLS] - --user value FTP username. (default: "$USER") [$USER] + --user value FTP username. (default: "anjor") [$USER] Advanced diff --git a/docs/en/cli-reference/storage/update/sftp.md b/docs/en/cli-reference/storage/update/sftp.md index d0dd5dd77..86b2a8158 100644 --- a/docs/en/cli-reference/storage/update/sftp.md +++ b/docs/en/cli-reference/storage/update/sftp.md @@ -456,7 +456,7 @@ OPTIONS: --pubkey-file value Optional path to public key file. [$PUBKEY_FILE] --ssh value Path and arguments to external ssh binary. [$SSH] --use-insecure-cipher Enable the use of insecure ciphers and key exchange methods. (default: false) [$USE_INSECURE_CIPHER] - --user value SSH username. (default: "$USER") [$USER] + --user value SSH username. (default: "anjor") [$USER] Advanced diff --git a/docs/en/cli-reference/storage/update/smb.md b/docs/en/cli-reference/storage/update/smb.md index 24a52d6e8..8a68531fe 100644 --- a/docs/en/cli-reference/storage/update/smb.md +++ b/docs/en/cli-reference/storage/update/smb.md @@ -93,7 +93,7 @@ OPTIONS: --port value SMB port number. (default: 445) [$PORT] --spn value Service principal name. [$SPN] --use-kerberos Use Kerberos authentication. (default: false) [$USE_KERBEROS] - --user value SMB username. (default: "$USER") [$USER] + --user value SMB username. (default: "anjor") [$USER] Advanced diff --git a/docs/swagger/docs.go b/docs/swagger/docs.go index 05959d10c..25bd94729 100644 --- a/docs/swagger/docs.go +++ b/docs/swagger/docs.go @@ -1636,6 +1636,14 @@ const docTemplate = `{ ], "summary": "List all deal making schedules", "operationId": "ListSchedules", + "parameters": [ + { + "type": "string", + "description": "Filter by group label", + "name": "group", + "in": "query" + } + ], "responses": { "200": { "description": "OK", diff --git a/docs/swagger/swagger.json b/docs/swagger/swagger.json index 35bc69581..8f8f07e6c 100644 --- a/docs/swagger/swagger.json +++ b/docs/swagger/swagger.json @@ -1629,6 +1629,14 @@ ], "summary": "List all deal making schedules", "operationId": "ListSchedules", + "parameters": [ + { + "type": "string", + "description": "Filter by group label", + "name": "group", + "in": "query" + } + ], "responses": { "200": { "description": "OK", diff --git a/docs/swagger/swagger.yaml b/docs/swagger/swagger.yaml index 3cb93ab59..c0e6259c9 100644 --- a/docs/swagger/swagger.yaml +++ b/docs/swagger/swagger.yaml @@ -16607,6 +16607,11 @@ paths: /schedule: get: operationId: ListSchedules + parameters: + - description: Filter by group label + in: query + name: group + type: string produces: - application/json responses: From 94902f8261fa1b2cf57260b3ab876f1b930706ab Mon Sep 17 00:00:00 2001 From: anjor Date: Tue, 31 Mar 2026 21:38:42 +0100 Subject: [PATCH 3/4] Fix CLI docs to use $USER literal instead of resolved username --- docs/en/cli-reference/storage/create/ftp.md | 2 +- docs/en/cli-reference/storage/create/sftp.md | 2 +- docs/en/cli-reference/storage/create/smb.md | 2 +- docs/en/cli-reference/storage/update/ftp.md | 2 +- docs/en/cli-reference/storage/update/sftp.md | 2 +- docs/en/cli-reference/storage/update/smb.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/en/cli-reference/storage/create/ftp.md b/docs/en/cli-reference/storage/create/ftp.md index 0a0aa7c32..73f7bd0f6 100644 --- a/docs/en/cli-reference/storage/create/ftp.md +++ b/docs/en/cli-reference/storage/create/ftp.md @@ -169,7 +169,7 @@ OPTIONS: --pass value FTP password. [$PASS] --port value FTP port number. (default: 21) [$PORT] --tls Use Implicit FTPS (FTP over TLS). (default: false) [$TLS] - --user value FTP username. (default: "anjor") [$USER] + --user value FTP username. (default: "$USER") [$USER] Advanced diff --git a/docs/en/cli-reference/storage/create/sftp.md b/docs/en/cli-reference/storage/create/sftp.md index 8dd3c887e..26f92a393 100644 --- a/docs/en/cli-reference/storage/create/sftp.md +++ b/docs/en/cli-reference/storage/create/sftp.md @@ -456,7 +456,7 @@ OPTIONS: --pubkey-file value Optional path to public key file. [$PUBKEY_FILE] --ssh value Path and arguments to external ssh binary. [$SSH] --use-insecure-cipher Enable the use of insecure ciphers and key exchange methods. (default: false) [$USE_INSECURE_CIPHER] - --user value SSH username. (default: "anjor") [$USER] + --user value SSH username. (default: "$USER") [$USER] Advanced diff --git a/docs/en/cli-reference/storage/create/smb.md b/docs/en/cli-reference/storage/create/smb.md index 4b6757dbe..26a630af0 100644 --- a/docs/en/cli-reference/storage/create/smb.md +++ b/docs/en/cli-reference/storage/create/smb.md @@ -93,7 +93,7 @@ OPTIONS: --port value SMB port number. (default: 445) [$PORT] --spn value Service principal name. [$SPN] --use-kerberos Use Kerberos authentication. (default: false) [$USE_KERBEROS] - --user value SMB username. (default: "anjor") [$USER] + --user value SMB username. (default: "$USER") [$USER] Advanced diff --git a/docs/en/cli-reference/storage/update/ftp.md b/docs/en/cli-reference/storage/update/ftp.md index a4490f562..3b989343d 100644 --- a/docs/en/cli-reference/storage/update/ftp.md +++ b/docs/en/cli-reference/storage/update/ftp.md @@ -169,7 +169,7 @@ OPTIONS: --pass value FTP password. [$PASS] --port value FTP port number. (default: 21) [$PORT] --tls Use Implicit FTPS (FTP over TLS). (default: false) [$TLS] - --user value FTP username. (default: "anjor") [$USER] + --user value FTP username. (default: "$USER") [$USER] Advanced diff --git a/docs/en/cli-reference/storage/update/sftp.md b/docs/en/cli-reference/storage/update/sftp.md index 86b2a8158..d0dd5dd77 100644 --- a/docs/en/cli-reference/storage/update/sftp.md +++ b/docs/en/cli-reference/storage/update/sftp.md @@ -456,7 +456,7 @@ OPTIONS: --pubkey-file value Optional path to public key file. [$PUBKEY_FILE] --ssh value Path and arguments to external ssh binary. [$SSH] --use-insecure-cipher Enable the use of insecure ciphers and key exchange methods. (default: false) [$USE_INSECURE_CIPHER] - --user value SSH username. (default: "anjor") [$USER] + --user value SSH username. (default: "$USER") [$USER] Advanced diff --git a/docs/en/cli-reference/storage/update/smb.md b/docs/en/cli-reference/storage/update/smb.md index 8a68531fe..24a52d6e8 100644 --- a/docs/en/cli-reference/storage/update/smb.md +++ b/docs/en/cli-reference/storage/update/smb.md @@ -93,7 +93,7 @@ OPTIONS: --port value SMB port number. (default: 445) [$PORT] --spn value Service principal name. [$SPN] --use-kerberos Use Kerberos authentication. (default: false) [$USE_KERBEROS] - --user value SMB username. (default: "anjor") [$USER] + --user value SMB username. (default: "$USER") [$USER] Advanced From baddcea29d90fb0d8c4a318ebd89c96f39be1e7f Mon Sep 17 00:00:00 2001 From: anjor Date: Tue, 31 Mar 2026 22:51:48 +0100 Subject: [PATCH 4/4] Fix group filter to work across all DB dialects Use GORM struct-based Where and UpdateColumn instead of raw SQL with backtick quoting, which fails on Postgres. --- handler/deal/schedule/list.go | 2 +- handler/deal/schedule/list_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/handler/deal/schedule/list.go b/handler/deal/schedule/list.go index 0ca6d18d6..902df7615 100644 --- a/handler/deal/schedule/list.go +++ b/handler/deal/schedule/list.go @@ -32,7 +32,7 @@ func (DefaultHandler) ListHandler( ) ([]model.Schedule, error) { db = db.WithContext(ctx) if request.Group != "" { - db = db.Where("`group` = ?", request.Group) + db = db.Where(&model.Schedule{Group: request.Group}) } var schedules []model.Schedule err := db.Find(&schedules).Error diff --git a/handler/deal/schedule/list_test.go b/handler/deal/schedule/list_test.go index a056e30a2..a6d0cea88 100644 --- a/handler/deal/schedule/list_test.go +++ b/handler/deal/schedule/list_test.go @@ -27,7 +27,7 @@ func TestListHandler(t *testing.T) { require.Len(t, schedules, 1) // Test filtering by group - err = db.Model(&model.Schedule{}).Where("id = ?", 1).Update("`group`", "test-group").Error + err = db.Model(&model.Schedule{}).Where("id = ?", 1).UpdateColumn("group", "test-group").Error require.NoError(t, err) filtered, err := Default.ListHandler(ctx, db, ListRequest{Group: "test-group"}) require.NoError(t, err)