From d8f2d858ac198b924edbaab1775ca60df9863eed Mon Sep 17 00:00:00 2001 From: Adrien Delannoy Date: Thu, 17 Oct 2024 11:40:25 +0200 Subject: [PATCH] feat: Add name filters for workflow list (exact/prefix/pattern) (#13160) Signed-off-by: Adrien Delannoy --- api/openapi-spec/swagger.json | 6 + persist/sqldb/selector.go | 14 +- pkg/apiclient/workflow/workflow.pb.go | 238 +++++++++++------- pkg/apiclient/workflow/workflow.proto | 2 + sdks/java/client/docs/WorkflowServiceApi.md | 6 +- .../api/workflow_service_api.py | 6 + sdks/python/client/docs/WorkflowServiceApi.md | 4 +- server/utils/list_options.go | 17 +- server/workflow/store/lister.go | 8 +- server/workflow/store/sqlite_store.go | 8 +- server/workflow/store/sqlite_store_test.go | 39 +++ server/workflow/workflow_server.go | 7 +- .../archived_workflow_server.go | 2 +- .../shared/components/dropdown/dropdown.tsx | 5 +- .../app/shared/components/input-filter.scss | 10 + ui/src/app/shared/components/input-filter.tsx | 10 +- ui/src/app/shared/services/utils.ts | 5 + .../app/shared/services/workflows-service.ts | 7 +- .../workflow-filters/workflow-filters.scss | 6 +- .../workflow-filters/workflow-filters.tsx | 53 ++++ .../workflows-list/workflows-list.tsx | 33 ++- 21 files changed, 355 insertions(+), 131 deletions(-) create mode 100644 ui/src/app/shared/components/input-filter.scss diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 222e843ad7cc..4fbfc845ac87 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -2961,6 +2961,12 @@ "description": "Fields to be included or excluded in the response. e.g. \"items.spec,items.status.phase\", \"-items.status.nodes\".", "name": "fields", "in": "query" + }, + { + "type": "string", + "description": "Filter type used for name filtering. Exact | Contains | Prefix. Default to Exact.", + "name": "nameFilter", + "in": "query" } ], "responses": { diff --git a/persist/sqldb/selector.go b/persist/sqldb/selector.go index 5e2b9cbb53ca..93a0b580ad7b 100644 --- a/persist/sqldb/selector.go +++ b/persist/sqldb/selector.go @@ -39,7 +39,19 @@ func BuildWorkflowSelector(in string, inArgs []any, tableName, labelTableName st clauses = append(clauses, db.Raw("namespace = ?", options.Namespace)) } if options.Name != "" { - clauses = append(clauses, db.Raw("name = ?", options.Name)) + nameFilter := options.NameFilter + if nameFilter == "" { + nameFilter = "Exact" + } + if nameFilter == "Exact" { + clauses = append(clauses, db.Raw("name = ?", options.Name)) + } + if nameFilter == "Contains" { + clauses = append(clauses, db.Raw("name like ?", "%"+options.Name+"%")) + } + if nameFilter == "Prefix" { + clauses = append(clauses, db.Raw("name like ?", options.Name+"%")) + } } if options.NamePrefix != "" { clauses = append(clauses, db.Raw("name like ?", options.NamePrefix+"%")) diff --git a/pkg/apiclient/workflow/workflow.pb.go b/pkg/apiclient/workflow/workflow.pb.go index 0733f16480d2..9f2f76be21f7 100644 --- a/pkg/apiclient/workflow/workflow.pb.go +++ b/pkg/apiclient/workflow/workflow.pb.go @@ -191,7 +191,9 @@ type WorkflowListRequest struct { Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` ListOptions *v1.ListOptions `protobuf:"bytes,2,opt,name=listOptions,proto3" json:"listOptions,omitempty"` // Fields to be included or excluded in the response. e.g. "items.spec,items.status.phase", "-items.status.nodes" - Fields string `protobuf:"bytes,3,opt,name=fields,proto3" json:"fields,omitempty"` + Fields string `protobuf:"bytes,3,opt,name=fields,proto3" json:"fields,omitempty"` + // Filter type used for name filtering. Exact | Contains | Prefix. Default to Exact + NameFilter string `protobuf:"bytes,4,opt,name=nameFilter,proto3" json:"nameFilter,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -251,6 +253,13 @@ func (m *WorkflowListRequest) GetFields() string { return "" } +func (m *WorkflowListRequest) GetNameFilter() string { + if m != nil { + return m.NameFilter + } + return "" +} + type WorkflowResubmitRequest struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` @@ -1312,98 +1321,98 @@ func init() { } var fileDescriptor_1f6bb75f9e833cb6 = []byte{ - // 1442 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x98, 0xcd, 0x6f, 0x1c, 0xb5, - 0x1b, 0xc7, 0xe5, 0xa4, 0x4d, 0x13, 0xe7, 0xa5, 0xad, 0x7f, 0x6d, 0x7f, 0xcb, 0xa8, 0x4d, 0x53, - 0x97, 0x42, 0x9a, 0x36, 0x33, 0x79, 0x29, 0xd0, 0x22, 0x81, 0x44, 0x9b, 0x12, 0x51, 0x96, 0x52, - 0xcd, 0x22, 0x21, 0xb8, 0xa0, 0xc9, 0xec, 0x93, 0xc9, 0x34, 0x3b, 0xe3, 0xc1, 0xf6, 0x6e, 0x15, - 0x4a, 0x91, 0xe0, 0x02, 0x07, 0x24, 0x0e, 0x1c, 0xb9, 0x20, 0x24, 0x04, 0x07, 0x04, 0x08, 0x09, - 0x09, 0x81, 0x84, 0x38, 0x70, 0xe0, 0x58, 0xa9, 0x57, 0x0e, 0xa8, 0xe2, 0x1f, 0xe0, 0x3f, 0x40, - 0xf6, 0xbc, 0x67, 0xb7, 0xdb, 0x21, 0xd9, 0x42, 0x6f, 0x63, 0xcf, 0xd8, 0xcf, 0xc7, 0xdf, 0xc7, - 0x7e, 0x9e, 0xc7, 0x83, 0x4f, 0x45, 0x9b, 0x9e, 0xe5, 0x44, 0xbe, 0xdb, 0xf2, 0x21, 0x94, 0xd6, - 0x0d, 0xc6, 0x37, 0xd7, 0x5b, 0xec, 0x46, 0xf6, 0x60, 0x46, 0x9c, 0x49, 0x46, 0x46, 0xd3, 0xb6, - 0x71, 0xd4, 0x63, 0xcc, 0x6b, 0x81, 0x1a, 0x63, 0x39, 0x61, 0xc8, 0xa4, 0x23, 0x7d, 0x16, 0x8a, - 0xf8, 0x3b, 0xe3, 0xdc, 0xe6, 0x79, 0x61, 0xfa, 0x4c, 0xbd, 0x0d, 0x1c, 0x77, 0xc3, 0x0f, 0x81, - 0x6f, 0x59, 0x89, 0x09, 0x61, 0x05, 0x20, 0x1d, 0xab, 0xb3, 0x68, 0x79, 0x10, 0x02, 0x77, 0x24, - 0x34, 0x93, 0x51, 0x2f, 0x79, 0xbe, 0xdc, 0x68, 0xaf, 0x99, 0x2e, 0x0b, 0x2c, 0x87, 0x7b, 0x2c, - 0xe2, 0xec, 0xba, 0x7e, 0x98, 0x4f, 0xcd, 0x8a, 0x7c, 0x92, 0x0c, 0xb1, 0xb3, 0xe8, 0xb4, 0xa2, - 0x0d, 0xa7, 0x7b, 0x3a, 0x9a, 0x43, 0x58, 0x2e, 0xe3, 0xd0, 0xc3, 0x24, 0xfd, 0x65, 0x08, 0x1f, - 0x7e, 0x35, 0x99, 0xe9, 0x12, 0x07, 0x47, 0x82, 0x0d, 0x6f, 0xb6, 0x41, 0x48, 0x72, 0x14, 0x8f, - 0x85, 0x4e, 0x00, 0x22, 0x72, 0x5c, 0xa8, 0xa1, 0x19, 0x34, 0x3b, 0x66, 0xe7, 0x1d, 0x64, 0x1d, - 0x67, 0x52, 0xd4, 0x86, 0x66, 0xd0, 0xec, 0xf8, 0xd2, 0x15, 0x33, 0xa7, 0x37, 0x53, 0x7a, 0xfd, - 0xf0, 0x46, 0x46, 0x6f, 0x76, 0x96, 0xcd, 0x68, 0xd3, 0x33, 0xd5, 0x02, 0xcc, 0x4c, 0xda, 0x74, - 0x01, 0x66, 0x0a, 0x62, 0x67, 0x73, 0x13, 0x8a, 0xb1, 0x1f, 0x0a, 0xe9, 0x84, 0x2e, 0xbc, 0xb0, - 0x52, 0x1b, 0x56, 0x18, 0x17, 0x87, 0x6a, 0xc8, 0x2e, 0xf4, 0x12, 0x8a, 0x27, 0x04, 0xf0, 0x0e, - 0xf0, 0x15, 0xbe, 0x65, 0xb7, 0xc3, 0xda, 0x9e, 0x19, 0x34, 0x3b, 0x6a, 0x97, 0xfa, 0xc8, 0x6b, - 0x78, 0xd2, 0xd5, 0xcb, 0x7b, 0x39, 0xd2, 0x7e, 0xaa, 0xed, 0xd5, 0xd0, 0xcb, 0x66, 0xac, 0x91, - 0x59, 0x74, 0x54, 0x8e, 0xa8, 0x1c, 0x65, 0x76, 0x16, 0xcd, 0x4b, 0xc5, 0xa1, 0x76, 0x79, 0x26, - 0xfa, 0x2d, 0xc2, 0x24, 0x25, 0x5f, 0x05, 0x99, 0xea, 0x47, 0xf0, 0x1e, 0x25, 0x57, 0x22, 0x9d, - 0x7e, 0x2e, 0x6b, 0x3a, 0xb4, 0x5d, 0xd3, 0x6b, 0x18, 0x7b, 0x20, 0x53, 0xc0, 0x61, 0x0d, 0xb8, - 0x50, 0x0d, 0x70, 0x35, 0x1b, 0x67, 0x17, 0xe6, 0x20, 0x47, 0xf0, 0xc8, 0xba, 0x0f, 0xad, 0xa6, - 0xd0, 0x9a, 0x8c, 0xd9, 0x49, 0x8b, 0x7e, 0x8a, 0xf0, 0xff, 0x52, 0xe4, 0xba, 0x2f, 0x64, 0x35, - 0x9f, 0x37, 0xf0, 0x78, 0xcb, 0x17, 0x19, 0x60, 0xec, 0xf6, 0xc5, 0x6a, 0x80, 0xf5, 0x7c, 0xa0, - 0x5d, 0x9c, 0xa5, 0x80, 0x38, 0x5c, 0x42, 0x7c, 0x1f, 0xe1, 0xff, 0x67, 0xfb, 0x01, 0x44, 0x7b, - 0x2d, 0xf0, 0x77, 0x21, 0xad, 0x81, 0x47, 0x03, 0x08, 0x98, 0xff, 0x16, 0x34, 0xb5, 0x9d, 0x51, - 0x3b, 0x6b, 0x93, 0x69, 0x8c, 0x23, 0x87, 0x3b, 0x01, 0x48, 0xe0, 0x6a, 0x5f, 0x0c, 0xcf, 0x8e, - 0xd9, 0x85, 0x1e, 0xfa, 0x2b, 0xc2, 0x87, 0x72, 0x12, 0xc9, 0xb7, 0x76, 0x8e, 0x71, 0x16, 0x1f, - 0xe4, 0x20, 0xa4, 0xc3, 0x65, 0xa3, 0xed, 0xba, 0x20, 0xc4, 0x7a, 0xbb, 0x95, 0xf0, 0x74, 0xbf, - 0x50, 0x5f, 0x87, 0xac, 0x09, 0xcf, 0x2b, 0x41, 0x1a, 0xd0, 0x02, 0x57, 0x32, 0x9e, 0x38, 0xb2, - 0xfb, 0xc5, 0x7d, 0x97, 0x71, 0x23, 0x3f, 0xe8, 0x4a, 0xcf, 0x00, 0x76, 0xb5, 0x8c, 0x6e, 0xb0, - 0xe1, 0x7b, 0x80, 0xd1, 0x3a, 0xae, 0xa5, 0x86, 0x5f, 0x01, 0x1e, 0xf8, 0x61, 0x21, 0xc8, 0xfc, - 0x63, 0xdb, 0xf4, 0xa3, 0xc2, 0xd6, 0x6d, 0x48, 0x16, 0xfd, 0x4b, 0xab, 0x20, 0x35, 0xbc, 0x2f, - 0x00, 0x21, 0x1c, 0x0f, 0x12, 0x17, 0xa4, 0x4d, 0x7a, 0xbb, 0x70, 0xfe, 0x1b, 0xbb, 0x39, 0xff, - 0x03, 0x02, 0x22, 0x87, 0xf0, 0xde, 0x68, 0xc3, 0x11, 0xa0, 0x63, 0xdc, 0x98, 0x1d, 0x37, 0xc8, - 0x1c, 0x3e, 0xc0, 0xda, 0x32, 0x6a, 0xcb, 0x6b, 0xf9, 0x2e, 0x19, 0xd1, 0x1f, 0x74, 0xf5, 0xd3, - 0x2b, 0xf8, 0x48, 0xb6, 0xa2, 0xb6, 0x88, 0x20, 0x6c, 0xee, 0xdc, 0x61, 0x77, 0x0a, 0xf2, 0xd4, - 0x99, 0xb7, 0x73, 0x79, 0x6a, 0x78, 0x5f, 0xc4, 0x9a, 0x57, 0xd5, 0xa0, 0x58, 0x94, 0xb4, 0x49, - 0x9e, 0xc3, 0xb8, 0xc5, 0xbc, 0x34, 0x2e, 0xed, 0xd1, 0x71, 0xe9, 0x44, 0x21, 0x2e, 0x99, 0x2a, - 0xfb, 0xa9, 0x28, 0x74, 0x8d, 0x35, 0xeb, 0xd9, 0x87, 0x76, 0x61, 0x90, 0xc2, 0xf1, 0x38, 0x44, - 0x89, 0x64, 0xfa, 0x59, 0x05, 0x0d, 0x91, 0xba, 0x21, 0x56, 0x2a, 0x6b, 0xd3, 0x1f, 0x51, 0x7e, - 0x9c, 0x56, 0xa0, 0x05, 0xbb, 0xd8, 0xd2, 0x2a, 0x37, 0x35, 0xf5, 0x14, 0xe5, 0xd0, 0x5f, 0x31, - 0x37, 0xad, 0x14, 0x87, 0xda, 0xe5, 0x99, 0xd4, 0x56, 0x58, 0x67, 0xdc, 0x85, 0x24, 0x27, 0xc6, - 0x0d, 0x5a, 0xcb, 0xdd, 0x9b, 0xb2, 0x8b, 0x88, 0x85, 0x02, 0xe8, 0x67, 0x6a, 0x59, 0x8e, 0x74, - 0x37, 0xd2, 0xf7, 0xe2, 0x21, 0x4c, 0x0d, 0x1f, 0x16, 0x76, 0x94, 0x86, 0xbd, 0xdc, 0x81, 0x50, - 0x0b, 0x2f, 0xb7, 0xa2, 0x4c, 0x78, 0xf5, 0x4c, 0xd6, 0xf0, 0x08, 0x5b, 0xbb, 0x0e, 0xae, 0x7c, - 0x00, 0x45, 0x4a, 0x32, 0xb3, 0xca, 0x54, 0x24, 0xc7, 0xf8, 0x0f, 0x05, 0xa3, 0xcf, 0xe2, 0xd1, - 0x3a, 0xf3, 0x2e, 0x87, 0x92, 0x6f, 0xa9, 0xd3, 0xe2, 0xb2, 0x50, 0x42, 0x28, 0x13, 0xe3, 0x69, - 0xb3, 0x78, 0x8e, 0x86, 0x4a, 0xe7, 0x88, 0x7e, 0x52, 0x2a, 0x0b, 0x42, 0xf9, 0x50, 0x95, 0x82, - 0xf4, 0xaf, 0xc2, 0x91, 0x6b, 0x94, 0xea, 0x81, 0xfe, 0x7c, 0x14, 0x4f, 0x70, 0x10, 0xac, 0xcd, - 0x5d, 0x78, 0xd1, 0x0f, 0x9b, 0xc9, 0xa2, 0x4b, 0x7d, 0xc5, 0x6f, 0x0a, 0x01, 0xa6, 0xd4, 0x47, - 0x38, 0x9e, 0x8c, 0xcb, 0x90, 0x72, 0xa0, 0xa9, 0xef, 0x7e, 0xb1, 0x8d, 0x74, 0x5a, 0x61, 0x97, - 0x4d, 0x2c, 0xfd, 0x7e, 0x18, 0xef, 0xcf, 0x73, 0x0b, 0xef, 0xf8, 0x2e, 0x90, 0x2f, 0x10, 0x9e, - 0x8a, 0x0b, 0xd2, 0xf4, 0x0d, 0x39, 0x9e, 0x4f, 0xda, 0xb3, 0x98, 0x37, 0x06, 0xe8, 0x11, 0x3a, - 0xfb, 0xde, 0x9d, 0x3f, 0x3f, 0x1e, 0xa2, 0xf4, 0x98, 0xbe, 0x58, 0x74, 0x16, 0xad, 0xfc, 0x72, - 0x72, 0x33, 0x53, 0xfd, 0xd6, 0xd3, 0x68, 0x8e, 0x7c, 0x8e, 0xf0, 0xf8, 0x2a, 0xc8, 0x0c, 0xf3, - 0x68, 0x37, 0x66, 0x5e, 0x30, 0x0f, 0x94, 0xf1, 0xac, 0x66, 0x7c, 0x8c, 0x3c, 0xda, 0x97, 0x31, - 0x7e, 0xbe, 0xa5, 0x38, 0x27, 0xd5, 0xa1, 0xca, 0x82, 0x1e, 0x39, 0xd6, 0x4d, 0x5a, 0xa8, 0x93, - 0x8d, 0xab, 0x83, 0x43, 0x55, 0xd3, 0xd2, 0x53, 0x1a, 0xf7, 0x38, 0xe9, 0x2f, 0x29, 0x79, 0x07, - 0x4f, 0x95, 0x83, 0x73, 0xc9, 0xf1, 0xbd, 0xc2, 0xb6, 0xd1, 0x43, 0xf2, 0x3c, 0x56, 0xd1, 0x33, - 0xda, 0xee, 0x29, 0x72, 0x72, 0xbb, 0xdd, 0x79, 0xd0, 0xb1, 0xac, 0x68, 0x7d, 0x01, 0x11, 0x81, - 0xc7, 0x0b, 0x81, 0xae, 0xe4, 0xce, 0xae, 0xf8, 0x67, 0x3c, 0xd2, 0x2b, 0x01, 0xc7, 0x66, 0x4f, - 0x6b, 0xb3, 0x27, 0xc9, 0x89, 0xd4, 0xac, 0x90, 0x1c, 0x9c, 0xc0, 0xea, 0x69, 0xf4, 0x5d, 0x84, - 0xa7, 0xe2, 0x2c, 0xd5, 0x6f, 0xbb, 0x97, 0x72, 0xb0, 0x31, 0x73, 0xef, 0x0f, 0x92, 0x44, 0x97, - 0x6c, 0x90, 0xb9, 0x6a, 0x1b, 0xe4, 0x3b, 0x84, 0x27, 0x75, 0xe9, 0x9f, 0x21, 0x4c, 0x77, 0x5b, - 0x28, 0xde, 0x0d, 0x06, 0xba, 0x99, 0x9f, 0xd0, 0xac, 0x96, 0x31, 0x57, 0x85, 0xd5, 0xe2, 0x0a, - 0x43, 0x9d, 0xbe, 0x9f, 0x10, 0x3e, 0x90, 0xde, 0x9c, 0x32, 0xee, 0x13, 0xbd, 0xb8, 0x4b, 0xb7, - 0xab, 0x81, 0xa2, 0x9f, 0xd7, 0xe8, 0x4b, 0xc6, 0x7c, 0x45, 0xf4, 0x98, 0x44, 0xd1, 0x7f, 0x8f, - 0xf0, 0x54, 0x7c, 0x4f, 0xe9, 0xe7, 0xf6, 0xd2, 0x4d, 0x66, 0xa0, 0xe4, 0x4f, 0x6a, 0xf2, 0x05, - 0xe3, 0x4c, 0x65, 0xf2, 0x00, 0x14, 0xf7, 0x0f, 0x08, 0xef, 0x4f, 0x6a, 0xe6, 0x0c, 0xbc, 0xc7, - 0x76, 0x2c, 0x97, 0xd5, 0x03, 0x25, 0x7f, 0x4a, 0x93, 0x2f, 0x1a, 0x67, 0x2b, 0x91, 0x8b, 0x18, - 0x44, 0xa1, 0xff, 0x8c, 0xf0, 0xc1, 0xec, 0x86, 0x96, 0xc1, 0xd3, 0x6e, 0xf8, 0xed, 0xd7, 0xb8, - 0x81, 0xe2, 0x5f, 0xd0, 0xf8, 0xcb, 0x86, 0x59, 0x09, 0x5f, 0xa6, 0x28, 0x6a, 0x01, 0xdf, 0x20, - 0x3c, 0xa1, 0xee, 0x84, 0x19, 0x7b, 0x8f, 0x30, 0x5e, 0xb8, 0x33, 0x0e, 0x14, 0xfb, 0x9c, 0xc6, - 0x36, 0x8d, 0xd3, 0xd5, 0x54, 0x97, 0x2c, 0x52, 0xc4, 0x5f, 0x21, 0x3c, 0xde, 0xe8, 0x9f, 0x21, - 0x1b, 0x0f, 0x26, 0x43, 0x2e, 0x6b, 0xde, 0x79, 0x63, 0xb6, 0x1a, 0x2f, 0xe8, 0x43, 0xf9, 0x25, - 0xc2, 0x13, 0xaa, 0x30, 0xec, 0x27, 0x70, 0xa1, 0x70, 0x1c, 0x28, 0xf0, 0xbc, 0x06, 0x7e, 0x9c, - 0xd2, 0xfe, 0xc0, 0x2d, 0x3f, 0xd4, 0xa8, 0x6f, 0xe3, 0x7d, 0xf1, 0x6d, 0x4f, 0xf4, 0x12, 0x35, - 0xbf, 0x88, 0x1a, 0x24, 0x7f, 0x9b, 0x16, 0xcf, 0xf4, 0x19, 0x6d, 0xeb, 0x1c, 0x59, 0xaa, 0x24, - 0xce, 0xcd, 0xa4, 0x7e, 0xbe, 0x65, 0xb5, 0x98, 0xf7, 0xc1, 0x10, 0x5a, 0x40, 0x44, 0xe2, 0x89, - 0x82, 0xa9, 0x9d, 0x20, 0x2c, 0x68, 0x84, 0x39, 0x52, 0xcd, 0x3f, 0x2d, 0xe6, 0x2d, 0x20, 0xf2, - 0x35, 0xc2, 0x53, 0x8d, 0x72, 0xbc, 0x3f, 0xde, 0x2b, 0xf4, 0x3c, 0xa8, 0x68, 0x6f, 0x69, 0xe6, - 0xd3, 0xf4, 0x3e, 0x49, 0x35, 0x0b, 0xf2, 0x17, 0x57, 0x7f, 0xbb, 0x3b, 0x8d, 0x6e, 0xdf, 0x9d, - 0x46, 0x7f, 0xdc, 0x9d, 0x46, 0xaf, 0x5f, 0xa8, 0xfe, 0xfb, 0x7b, 0xdb, 0x6f, 0xfa, 0xb5, 0x11, - 0xfd, 0x37, 0x7b, 0xf9, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x6d, 0x5c, 0x66, 0x41, 0xc7, 0x17, - 0x00, 0x00, + // 1451 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x98, 0xcf, 0x6f, 0x1c, 0x35, + 0x14, 0xc7, 0xe5, 0x4d, 0x9b, 0x26, 0xce, 0x8f, 0xb6, 0xa6, 0x2d, 0xcb, 0xa8, 0x4d, 0x53, 0x97, + 0x42, 0x9a, 0x36, 0x33, 0xf9, 0x51, 0xa0, 0x45, 0x02, 0x89, 0x36, 0x6d, 0x44, 0x59, 0x4a, 0x35, + 0x8b, 0x84, 0xe0, 0x82, 0x26, 0xb3, 0xce, 0x64, 0x9a, 0x99, 0xf1, 0x60, 0x7b, 0xb7, 0x0a, 0xa5, + 0x48, 0x70, 0x81, 0x03, 0x12, 0x07, 0x8e, 0xdc, 0x90, 0x10, 0x1c, 0x10, 0x20, 0x24, 0x24, 0x04, + 0x12, 0xea, 0x81, 0x03, 0xc7, 0x4a, 0xbd, 0x72, 0x40, 0x15, 0xff, 0x00, 0xff, 0x01, 0xb2, 0xe7, + 0x97, 0x27, 0xbb, 0xdd, 0x0e, 0xc9, 0x06, 0x7a, 0x1b, 0x7b, 0xc6, 0x7e, 0x1f, 0x7f, 0x9f, 0xfd, + 0xde, 0xf3, 0xc0, 0x53, 0xf1, 0x86, 0x67, 0x39, 0xb1, 0xef, 0x06, 0x3e, 0x89, 0x84, 0x75, 0x93, + 0xb2, 0x8d, 0xb5, 0x80, 0xde, 0xcc, 0x1f, 0xcc, 0x98, 0x51, 0x41, 0xd1, 0x48, 0xd6, 0x36, 0x8e, + 0x7a, 0x94, 0x7a, 0x01, 0x91, 0x63, 0x2c, 0x27, 0x8a, 0xa8, 0x70, 0x84, 0x4f, 0x23, 0x9e, 0x7c, + 0x67, 0x9c, 0xdb, 0x38, 0xcf, 0x4d, 0x9f, 0xca, 0xb7, 0xa1, 0xe3, 0xae, 0xfb, 0x11, 0x61, 0x9b, + 0x56, 0x6a, 0x82, 0x5b, 0x21, 0x11, 0x8e, 0xd5, 0x59, 0xb0, 0x3c, 0x12, 0x11, 0xe6, 0x08, 0xd2, + 0x4a, 0x47, 0xbd, 0xea, 0xf9, 0x62, 0xbd, 0xbd, 0x6a, 0xba, 0x34, 0xb4, 0x1c, 0xe6, 0xd1, 0x98, + 0xd1, 0x1b, 0xea, 0x61, 0x2e, 0x33, 0xcb, 0x8b, 0x49, 0x72, 0xc4, 0xce, 0x82, 0x13, 0xc4, 0xeb, + 0x4e, 0xf7, 0x74, 0xb8, 0x80, 0xb0, 0x5c, 0xca, 0x48, 0x0f, 0x93, 0xf8, 0x4e, 0x0d, 0x1e, 0x7e, + 0x23, 0x9d, 0xe9, 0x12, 0x23, 0x8e, 0x20, 0x36, 0x79, 0xa7, 0x4d, 0xb8, 0x40, 0x47, 0xe1, 0x68, + 0xe4, 0x84, 0x84, 0xc7, 0x8e, 0x4b, 0xea, 0x60, 0x1a, 0xcc, 0x8c, 0xda, 0x45, 0x07, 0x5a, 0x83, + 0xb9, 0x14, 0xf5, 0xda, 0x34, 0x98, 0x19, 0x5b, 0xbc, 0x6a, 0x16, 0xf4, 0x66, 0x46, 0xaf, 0x1e, + 0xde, 0xce, 0xe9, 0xcd, 0xce, 0x92, 0x19, 0x6f, 0x78, 0xa6, 0x5c, 0x80, 0x99, 0x4b, 0x9b, 0x2d, + 0xc0, 0xcc, 0x40, 0xec, 0x7c, 0x6e, 0x84, 0x21, 0xf4, 0x23, 0x2e, 0x9c, 0xc8, 0x25, 0x2f, 0x2f, + 0xd7, 0x87, 0x24, 0xc6, 0xc5, 0x5a, 0x1d, 0xd8, 0x5a, 0x2f, 0xc2, 0x70, 0x9c, 0x13, 0xd6, 0x21, + 0x6c, 0x99, 0x6d, 0xda, 0xed, 0xa8, 0xbe, 0x67, 0x1a, 0xcc, 0x8c, 0xd8, 0xa5, 0x3e, 0xf4, 0x26, + 0x9c, 0x70, 0xd5, 0xf2, 0x5e, 0x8b, 0x95, 0x9f, 0xea, 0x7b, 0x15, 0xf4, 0x92, 0x99, 0x68, 0x64, + 0xea, 0x8e, 0x2a, 0x10, 0xa5, 0xa3, 0xcc, 0xce, 0x82, 0x79, 0x49, 0x1f, 0x6a, 0x97, 0x67, 0xc2, + 0xdf, 0x03, 0x88, 0x32, 0xf2, 0x15, 0x22, 0x32, 0xfd, 0x10, 0xdc, 0x23, 0xe5, 0x4a, 0xa5, 0x53, + 0xcf, 0x65, 0x4d, 0x6b, 0x5b, 0x35, 0xbd, 0x0e, 0xa1, 0x47, 0x44, 0x06, 0x38, 0xa4, 0x00, 0xe7, + 0xab, 0x01, 0xae, 0xe4, 0xe3, 0x6c, 0x6d, 0x0e, 0x74, 0x04, 0x0e, 0xaf, 0xf9, 0x24, 0x68, 0x71, + 0xa5, 0xc9, 0xa8, 0x9d, 0xb6, 0xf0, 0x1d, 0x00, 0x1f, 0xcb, 0x90, 0x1b, 0x3e, 0x17, 0xd5, 0x7c, + 0xde, 0x84, 0x63, 0x81, 0xcf, 0x73, 0xc0, 0xc4, 0xed, 0x0b, 0xd5, 0x00, 0x1b, 0xc5, 0x40, 0x5b, + 0x9f, 0x45, 0x43, 0x1c, 0xd2, 0x11, 0xd1, 0x14, 0x84, 0xd2, 0xf2, 0x15, 0x3f, 0x10, 0x84, 0xa5, + 0xf8, 0x5a, 0x0f, 0xfe, 0x08, 0xc0, 0xc7, 0xf3, 0xfd, 0x42, 0x78, 0x7b, 0x35, 0xf4, 0x77, 0x20, + 0xbd, 0x01, 0x47, 0x42, 0x12, 0x52, 0xff, 0x5d, 0xd2, 0x52, 0x1c, 0x23, 0x76, 0xde, 0x96, 0x24, + 0xb1, 0xc3, 0x9c, 0x90, 0x08, 0xc2, 0xe4, 0xbe, 0x19, 0x92, 0x24, 0x45, 0x0f, 0xfe, 0x0d, 0xc0, + 0x43, 0x05, 0x89, 0x60, 0x9b, 0xdb, 0xc7, 0x38, 0x0b, 0x0f, 0x32, 0xc2, 0x85, 0xc3, 0x44, 0xb3, + 0xed, 0xba, 0x84, 0xf3, 0xb5, 0x76, 0x90, 0xf2, 0x74, 0xbf, 0x90, 0x5f, 0x47, 0xb4, 0x45, 0xae, + 0x48, 0xc1, 0x9a, 0x24, 0x20, 0xae, 0xa0, 0x99, 0x52, 0xdd, 0x2f, 0x1e, 0xba, 0x8c, 0x9b, 0x45, + 0x20, 0x90, 0x7a, 0x86, 0x64, 0x47, 0xcb, 0xe8, 0x06, 0x1b, 0x7a, 0x00, 0x18, 0x6e, 0xc0, 0x7a, + 0x66, 0xf8, 0x75, 0xc2, 0x42, 0x3f, 0xd2, 0x82, 0xd0, 0xbf, 0xb6, 0x8d, 0x3f, 0xd5, 0xb6, 0x76, + 0x53, 0xd0, 0xf8, 0x3f, 0x5a, 0x05, 0xaa, 0xc3, 0x7d, 0x21, 0xe1, 0xdc, 0xf1, 0x48, 0xea, 0x82, + 0xac, 0x89, 0xef, 0x6a, 0xf1, 0xa1, 0xb9, 0x93, 0xf8, 0x30, 0x20, 0x20, 0x74, 0x08, 0xee, 0x8d, + 0xd7, 0x1d, 0x4e, 0x54, 0x0c, 0x1c, 0xb5, 0x93, 0x06, 0x9a, 0x85, 0x07, 0x68, 0x5b, 0xc4, 0x6d, + 0x71, 0xbd, 0xd8, 0x25, 0xc3, 0xea, 0x83, 0xae, 0x7e, 0x7c, 0x15, 0x1e, 0xc9, 0x57, 0xd4, 0xe6, + 0x31, 0x89, 0x5a, 0xdb, 0x77, 0xd8, 0x3d, 0x4d, 0x9e, 0x06, 0xf5, 0xb6, 0x2f, 0x4f, 0x1d, 0xee, + 0x8b, 0x69, 0xeb, 0x9a, 0x1c, 0x94, 0x88, 0x92, 0x35, 0xd1, 0x4b, 0x10, 0x06, 0xd4, 0xcb, 0xe2, + 0xd6, 0x1e, 0x15, 0xb7, 0x4e, 0x68, 0x71, 0xcb, 0x94, 0xd9, 0x51, 0x46, 0xa9, 0xeb, 0xb4, 0xd5, + 0xc8, 0x3f, 0xb4, 0xb5, 0x41, 0x12, 0xc7, 0x63, 0x24, 0x4e, 0x25, 0x53, 0xcf, 0x32, 0x68, 0xf0, + 0xcc, 0x0d, 0x89, 0x52, 0x79, 0x1b, 0xff, 0x0c, 0x8a, 0xe3, 0xb4, 0x4c, 0x02, 0xb2, 0x83, 0x2d, + 0x2d, 0x73, 0x57, 0x4b, 0x4d, 0x51, 0x4e, 0x0d, 0x15, 0x73, 0xd7, 0xb2, 0x3e, 0xd4, 0x2e, 0xcf, + 0x24, 0xb7, 0xc2, 0x1a, 0x65, 0x2e, 0x49, 0x73, 0x66, 0xd2, 0xc0, 0xf5, 0xc2, 0xbd, 0x19, 0x3b, + 0x8f, 0x69, 0xc4, 0x09, 0xfe, 0x42, 0x2e, 0xcb, 0x11, 0xee, 0x7a, 0xf6, 0x9e, 0x3f, 0x7a, 0xa9, + 0x03, 0x7f, 0xa2, 0xed, 0x28, 0x05, 0x7b, 0xb9, 0x43, 0x22, 0x25, 0xbc, 0xd8, 0x8c, 0x73, 0xe1, + 0xe5, 0x33, 0x5a, 0x85, 0xc3, 0x74, 0xf5, 0x06, 0x71, 0xc5, 0x2e, 0x14, 0x31, 0xe9, 0xcc, 0x32, + 0x53, 0xa1, 0x02, 0xe3, 0x7f, 0x14, 0x0c, 0xbf, 0x08, 0x47, 0x1a, 0xd4, 0xbb, 0x1c, 0x09, 0xb6, + 0x29, 0x4f, 0x8b, 0x4b, 0x23, 0x41, 0x22, 0x91, 0x1a, 0xcf, 0x9a, 0xfa, 0x39, 0xaa, 0x95, 0xce, + 0x11, 0xfe, 0xbc, 0x54, 0x36, 0x44, 0xe2, 0x91, 0x2a, 0x15, 0xf1, 0xdf, 0xda, 0x91, 0x6b, 0x96, + 0xea, 0x81, 0xfe, 0x7c, 0x18, 0x8e, 0x33, 0xc2, 0x69, 0x9b, 0xb9, 0xe4, 0x15, 0x3f, 0x6a, 0xa5, + 0x8b, 0x2e, 0xf5, 0xe9, 0xdf, 0x68, 0x01, 0xa6, 0xd4, 0x87, 0x18, 0x9c, 0x48, 0xca, 0x90, 0x72, + 0xa0, 0x69, 0xec, 0x7c, 0xb1, 0xcd, 0x6c, 0x5a, 0x6e, 0x97, 0x4d, 0x2c, 0xfe, 0x71, 0x18, 0xee, + 0x2f, 0x72, 0x0b, 0xeb, 0xf8, 0x2e, 0x41, 0x5f, 0x01, 0x38, 0x99, 0x14, 0xac, 0xd9, 0x1b, 0x74, + 0xbc, 0x98, 0xb4, 0x67, 0xb1, 0x6f, 0x0c, 0xd0, 0x23, 0x78, 0xe6, 0xc3, 0x7b, 0x7f, 0x7d, 0x56, + 0xc3, 0xf8, 0x98, 0xba, 0x78, 0x74, 0x16, 0xac, 0xe2, 0xf2, 0x72, 0x2b, 0x57, 0xfd, 0xf6, 0xf3, + 0x60, 0x16, 0x7d, 0x09, 0xe0, 0xd8, 0x0a, 0x11, 0x39, 0xe6, 0xd1, 0x6e, 0xcc, 0xa2, 0xa0, 0x1e, + 0x28, 0xe3, 0x59, 0xc5, 0xf8, 0x14, 0x7a, 0xb2, 0x2f, 0x63, 0xf2, 0x7c, 0x5b, 0x72, 0x4e, 0xc8, + 0x43, 0x95, 0x07, 0x3d, 0x74, 0xac, 0x9b, 0x54, 0xab, 0xa3, 0x8d, 0x6b, 0x83, 0x43, 0x95, 0xd3, + 0xe2, 0x53, 0x0a, 0xf7, 0x38, 0xea, 0x2f, 0x29, 0x7a, 0x1f, 0x4e, 0x96, 0x83, 0x73, 0xc9, 0xf1, + 0xbd, 0xc2, 0xb6, 0xd1, 0x43, 0xf2, 0x22, 0x56, 0xe1, 0x33, 0xca, 0xee, 0x29, 0x74, 0x72, 0xab, + 0xdd, 0x39, 0xa2, 0x62, 0x99, 0x6e, 0x7d, 0x1e, 0x20, 0x0e, 0xc7, 0xb4, 0x40, 0x57, 0x72, 0x67, + 0x57, 0xfc, 0x33, 0x9e, 0xe8, 0x95, 0x80, 0x13, 0xb3, 0xa7, 0x95, 0xd9, 0x93, 0xe8, 0x44, 0x66, + 0x96, 0x0b, 0x46, 0x9c, 0xd0, 0xea, 0x69, 0xf4, 0x03, 0x00, 0x27, 0x93, 0x2c, 0xd5, 0x6f, 0xbb, + 0x97, 0x72, 0xb0, 0x31, 0xfd, 0xe0, 0x0f, 0xd2, 0x44, 0x97, 0x6e, 0x90, 0xd9, 0x6a, 0x1b, 0xe4, + 0x07, 0x00, 0x27, 0x54, 0xe9, 0x9f, 0x23, 0x4c, 0x75, 0x5b, 0xd0, 0xef, 0x06, 0x03, 0xdd, 0xcc, + 0xcf, 0x28, 0x56, 0xcb, 0x98, 0xad, 0xc2, 0x6a, 0x31, 0x89, 0x21, 0x4f, 0xdf, 0x2f, 0x00, 0x1e, + 0xc8, 0x6e, 0x4e, 0x39, 0xf7, 0x89, 0x5e, 0xdc, 0xa5, 0xdb, 0xd5, 0x40, 0xd1, 0xcf, 0x2b, 0xf4, + 0x45, 0x63, 0xae, 0x22, 0x7a, 0x42, 0x22, 0xe9, 0x7f, 0x04, 0x70, 0x32, 0xb9, 0xa7, 0xf4, 0x73, + 0x7b, 0xe9, 0x26, 0x33, 0x50, 0xf2, 0x67, 0x15, 0xf9, 0xbc, 0x71, 0xa6, 0x32, 0x79, 0x48, 0x24, + 0xf7, 0x4f, 0x00, 0xee, 0x4f, 0x6b, 0xe6, 0x1c, 0xbc, 0xc7, 0x76, 0x2c, 0x97, 0xd5, 0x03, 0x25, + 0x7f, 0x4e, 0x91, 0x2f, 0x18, 0x67, 0x2b, 0x91, 0xf3, 0x04, 0x44, 0xa2, 0xff, 0x0a, 0xe0, 0xc1, + 0xfc, 0x86, 0x96, 0xc3, 0xe3, 0x6e, 0xf8, 0xad, 0xd7, 0xb8, 0x81, 0xe2, 0x5f, 0x50, 0xf8, 0x4b, + 0x86, 0x59, 0x09, 0x5f, 0x64, 0x28, 0x72, 0x01, 0xdf, 0x01, 0x38, 0x2e, 0xef, 0x84, 0x39, 0x7b, + 0x8f, 0x30, 0xae, 0xdd, 0x19, 0x07, 0x8a, 0x7d, 0x4e, 0x61, 0x9b, 0xc6, 0xe9, 0x6a, 0xaa, 0x0b, + 0x1a, 0x4b, 0xe2, 0x6f, 0x00, 0x1c, 0x6b, 0xf6, 0xcf, 0x90, 0xcd, 0xdd, 0xc9, 0x90, 0x4b, 0x8a, + 0x77, 0xce, 0x98, 0xa9, 0xc6, 0x4b, 0xd4, 0xa1, 0xfc, 0x1a, 0xc0, 0x71, 0x59, 0x18, 0xf6, 0x13, + 0x58, 0x2b, 0x1c, 0x07, 0x0a, 0x3c, 0xa7, 0x80, 0x9f, 0xc6, 0xb8, 0x3f, 0x70, 0xe0, 0x47, 0x0a, + 0xf5, 0x3d, 0xb8, 0x2f, 0xb9, 0xed, 0xf1, 0x5e, 0xa2, 0x16, 0x17, 0x51, 0x03, 0x15, 0x6f, 0xb3, + 0xe2, 0x19, 0xbf, 0xa0, 0x6c, 0x9d, 0x43, 0x8b, 0x95, 0xc4, 0xb9, 0x95, 0xd6, 0xcf, 0xb7, 0xad, + 0x80, 0x7a, 0x1f, 0xd7, 0xc0, 0x3c, 0x40, 0x02, 0x8e, 0x6b, 0xa6, 0xb6, 0x83, 0x30, 0xaf, 0x10, + 0x66, 0x51, 0x35, 0xff, 0x04, 0xd4, 0x9b, 0x07, 0xe8, 0x5b, 0x00, 0x27, 0x9b, 0xe5, 0x78, 0x7f, + 0xbc, 0x57, 0xe8, 0xd9, 0xad, 0x68, 0x6f, 0x29, 0xe6, 0xd3, 0xf8, 0x21, 0x49, 0x35, 0x0f, 0xf2, + 0x17, 0x57, 0x7e, 0xbf, 0x3f, 0x05, 0xee, 0xde, 0x9f, 0x02, 0x7f, 0xde, 0x9f, 0x02, 0x6f, 0x5d, + 0xa8, 0xfe, 0x7b, 0x7c, 0xcb, 0x6f, 0xfc, 0xd5, 0x61, 0xf5, 0xb7, 0x7b, 0xe9, 0x9f, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x07, 0xe3, 0x32, 0x3c, 0xe7, 0x17, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -2333,6 +2342,13 @@ func (m *WorkflowListRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if len(m.NameFilter) > 0 { + i -= len(m.NameFilter) + copy(dAtA[i:], m.NameFilter) + i = encodeVarintWorkflow(dAtA, i, uint64(len(m.NameFilter))) + i-- + dAtA[i] = 0x22 + } if len(m.Fields) > 0 { i -= len(m.Fields) copy(dAtA[i:], m.Fields) @@ -3287,6 +3303,10 @@ func (m *WorkflowListRequest) Size() (n int) { if l > 0 { n += 1 + l + sovWorkflow(uint64(l)) } + l = len(m.NameFilter) + if l > 0 { + n += 1 + l + sovWorkflow(uint64(l)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -4215,6 +4235,38 @@ func (m *WorkflowListRequest) Unmarshal(dAtA []byte) error { } m.Fields = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NameFilter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWorkflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthWorkflow + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthWorkflow + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NameFilter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipWorkflow(dAtA[iNdEx:]) diff --git a/pkg/apiclient/workflow/workflow.proto b/pkg/apiclient/workflow/workflow.proto index edfeaf171280..17b234c06bfd 100644 --- a/pkg/apiclient/workflow/workflow.proto +++ b/pkg/apiclient/workflow/workflow.proto @@ -33,6 +33,8 @@ message WorkflowListRequest { k8s.io.apimachinery.pkg.apis.meta.v1.ListOptions listOptions = 2; // Fields to be included or excluded in the response. e.g. "items.spec,items.status.phase", "-items.status.nodes" string fields = 3; + // Filter type used for name filtering. Exact | Contains | Prefix. Default to Exact + string nameFilter = 4; } message WorkflowResubmitRequest { diff --git a/sdks/java/client/docs/WorkflowServiceApi.md b/sdks/java/client/docs/WorkflowServiceApi.md index ab2d95d3fbbd..d99bc3d91623 100644 --- a/sdks/java/client/docs/WorkflowServiceApi.md +++ b/sdks/java/client/docs/WorkflowServiceApi.md @@ -323,7 +323,7 @@ Name | Type | Description | Notes # **workflowServiceListWorkflows** -> IoArgoprojWorkflowV1alpha1WorkflowList workflowServiceListWorkflows(namespace, listOptionsLabelSelector, listOptionsFieldSelector, listOptionsWatch, listOptionsAllowWatchBookmarks, listOptionsResourceVersion, listOptionsResourceVersionMatch, listOptionsTimeoutSeconds, listOptionsLimit, listOptionsContinue, listOptionsSendInitialEvents, fields) +> IoArgoprojWorkflowV1alpha1WorkflowList workflowServiceListWorkflows(namespace, listOptionsLabelSelector, listOptionsFieldSelector, listOptionsWatch, listOptionsAllowWatchBookmarks, listOptionsResourceVersion, listOptionsResourceVersionMatch, listOptionsTimeoutSeconds, listOptionsLimit, listOptionsContinue, listOptionsSendInitialEvents, fields, nameFilter) @@ -361,8 +361,9 @@ public class Example { String listOptionsContinue = "listOptionsContinue_example"; // String | The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\". This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications. Boolean listOptionsSendInitialEvents = true; // Boolean | `sendInitialEvents=true` may be set together with `watch=true`. In that case, the watch stream will begin with synthetic events to produce the current state of objects in the collection. Once all such events have been sent, a synthetic \"Bookmark\" event will be sent. The bookmark will report the ResourceVersion (RV) corresponding to the set of objects, and be marked with `\"io.k8s.initial-events-end\": \"true\"` annotation. Afterwards, the watch stream will proceed as usual, sending watch events corresponding to changes (subsequent to the RV) to objects watched. When `sendInitialEvents` option is set, we require `resourceVersionMatch` option to also be set. The semantic of the watch request is as following: - `resourceVersionMatch` = NotOlderThan is interpreted as \"data at least as new as the provided `resourceVersion`\" and the bookmark event is send when the state is synced to a `resourceVersion` at least as fresh as the one provided by the ListOptions. If `resourceVersion` is unset, this is interpreted as \"consistent read\" and the bookmark event is send when the state is synced at least to the moment when request started being processed. - `resourceVersionMatch` set to any other value or unset Invalid error is returned. Defaults to true if `resourceVersion=\"\"` or `resourceVersion=\"0\"` (for backward compatibility reasons) and to false otherwise. +optional String fields = "fields_example"; // String | Fields to be included or excluded in the response. e.g. \"items.spec,items.status.phase\", \"-items.status.nodes\". + String nameFilter = "nameFilter_example"; // String | Filter type used for name filtering. Exact | Contains | Prefix. Default to Exact. try { - IoArgoprojWorkflowV1alpha1WorkflowList result = apiInstance.workflowServiceListWorkflows(namespace, listOptionsLabelSelector, listOptionsFieldSelector, listOptionsWatch, listOptionsAllowWatchBookmarks, listOptionsResourceVersion, listOptionsResourceVersionMatch, listOptionsTimeoutSeconds, listOptionsLimit, listOptionsContinue, listOptionsSendInitialEvents, fields); + IoArgoprojWorkflowV1alpha1WorkflowList result = apiInstance.workflowServiceListWorkflows(namespace, listOptionsLabelSelector, listOptionsFieldSelector, listOptionsWatch, listOptionsAllowWatchBookmarks, listOptionsResourceVersion, listOptionsResourceVersionMatch, listOptionsTimeoutSeconds, listOptionsLimit, listOptionsContinue, listOptionsSendInitialEvents, fields, nameFilter); System.out.println(result); } catch (ApiException e) { System.err.println("Exception when calling WorkflowServiceApi#workflowServiceListWorkflows"); @@ -391,6 +392,7 @@ Name | Type | Description | Notes **listOptionsContinue** | **String**| The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\". This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications. | [optional] **listOptionsSendInitialEvents** | **Boolean**| `sendInitialEvents=true` may be set together with `watch=true`. In that case, the watch stream will begin with synthetic events to produce the current state of objects in the collection. Once all such events have been sent, a synthetic \"Bookmark\" event will be sent. The bookmark will report the ResourceVersion (RV) corresponding to the set of objects, and be marked with `\"io.k8s.initial-events-end\": \"true\"` annotation. Afterwards, the watch stream will proceed as usual, sending watch events corresponding to changes (subsequent to the RV) to objects watched. When `sendInitialEvents` option is set, we require `resourceVersionMatch` option to also be set. The semantic of the watch request is as following: - `resourceVersionMatch` = NotOlderThan is interpreted as \"data at least as new as the provided `resourceVersion`\" and the bookmark event is send when the state is synced to a `resourceVersion` at least as fresh as the one provided by the ListOptions. If `resourceVersion` is unset, this is interpreted as \"consistent read\" and the bookmark event is send when the state is synced at least to the moment when request started being processed. - `resourceVersionMatch` set to any other value or unset Invalid error is returned. Defaults to true if `resourceVersion=\"\"` or `resourceVersion=\"0\"` (for backward compatibility reasons) and to false otherwise. +optional | [optional] **fields** | **String**| Fields to be included or excluded in the response. e.g. \"items.spec,items.status.phase\", \"-items.status.nodes\". | [optional] + **nameFilter** | **String**| Filter type used for name filtering. Exact | Contains | Prefix. Default to Exact. | [optional] ### Return type diff --git a/sdks/python/client/argo_workflows/api/workflow_service_api.py b/sdks/python/client/argo_workflows/api/workflow_service_api.py index b000b92a4a62..29d73f0bac40 100644 --- a/sdks/python/client/argo_workflows/api/workflow_service_api.py +++ b/sdks/python/client/argo_workflows/api/workflow_service_api.py @@ -351,6 +351,7 @@ def __init__(self, api_client=None): 'list_options_continue', 'list_options_send_initial_events', 'fields', + 'name_filter', ], 'required': [ 'namespace', @@ -392,6 +393,8 @@ def __init__(self, api_client=None): (bool,), 'fields': (str,), + 'name_filter': + (str,), }, 'attribute_map': { 'namespace': 'namespace', @@ -406,6 +409,7 @@ def __init__(self, api_client=None): 'list_options_continue': 'listOptions.continue', 'list_options_send_initial_events': 'listOptions.sendInitialEvents', 'fields': 'fields', + 'name_filter': 'nameFilter', }, 'location_map': { 'namespace': 'path', @@ -420,6 +424,7 @@ def __init__(self, api_client=None): 'list_options_continue': 'query', 'list_options_send_initial_events': 'query', 'fields': 'query', + 'name_filter': 'query', }, 'collection_format_map': { } @@ -1752,6 +1757,7 @@ def list_workflows( list_options_continue (str): The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\". This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.. [optional] list_options_send_initial_events (bool): `sendInitialEvents=true` may be set together with `watch=true`. In that case, the watch stream will begin with synthetic events to produce the current state of objects in the collection. Once all such events have been sent, a synthetic \"Bookmark\" event will be sent. The bookmark will report the ResourceVersion (RV) corresponding to the set of objects, and be marked with `\"io.k8s.initial-events-end\": \"true\"` annotation. Afterwards, the watch stream will proceed as usual, sending watch events corresponding to changes (subsequent to the RV) to objects watched. When `sendInitialEvents` option is set, we require `resourceVersionMatch` option to also be set. The semantic of the watch request is as following: - `resourceVersionMatch` = NotOlderThan is interpreted as \"data at least as new as the provided `resourceVersion`\" and the bookmark event is send when the state is synced to a `resourceVersion` at least as fresh as the one provided by the ListOptions. If `resourceVersion` is unset, this is interpreted as \"consistent read\" and the bookmark event is send when the state is synced at least to the moment when request started being processed. - `resourceVersionMatch` set to any other value or unset Invalid error is returned. Defaults to true if `resourceVersion=\"\"` or `resourceVersion=\"0\"` (for backward compatibility reasons) and to false otherwise. +optional. [optional] fields (str): Fields to be included or excluded in the response. e.g. \"items.spec,items.status.phase\", \"-items.status.nodes\".. [optional] + name_filter (str): Filter type used for name filtering. Exact | Contains | Prefix. Default to Exact.. [optional] _return_http_data_only (bool): response data without head status code and headers. Default is True. _preload_content (bool): if False, the urllib3.HTTPResponse object diff --git a/sdks/python/client/docs/WorkflowServiceApi.md b/sdks/python/client/docs/WorkflowServiceApi.md index 9a7be230c42c..b2288e27aaee 100644 --- a/sdks/python/client/docs/WorkflowServiceApi.md +++ b/sdks/python/client/docs/WorkflowServiceApi.md @@ -57770,6 +57770,7 @@ with argo_workflows.ApiClient(configuration) as api_client: list_options_continue = "listOptions.continue_example" # str | The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\". This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications. (optional) list_options_send_initial_events = True # bool | `sendInitialEvents=true` may be set together with `watch=true`. In that case, the watch stream will begin with synthetic events to produce the current state of objects in the collection. Once all such events have been sent, a synthetic \"Bookmark\" event will be sent. The bookmark will report the ResourceVersion (RV) corresponding to the set of objects, and be marked with `\"io.k8s.initial-events-end\": \"true\"` annotation. Afterwards, the watch stream will proceed as usual, sending watch events corresponding to changes (subsequent to the RV) to objects watched. When `sendInitialEvents` option is set, we require `resourceVersionMatch` option to also be set. The semantic of the watch request is as following: - `resourceVersionMatch` = NotOlderThan is interpreted as \"data at least as new as the provided `resourceVersion`\" and the bookmark event is send when the state is synced to a `resourceVersion` at least as fresh as the one provided by the ListOptions. If `resourceVersion` is unset, this is interpreted as \"consistent read\" and the bookmark event is send when the state is synced at least to the moment when request started being processed. - `resourceVersionMatch` set to any other value or unset Invalid error is returned. Defaults to true if `resourceVersion=\"\"` or `resourceVersion=\"0\"` (for backward compatibility reasons) and to false otherwise. +optional (optional) fields = "fields_example" # str | Fields to be included or excluded in the response. e.g. \"items.spec,items.status.phase\", \"-items.status.nodes\". (optional) + name_filter = "nameFilter_example" # str | Filter type used for name filtering. Exact | Contains | Prefix. Default to Exact. (optional) # example passing only required values which don't have defaults set try: @@ -57781,7 +57782,7 @@ with argo_workflows.ApiClient(configuration) as api_client: # example passing only required values which don't have defaults set # and optional values try: - api_response = api_instance.list_workflows(namespace, list_options_label_selector=list_options_label_selector, list_options_field_selector=list_options_field_selector, list_options_watch=list_options_watch, list_options_allow_watch_bookmarks=list_options_allow_watch_bookmarks, list_options_resource_version=list_options_resource_version, list_options_resource_version_match=list_options_resource_version_match, list_options_timeout_seconds=list_options_timeout_seconds, list_options_limit=list_options_limit, list_options_continue=list_options_continue, list_options_send_initial_events=list_options_send_initial_events, fields=fields) + api_response = api_instance.list_workflows(namespace, list_options_label_selector=list_options_label_selector, list_options_field_selector=list_options_field_selector, list_options_watch=list_options_watch, list_options_allow_watch_bookmarks=list_options_allow_watch_bookmarks, list_options_resource_version=list_options_resource_version, list_options_resource_version_match=list_options_resource_version_match, list_options_timeout_seconds=list_options_timeout_seconds, list_options_limit=list_options_limit, list_options_continue=list_options_continue, list_options_send_initial_events=list_options_send_initial_events, fields=fields, name_filter=name_filter) pprint(api_response) except argo_workflows.ApiException as e: print("Exception when calling WorkflowServiceApi->list_workflows: %s\n" % e) @@ -57804,6 +57805,7 @@ Name | Type | Description | Notes **list_options_continue** | **str**| The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\". This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications. | [optional] **list_options_send_initial_events** | **bool**| `sendInitialEvents=true` may be set together with `watch=true`. In that case, the watch stream will begin with synthetic events to produce the current state of objects in the collection. Once all such events have been sent, a synthetic \"Bookmark\" event will be sent. The bookmark will report the ResourceVersion (RV) corresponding to the set of objects, and be marked with `\"io.k8s.initial-events-end\": \"true\"` annotation. Afterwards, the watch stream will proceed as usual, sending watch events corresponding to changes (subsequent to the RV) to objects watched. When `sendInitialEvents` option is set, we require `resourceVersionMatch` option to also be set. The semantic of the watch request is as following: - `resourceVersionMatch` = NotOlderThan is interpreted as \"data at least as new as the provided `resourceVersion`\" and the bookmark event is send when the state is synced to a `resourceVersion` at least as fresh as the one provided by the ListOptions. If `resourceVersion` is unset, this is interpreted as \"consistent read\" and the bookmark event is send when the state is synced at least to the moment when request started being processed. - `resourceVersionMatch` set to any other value or unset Invalid error is returned. Defaults to true if `resourceVersion=\"\"` or `resourceVersion=\"0\"` (for backward compatibility reasons) and to false otherwise. +optional | [optional] **fields** | **str**| Fields to be included or excluded in the response. e.g. \"items.spec,items.status.phase\", \"-items.status.nodes\". | [optional] + **name_filter** | **str**| Filter type used for name filtering. Exact | Contains | Prefix. Default to Exact. | [optional] ### Return type diff --git a/server/utils/list_options.go b/server/utils/list_options.go index 69a03456cbd5..978592db3a14 100644 --- a/server/utils/list_options.go +++ b/server/utils/list_options.go @@ -13,12 +13,13 @@ import ( ) type ListOptions struct { - Namespace, Name, NamePrefix string - MinStartedAt, MaxStartedAt time.Time - LabelRequirements labels.Requirements - Limit, Offset int - ShowRemainingItemCount bool - StartedAtAscending bool + Namespace, Name string + NamePrefix, NameFilter string + MinStartedAt, MaxStartedAt time.Time + LabelRequirements labels.Requirements + Limit, Offset int + ShowRemainingItemCount bool + StartedAtAscending bool } func (l ListOptions) WithLimit(limit int) ListOptions { @@ -51,10 +52,11 @@ func (l ListOptions) WithStartedAtAscending(ascending bool) ListOptions { return l } -func BuildListOptions(options metav1.ListOptions, ns, namePrefix string) (ListOptions, error) { +func BuildListOptions(options metav1.ListOptions, ns, namePrefix, nameFilter string) (ListOptions, error) { if options.Continue == "" { options.Continue = "0" } + limit := int(options.Limit) offset, err := strconv.Atoi(options.Continue) @@ -123,6 +125,7 @@ func BuildListOptions(options metav1.ListOptions, ns, namePrefix string) (ListOp Namespace: namespace, Name: name, NamePrefix: namePrefix, + NameFilter: nameFilter, MinStartedAt: minStartedAt, MaxStartedAt: maxStartedAt, LabelRequirements: requirements, diff --git a/server/workflow/store/lister.go b/server/workflow/store/lister.go index 3a2dc0870a7a..e50ab6938e3e 100644 --- a/server/workflow/store/lister.go +++ b/server/workflow/store/lister.go @@ -10,8 +10,8 @@ import ( ) type WorkflowLister interface { - ListWorkflows(ctx context.Context, namespace, namePrefix string, listOptions metav1.ListOptions) (*wfv1.WorkflowList, error) - CountWorkflows(ctx context.Context, namespace, namePrefix string, listOptions metav1.ListOptions) (int64, error) + ListWorkflows(ctx context.Context, namespace, nameFilter string, listOptions metav1.ListOptions) (*wfv1.WorkflowList, error) + CountWorkflows(ctx context.Context, namespace, nameFilter string, listOptions metav1.ListOptions) (int64, error) } type kubeLister struct { @@ -24,7 +24,7 @@ func NewKubeLister(wfClient versioned.Interface) WorkflowLister { return &kubeLister{wfClient: wfClient} } -func (k *kubeLister) ListWorkflows(ctx context.Context, namespace, namePrefix string, listOptions metav1.ListOptions) (*wfv1.WorkflowList, error) { +func (k *kubeLister) ListWorkflows(ctx context.Context, namespace, nameFilter string, listOptions metav1.ListOptions) (*wfv1.WorkflowList, error) { wfList, err := k.wfClient.ArgoprojV1alpha1().Workflows(namespace).List(ctx, listOptions) if err != nil { return nil, err @@ -32,7 +32,7 @@ func (k *kubeLister) ListWorkflows(ctx context.Context, namespace, namePrefix st return wfList, nil } -func (k *kubeLister) CountWorkflows(ctx context.Context, namespace, namePrefix string, listOptions metav1.ListOptions) (int64, error) { +func (k *kubeLister) CountWorkflows(ctx context.Context, namespace, nameFilter string, listOptions metav1.ListOptions) (int64, error) { wfList, err := k.wfClient.ArgoprojV1alpha1().Workflows(namespace).List(ctx, listOptions) if err != nil { return 0, err diff --git a/server/workflow/store/sqlite_store.go b/server/workflow/store/sqlite_store.go index c06eda14e4c3..2c8aecfbc84e 100644 --- a/server/workflow/store/sqlite_store.go +++ b/server/workflow/store/sqlite_store.go @@ -88,8 +88,8 @@ func NewSQLiteStore(instanceService instanceid.Service) (*SQLiteStore, error) { return &SQLiteStore{conn: conn, instanceService: instanceService}, nil } -func (s *SQLiteStore) ListWorkflows(ctx context.Context, namespace, namePrefix string, listOptions metav1.ListOptions) (*wfv1.WorkflowList, error) { - options, err := sutils.BuildListOptions(listOptions, namespace, namePrefix) +func (s *SQLiteStore) ListWorkflows(ctx context.Context, namespace, nameFilter string, listOptions metav1.ListOptions) (*wfv1.WorkflowList, error) { + options, err := sutils.BuildListOptions(listOptions, namespace, "", nameFilter) if err != nil { return nil, err } @@ -129,8 +129,8 @@ where instanceid = ? }, nil } -func (s *SQLiteStore) CountWorkflows(ctx context.Context, namespace, namePrefix string, listOptions metav1.ListOptions) (int64, error) { - options, err := sutils.BuildListOptions(listOptions, namespace, namePrefix) +func (s *SQLiteStore) CountWorkflows(ctx context.Context, namespace, nameFilter string, listOptions metav1.ListOptions) (int64, error) { + options, err := sutils.BuildListOptions(listOptions, namespace, "", nameFilter) if err != nil { return 0, err } diff --git a/server/workflow/store/sqlite_store_test.go b/server/workflow/store/sqlite_store_test.go index e79477aa4d0b..cc96e4d0b8f9 100644 --- a/server/workflow/store/sqlite_store_test.go +++ b/server/workflow/store/sqlite_store_test.go @@ -133,6 +133,45 @@ func TestStoreOperation(t *testing.T) { require.NoError(t, err) assert.Len(t, wfList.Items, 5) }) + t.Run("TestListWorkflows name", func(t *testing.T) { + wfList, err := store.ListWorkflows(context.Background(), "argo", "Exact", metav1.ListOptions{Limit: 5, FieldSelector: "metadata.name=flow"}) + require.NoError(t, err) + assert.Empty(t, wfList.Items) + + wfList, err = store.ListWorkflows(context.Background(), "argo", "Exact", metav1.ListOptions{Limit: 5, FieldSelector: "metadata.name=workflow-1"}) + require.NoError(t, err) + assert.Len(t, wfList.Items, 1) + + wfList, err = store.ListWorkflows(context.Background(), "argo", "", metav1.ListOptions{Limit: 5, FieldSelector: "metadata.name=workflow-1"}) + require.NoError(t, err) + assert.Len(t, wfList.Items, 1) + }) + t.Run("TestListWorkflows namePrefix", func(t *testing.T) { + wfList, err := store.ListWorkflows(context.Background(), "argo", "Prefix", metav1.ListOptions{Limit: 5, FieldSelector: "metadata.name=flow"}) + require.NoError(t, err) + assert.Empty(t, wfList.Items) + + wfList, err = store.ListWorkflows(context.Background(), "argo", "Prefix", metav1.ListOptions{Limit: 5, FieldSelector: "metadata.name=workflow-"}) + require.NoError(t, err) + assert.Len(t, wfList.Items, 5) + + wfList, err = store.ListWorkflows(context.Background(), "argo", "Prefix", metav1.ListOptions{Limit: 5, FieldSelector: "metadata.name=workflow-1"}) + require.NoError(t, err) + assert.Len(t, wfList.Items, 1) + }) + t.Run("TestListWorkflows namePattern", func(t *testing.T) { + wfList, err := store.ListWorkflows(context.Background(), "argo", "Contains", metav1.ListOptions{Limit: 5, FieldSelector: "metadata.name=non-existing-pattern"}) + require.NoError(t, err) + assert.Empty(t, wfList.Items) + + wfList, err = store.ListWorkflows(context.Background(), "argo", "Contains", metav1.ListOptions{Limit: 5, FieldSelector: "metadata.name=flow"}) + require.NoError(t, err) + assert.Len(t, wfList.Items, 5) + + wfList, err = store.ListWorkflows(context.Background(), "argo", "Contains", metav1.ListOptions{Limit: 5, FieldSelector: "metadata.name=workflow-1"}) + require.NoError(t, err) + assert.Len(t, wfList.Items, 1) + }) t.Run("TestCountWorkflows", func(t *testing.T) { num, err := store.CountWorkflows(context.Background(), "argo", "", metav1.ListOptions{}) require.NoError(t, err) diff --git a/server/workflow/workflow_server.go b/server/workflow/workflow_server.go index 7c0c36182e3b..6f8e08a7386d 100644 --- a/server/workflow/workflow_server.go +++ b/server/workflow/workflow_server.go @@ -173,7 +173,8 @@ func (s *workflowServer) ListWorkflows(ctx context.Context, req *workflowpkg.Wor } s.instanceIDService.With(&listOption) - options, err := sutils.BuildListOptions(listOption, req.Namespace, "") + options, err := sutils.BuildListOptions(listOption, req.Namespace, "", req.NameFilter) + if err != nil { return nil, err } @@ -187,7 +188,7 @@ func (s *workflowServer) ListWorkflows(ctx context.Context, req *workflowpkg.Wor } var wfs wfv1.Workflows - liveWfCount, err := s.wfLister.CountWorkflows(ctx, req.Namespace, "", listOption) + liveWfCount, err := s.wfLister.CountWorkflows(ctx, req.Namespace, req.NameFilter, listOption) if err != nil { return nil, sutils.ToStatusError(err, codes.Internal) } @@ -200,7 +201,7 @@ func (s *workflowServer) ListWorkflows(ctx context.Context, req *workflowpkg.Wor // first fetch live workflows liveWfList := &wfv1.WorkflowList{} if liveWfCount > 0 && (options.Limit == 0 || options.Offset < int(liveWfCount)) { - liveWfList, err = s.wfLister.ListWorkflows(ctx, req.Namespace, "", listOption) + liveWfList, err = s.wfLister.ListWorkflows(ctx, req.Namespace, req.NameFilter, listOption) if err != nil { return nil, sutils.ToStatusError(err, codes.Internal) } diff --git a/server/workflowarchive/archived_workflow_server.go b/server/workflowarchive/archived_workflow_server.go index 2f6c69369dce..a3c8500783b2 100644 --- a/server/workflowarchive/archived_workflow_server.go +++ b/server/workflowarchive/archived_workflow_server.go @@ -41,7 +41,7 @@ func NewWorkflowArchiveServer(wfArchive sqldb.WorkflowArchive, offloadNodeStatus func (w *archivedWorkflowServer) ListArchivedWorkflows(ctx context.Context, req *workflowarchivepkg.ListArchivedWorkflowsRequest) (*wfv1.WorkflowList, error) { - options, err := sutils.BuildListOptions(*req.ListOptions, req.Namespace, req.NamePrefix) + options, err := sutils.BuildListOptions(*req.ListOptions, req.Namespace, req.NamePrefix, "") if err != nil { return nil, err } diff --git a/ui/src/app/shared/components/dropdown/dropdown.tsx b/ui/src/app/shared/components/dropdown/dropdown.tsx index 5c9253d8125d..50b1569e531a 100644 --- a/ui/src/app/shared/components/dropdown/dropdown.tsx +++ b/ui/src/app/shared/components/dropdown/dropdown.tsx @@ -7,10 +7,11 @@ import './dropdown.scss'; export interface DropDownProps { isMenu?: boolean; anchor: JSX.Element; + closeOnInsideClick?: boolean; children: ReactNode; } -export function DropDown({isMenu, anchor, children}: DropDownProps) { +export function DropDown({isMenu, anchor, closeOnInsideClick, children}: DropDownProps) { const [opened, setOpened] = useState(false); const [left, setLeft] = useState(0); const [top, setTop] = useState(0); @@ -56,7 +57,7 @@ export function DropDown({isMenu, anchor, children}: DropDownProps) { function close(event: MouseEvent) { // Doesn't close when clicked inside the portal area - if (contentEl.contains(event.target as Node) || anchorEl.contains(event.target as Node)) { + if (!closeOnInsideClick && (contentEl.contains(event.target as Node) || anchorEl.contains(event.target as Node))) { return; } diff --git a/ui/src/app/shared/components/input-filter.scss b/ui/src/app/shared/components/input-filter.scss new file mode 100644 index 000000000000..76dfe8e6785c --- /dev/null +++ b/ui/src/app/shared/components/input-filter.scss @@ -0,0 +1,10 @@ +.input-filter { + display: flex; + align-items: center; + justify-content: space-between; + + div:first-child { + flex: 1; + } +} + diff --git a/ui/src/app/shared/components/input-filter.tsx b/ui/src/app/shared/components/input-filter.tsx index 14e781aa420c..c73cb4c7e9e4 100644 --- a/ui/src/app/shared/components/input-filter.tsx +++ b/ui/src/app/shared/components/input-filter.tsx @@ -1,11 +1,15 @@ import {Autocomplete} from 'argo-ui/src/components/autocomplete/autocomplete'; import React, {useState} from 'react'; +import './input-filter.scss'; + interface InputProps { value: string; placeholder?: string; name: string; onChange: (input: string) => void; + filterSuggestions?: boolean; + autoHighlight?: boolean; } export function InputFilter(props: InputProps) { @@ -44,7 +48,7 @@ export function InputFilter(props: InputProps) { } return ( - <> +
{ @@ -62,6 +68,6 @@ export function InputFilter(props: InputProps) { }}> - +
); } diff --git a/ui/src/app/shared/services/utils.ts b/ui/src/app/shared/services/utils.ts index 102955ad6fa2..7b74e1c87b06 100644 --- a/ui/src/app/shared/services/utils.ts +++ b/ui/src/app/shared/services/utils.ts @@ -1,3 +1,4 @@ +import {NameFilterKeys} from '../../workflows/components/workflow-filters/workflow-filters'; import {Pagination} from '../pagination'; export function queryParams(filter: { @@ -5,6 +6,7 @@ export function queryParams(filter: { name?: string; namePrefix?: string; namePattern?: string; + nameFilter?: NameFilterKeys; phases?: Array; labels?: Array; createdAfter?: Date; @@ -35,6 +37,9 @@ export function queryParams(filter: { if (filter.namePattern) { queryParams.push(`namePattern=${filter.namePattern}`); } + if (filter.nameFilter) { + queryParams.push(`nameFilter=${filter.nameFilter}`); + } if (filter.resourceVersion) { queryParams.push(`listOptions.resourceVersion=${filter.resourceVersion}`); } diff --git a/ui/src/app/shared/services/workflows-service.ts b/ui/src/app/shared/services/workflows-service.ts index a5cef79434b9..71a549edc397 100644 --- a/ui/src/app/shared/services/workflows-service.ts +++ b/ui/src/app/shared/services/workflows-service.ts @@ -9,6 +9,7 @@ import {Pagination} from '../pagination'; import {queryParams} from './utils'; import requests from './requests'; import {WorkflowDeleteResponse} from './responses'; +import {NameFilterKeys} from '../../workflows/components/workflow-filters/workflow-filters'; function isString(value: any): value is string { return typeof value === 'string'; @@ -51,9 +52,11 @@ export const WorkflowsService = { 'items.status.estimatedDuration', 'items.status.progress', 'items.spec.suspend' - ] + ], + name?: string, + nameFilter?: NameFilterKeys ) { - const params = queryParams({phases, labels, pagination}); + const params = queryParams({phases, labels, pagination, name, nameFilter}); params.push(`fields=${fields.join(',')}`); return requests.get(`api/v1/workflows/${namespace}?${params.join('&')}`).then(res => res.body as WorkflowList); }, diff --git a/ui/src/app/workflows/components/workflow-filters/workflow-filters.scss b/ui/src/app/workflows/components/workflow-filters/workflow-filters.scss index 3e9a03ad1463..1749070ee4e8 100644 --- a/ui/src/app/workflows/components/workflow-filters/workflow-filters.scss +++ b/ui/src/app/workflows/components/workflow-filters/workflow-filters.scss @@ -32,4 +32,8 @@ flex-direction: row; align-items: center; justify-content: space-between; -} \ No newline at end of file +} + +#top-bar__filter-list { + column-count: 1; +} diff --git a/ui/src/app/workflows/components/workflow-filters/workflow-filters.tsx b/ui/src/app/workflows/components/workflow-filters/workflow-filters.tsx index 9a29c75e3a9b..58c865f6fc36 100644 --- a/ui/src/app/workflows/components/workflow-filters/workflow-filters.tsx +++ b/ui/src/app/workflows/components/workflow-filters/workflow-filters.tsx @@ -1,6 +1,8 @@ import * as React from 'react'; import {useMemo} from 'react'; import DatePicker from 'react-datepicker'; +import classNames from 'classnames'; + import 'react-datepicker/dist/react-datepicker.css'; import * as models from '../../../../models'; @@ -10,9 +12,30 @@ import {DataLoaderDropdown} from '../../../shared/components/data-loader-dropdow import {NamespaceFilter} from '../../../shared/components/namespace-filter'; import {TagsInput} from '../../../shared/components/tags-input/tags-input'; import {services} from '../../../shared/services'; +import {InputFilter} from '../../../shared/components/input-filter'; +import {DropDown} from '../../../shared/components/dropdown/dropdown'; import './workflow-filters.scss'; +const NAME_FILTERS = [ + { + title: 'Name Contains', + id: 'Contains' as const + }, + { + title: 'Name Prefix', + id: 'Prefix' as const + }, + { + title: 'Name Exact', + id: 'Exact' as const + } +]; + +export const NAME_FILTER_KEYS = NAME_FILTERS.map(item => item.id); + +export type NameFilterKeys = (typeof NAME_FILTER_KEYS)[number]; + interface WorkflowFilterProps { workflows: models.Workflow[]; namespace: string; @@ -26,9 +49,14 @@ interface WorkflowFilterProps { setLabels: (labels: string[]) => void; setCreatedAfter: (createdAfter: Date) => void; setFinishedBefore: (finishedBefore: Date) => void; + nameFilter: NameFilterKeys; + nameValue: string; + setNameFilter: (nameFilter: NameFilterKeys) => void; + setNameValue: (nameValue: string) => void; } export function WorkflowFilters(props: WorkflowFilterProps) { + const nameFilter = NAME_FILTERS.find(item => item.id === props.nameFilter); function setLabel(name: string, value: string) { props.setLabels([name.concat('=' + value)]); } @@ -57,6 +85,10 @@ export function WorkflowFilters(props: WorkflowFilterProps) { return results; }, [props.workflows, props.phaseItems]); + function handleNameFilterChange(item: {title: string; id: string}) { + props.setNameFilter(item.id as NameFilterKeys); + } + return (
@@ -64,6 +96,27 @@ export function WorkflowFilters(props: WorkflowFilterProps) {

Namespace

+
+ +

+ {nameFilter.title}