diff --git a/controllers/loki.go b/controllers/loki.go index 5e38a98..3bc5df5 100644 --- a/controllers/loki.go +++ b/controllers/loki.go @@ -27,14 +27,13 @@ type LokiInfo struct { // @Description get logs // @Param body body models.compute true "The compute content" // @Success 200 {workspace} models.workspace -// @router / [post] +// @router /:id [post] func (o *LokiController) GetLogs() { - + id := o.Ctx.Input.Param(":id") var resp map[string]interface{} json.Unmarshal(o.Ctx.Input.CopyBody(100000), &resp) path := "/loki/api/v1/query_range" - if len(resp) > 0 { start := fmt.Sprintf("%v", resp["start"]) if len(start) > 10 { @@ -44,7 +43,9 @@ func (o *LokiController) GetLogs() { if len(end) > 10 { end = end[0:10] } - query := []string{} + query := []string{ + "workflow_execution_id=\"" + id + "\"", + } for k, v := range resp { if k == "start" || k == "end" { continue @@ -96,6 +97,10 @@ func (o *LokiController) GetLogs() { // The server connects to Loki's /loki/api/v1/tail WebSocket endpoint and // forwards every message it receives until the client disconnects. func LogsStreamHandler(w http.ResponseWriter, r *http.Request) { + execID := strings.TrimSuffix( + strings.TrimPrefix(r.URL.Path, "/oc/logs/"), + "", + ) conn, err := wsUpgrader.Upgrade(w, r, nil) if err != nil { return @@ -112,7 +117,9 @@ func LogsStreamHandler(w http.ResponseWriter, r *http.Request) { start = start[:10] } - var labels []string + labels := []string{ + "workflow_execution_id=\"" + execID + "\"", + } for k, v := range query { if k == "start" || k == "end" { continue diff --git a/controllers/sheduler.go b/controllers/sheduler.go index 4fd5633..712ffe8 100644 --- a/controllers/sheduler.go +++ b/controllers/sheduler.go @@ -198,6 +198,10 @@ func CheckStreamHandler(w http.ResponseWriter, r *http.Request) { schedulerMu.Unlock() if updated.Confirm { + // Subscribe BEFORE calling Schedule to avoid missing the notification. + confirmCh, confirmUnsub := infrastructure.SubscribeSessionConfirmation(executionsID) + defer confirmUnsub() + workflowScheduler.UUID = executionsID _, _, _, schedErr := infrastructure.Schedule(&workflowScheduler, wfID, req) if schedErr != nil { @@ -206,8 +210,23 @@ func CheckStreamHandler(w http.ResponseWriter, r *http.Request) { }) return } + fmt.Println("UPDATE CONFIRM — waiting for execution confirmation") + select { + case <-confirmCh: + _ = conn.WriteJSON(map[string]interface{}{ + "confirmed": true, + "scheduling_id": executionsID, + }) + case <-time.After(60 * time.Second): + _ = conn.WriteJSON(map[string]interface{}{ + "confirmed": false, + "error": "confirmation timeout: scheduling accepted but peers did not confirm in time", + }) + case <-ctx.Done(): + // client disconnected before confirmation + } confirmed = true - fmt.Println("UPDATE CONFIRM") + fmt.Println("UPDATE CONFIRM done") return } // Detect mode change before updating local vars. diff --git a/controllers/workflow_execution.go b/controllers/workflow_execution.go index 036949b..5c6806e 100644 --- a/controllers/workflow_execution.go +++ b/controllers/workflow_execution.go @@ -85,6 +85,30 @@ func (o *WorkflowExecutionController) Get() { o.ServeJSON() } +// @Title Delete +// @Description find workflow by workflowid +// @Param id path string true "the workflowid you want to get" +// @Success 200 {workflow} models.workflow +// @router /:id [delete] +func (o *WorkflowExecutionController) Delete() { + user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request) + id := o.Ctx.Input.Param(":id") + data := oclib.NewRequest(collection, user, peerID, groups, nil).LoadOne(id) + if b := data.ToBookings(); b != nil { + bAccess := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.BOOKING), nil) + s := bAccess.Search(&dbs.Filters{ + And: map[string][]dbs.Filter{ + "execution_id": {{Operator: dbs.EQUAL.String(), Value: b.ExecutionID}}, + }, + }, "", false, 0, 10000) + for _, ss := range s.Data { + bAccess.DeleteOne(ss.GetID()) + } + } + o.Data["json"] = oclib.NewRequest(collection, user, peerID, groups, nil).DeleteOne(id) + o.ServeJSON() +} + // @Title Search // @Description find compute by key word // @Param search path string true "the search you want to get" diff --git a/env.env b/env.env index c0d18f1..d60dd97 100644 --- a/env.env +++ b/env.env @@ -1,4 +1,4 @@ -KUBERNETES_SERVICE_HOST=192.168.47.20 -KUBE_CA="LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdGMyVnkKZG1WeUxXTmhRREUzTWpNeE1USXdNell3SGhjTk1qUXdPREE0TVRBeE16VTJXaGNOTXpRd09EQTJNVEF4TXpVMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRjMlZ5ZG1WeUxXTmhRREUzTWpNeE1USXdNell3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFTVlk3ZHZhNEdYTVdkMy9jMlhLN3JLYjlnWXgyNSthaEE0NmkyNVBkSFAKRktQL2UxSVMyWVF0dzNYZW1TTUQxaStZdzJSaVppNUQrSVZUamNtNHdhcnFvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVWtlUVJpNFJiODduME5yRnZaWjZHClc2SU55NnN3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnRXA5ck04WmdNclRZSHYxZjNzOW5DZXZZeWVVa3lZUk4KWjUzazdoaytJS1FDSVFDbk05TnVGKzlTakIzNDFacGZ5ays2NEpWdkpSM3BhcmVaejdMd2lhNm9kdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K" -KUBE_CERT="LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrVENDQVRlZ0F3SUJBZ0lJWUxWNkFPQkdrU1F3Q2dZSUtvWkl6ajBFQXdJd0l6RWhNQjhHQTFVRUF3d1kKYXpOekxXTnNhV1Z1ZEMxallVQXhOekl6TVRFeU1ETTJNQjRYRFRJME1EZ3dPREV3TVRNMU5sb1hEVEkxTURndwpPREV3TVRNMU5sb3dNREVYTUJVR0ExVUVDaE1PYzNsemRHVnRPbTFoYzNSbGNuTXhGVEFUQmdOVkJBTVRESE41CmMzUmxiVHBoWkcxcGJqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJGQ2Q1MFdPeWdlQ2syQzcKV2FrOWY4MVAvSkJieVRIajRWOXBsTEo0ck5HeHFtSjJOb2xROFYxdUx5RjBtOTQ2Nkc0RmRDQ2dqaXFVSk92Swp3NVRPNnd5alNEQkdNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFmCkJnTlZIU01FR0RBV2dCVFJkOFI5cXVWK2pjeUVmL0ovT1hQSzMyS09XekFLQmdncWhrak9QUVFEQWdOSUFEQkYKQWlFQTArbThqTDBJVldvUTZ0dnB4cFo4NVlMalF1SmpwdXM0aDdnSXRxS3NmUVVDSUI2M2ZNdzFBMm5OVWU1TgpIUGZOcEQwSEtwcVN0Wnk4djIyVzliYlJUNklZCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJlRENDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdFkyeHAKWlc1MExXTmhRREUzTWpNeE1USXdNell3SGhjTk1qUXdPREE0TVRBeE16VTJXaGNOTXpRd09EQTJNVEF4TXpVMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRZMnhwWlc1MExXTmhRREUzTWpNeE1USXdNell3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFRc3hXWk9pbnIrcVp4TmFEQjVGMGsvTDF5cE01VHAxOFRaeU92ektJazQKRTFsZWVqUm9STW0zNmhPeVljbnN3d3JoNnhSUnBpMW5RdGhyMzg0S0Z6MlBvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVTBYZkVmYXJsZm8zTWhIL3lmemx6Cnl0OWlqbHN3Q2dZSUtvWkl6ajBFQXdJRFNRQXdSZ0loQUxJL2dNYnNMT3MvUUpJa3U2WHVpRVMwTEE2cEJHMXgKcnBlTnpGdlZOekZsQWlFQW1wdjBubjZqN3M0MVI0QzFNMEpSL0djNE53MHdldlFmZWdEVGF1R2p3cFk9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K" -KUBE_DATA="LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU5ZS1BFb1dhd1NKUzJlRW5oWmlYMk5VZlY1ZlhKV2krSVNnV09TNFE5VTlvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFVUozblJZN0tCNEtUWUx0WnFUMS96VS84a0Z2Sk1lUGhYMm1Vc25pczBiR3FZblkyaVZEeApYVzR2SVhTYjNqcm9iZ1YwSUtDT0twUWs2OHJEbE03ckRBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=" +KUBERNETES_SERVICE_HOST=192.168.1.169 +KUBE_CA="LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdGMyVnkKZG1WeUxXTmhRREUzTnpReU56STVNVEF3SGhjTk1qWXdNekl6TVRNek5URXdXaGNOTXpZd016SXdNVE16TlRFdwpXakFqTVNFd0h3WURWUVFEREJock0zTXRjMlZ5ZG1WeUxXTmhRREUzTnpReU56STVNVEF3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFSSGpYRDVpbnRIYWZWSk5VaDFlRnIxcXBKdFlkUmc5NStKVENEa0tadTIKYjUxRXlKaG1zanRIY3BDUndGL1VGMzlvdzY4TFBUcjBxaUorUHlhQTBLZUtvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVTdWQkNzZVN3ajJ2cmczMFE5UG8vCnV6ZzAvMjR3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUloQUlEOVY2aFlUSS83ZW1hRzU0dDdDWVU3TXFSdDdESUkKNlgvSUwrQ0RLbzlNQWlCdlFEMGJmT0tVWDc4UmRGdUplcEhEdWFUMUExaGkxcWdIUGduM1dZdDBxUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K" +KUBE_CERT="LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrVENDQVRlZ0F3SUJBZ0lJUU5KbFNJQUJPMDR3Q2dZSUtvWkl6ajBFQXdJd0l6RWhNQjhHQTFVRUF3d1kKYXpOekxXTnNhV1Z1ZEMxallVQXhOemMwTWpjeU9URXdNQjRYRFRJMk1ETXlNekV6TXpVeE1Gb1hEVEkzTURNeQpNekV6TXpVeE1Gb3dNREVYTUJVR0ExVUVDaE1PYzNsemRHVnRPbTFoYzNSbGNuTXhGVEFUQmdOVkJBTVRESE41CmMzUmxiVHBoWkcxcGJqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJMY3Uwb2pUbVg4RFhTQkYKSHZwZDZNVEoyTHdXc1lRTmdZVURXRDhTVERIUWlCczlMZ0x5ZTdOMEFvZk85RkNZVW1HamhiaVd3WFVHR3dGTgpUdlRMU2lXalNEQkdNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFmCkJnTlZIU01FR0RBV2dCUlJhRW9wQzc5NGJyTHlnR0g5SVhvbDZTSmlFREFLQmdncWhrak9QUVFEQWdOSUFEQkYKQWlFQWhaRUlrSWV3Y1loL1NmTFVCVjE5MW1CYTNRK0J5S2J5eTVlQmpwL3kzeWtDSUIxWTJicTVOZTNLUUU4RAprNnNzeFJrbjJmN0VoWWVRQU1pUlJ2MjIweDNLCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdFkyeHAKWlc1MExXTmhRREUzTnpReU56STVNVEF3SGhjTk1qWXdNekl6TVRNek5URXdXaGNOTXpZd016SXdNVE16TlRFdwpXakFqTVNFd0h3WURWUVFEREJock0zTXRZMnhwWlc1MExXTmhRREUzTnpReU56STVNVEF3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFTcTdVTC85MEc1ZmVTaE95NjI3eGFZWlM5dHhFdWFoWFQ3Vk5wZkpQSnMKaEdXd2UxOXdtbXZzdlp6dlNPUWFRSzJaMmttN0hSb1IrNlA1YjIyamczbHVvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVVVXaEtLUXUvZUc2eThvQmgvU0Y2Ckpla2lZaEF3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUloQUk3cGxHczFtV20ySDErbjRobDBNTk13RmZzd0o5ZXIKTzRGVkM0QzhwRG44QWlCN3NZMVFwd2M5VkRUeGNZaGxuZzZNUzRXai85K0lHWjJxcy94UStrMjdTQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K" +KUBE_DATA="LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUROZDRnWXd6aVRhK1hwNnFtNVc3SHFzc1JJNkREaUJTbUV2ZHoxZzk3VGxvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFdHk3U2lOT1pmd05kSUVVZStsM294TW5ZdkJheGhBMkJoUU5ZUHhKTU1kQ0lHejB1QXZKNwpzM1FDaDg3MFVKaFNZYU9GdUpiQmRRWWJBVTFPOU10S0pRPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=" diff --git a/go.mod b/go.mod index 8a2db8b..d79ccd3 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module oc-scheduler go 1.25.0 require ( - cloud.o-forge.io/core/oc-lib v0.0.0-20260408134044-284533ad1d7b + cloud.o-forge.io/core/oc-lib v0.0.0-20260410075751-d7b2ef6ae120 github.com/beego/beego/v2 v2.3.8 github.com/google/uuid v1.6.0 github.com/robfig/cron v1.2.0 diff --git a/go.sum b/go.sum index 7c8e164..8485559 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,10 @@ cloud.o-forge.io/core/oc-lib v0.0.0-20260407090927-6fe91eda875d h1:54Vl14gurwAkm cloud.o-forge.io/core/oc-lib v0.0.0-20260407090927-6fe91eda875d/go.mod h1:+ENuvBfZdESSvecoqGY/wSvRlT3vinEolxKgwbOhUpA= cloud.o-forge.io/core/oc-lib v0.0.0-20260408134044-284533ad1d7b h1:mOU+tc87/KEQgFmw1RcQ9E9Rbz8Q2jLOh5Cpu6po9Ww= cloud.o-forge.io/core/oc-lib v0.0.0-20260408134044-284533ad1d7b/go.mod h1:+ENuvBfZdESSvecoqGY/wSvRlT3vinEolxKgwbOhUpA= +cloud.o-forge.io/core/oc-lib v0.0.0-20260409065442-c340146c8db1 h1:xpz/wRyZ7DfPjk9L5NjIggdWcGFI6wsoq+gvOh+9NKA= +cloud.o-forge.io/core/oc-lib v0.0.0-20260409065442-c340146c8db1/go.mod h1:+ENuvBfZdESSvecoqGY/wSvRlT3vinEolxKgwbOhUpA= +cloud.o-forge.io/core/oc-lib v0.0.0-20260410075751-d7b2ef6ae120 h1:CMOOpmpgkD63Gq7ukmXG6r+WlJxvpSgDRmalpWPhaIg= +cloud.o-forge.io/core/oc-lib v0.0.0-20260410075751-d7b2ef6ae120/go.mod h1:+ENuvBfZdESSvecoqGY/wSvRlT3vinEolxKgwbOhUpA= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= diff --git a/infrastructure/api.go b/infrastructure/api.go index 5ad2632..37171f1 100644 --- a/infrastructure/api.go +++ b/infrastructure/api.go @@ -52,6 +52,10 @@ func GetWorkflowPeerIDs(wfID string, req *tools.APIRequest) ([]string, error) { // Planner subscriptions // --------------------------------------------------------------------------- +func SubscribeSessionConfirmation(executionsID string) (<-chan struct{}, func()) { + return execution.SubscribeSessionConfirmation(executionsID) +} + func SubscribePlannerUpdates(peerIDs []string) (<-chan string, func()) { return planner.GetPlannerService().SubscribePlannerUpdates(peerIDs...) } diff --git a/infrastructure/execution/execution.go b/infrastructure/execution/execution.go index 908e399..8b74ed0 100644 --- a/infrastructure/execution/execution.go +++ b/infrastructure/execution/execution.go @@ -24,6 +24,46 @@ import ( "go.mongodb.org/mongo-driver/bson/primitive" ) +// --------------------------------------------------------------------------- +// Session confirmation pub/sub +// --------------------------------------------------------------------------- + +var sessionConfirmMu sync.Mutex +var sessionConfirmSubs = map[string][]chan struct{}{} + +// SubscribeSessionConfirmation returns a channel that receives one signal when +// the first execution of the given session is fully confirmed (IsDraft=false). +// The returned cancel func must be called to clean up. +func SubscribeSessionConfirmation(executionsID string) (<-chan struct{}, func()) { + ch := make(chan struct{}, 1) + sessionConfirmMu.Lock() + sessionConfirmSubs[executionsID] = append(sessionConfirmSubs[executionsID], ch) + sessionConfirmMu.Unlock() + return ch, func() { + sessionConfirmMu.Lock() + subs := sessionConfirmSubs[executionsID] + for i, c := range subs { + if c == ch { + sessionConfirmSubs[executionsID] = append(subs[:i], subs[i+1:]...) + break + } + } + sessionConfirmMu.Unlock() + } +} + +func notifySessionConfirmed(executionsID string) { + sessionConfirmMu.Lock() + subs := sessionConfirmSubs[executionsID] + sessionConfirmMu.Unlock() + for _, ch := range subs { + select { + case ch <- struct{}{}: + default: + } + } +} + // --------------------------------------------------------------------------- // Global execution lock registry // --------------------------------------------------------------------------- @@ -135,6 +175,7 @@ func UpdateExecutionState(payload []byte, dt tools.DataType) { return } if allConfirmed { + go notifySessionConfirmed(exec.ExecutionsID) go confirmSessionOrder(exec.ExecutionsID, adminReq) obj, _, err := workflow.NewAccessor(adminReq).LoadOne(exec.WorkflowID) if err == nil && obj != nil { diff --git a/main.go b/main.go index 7ddaa55..7cea505 100644 --- a/main.go +++ b/main.go @@ -26,7 +26,7 @@ func main() { oclib.InitAPI(appname, map[string][]string{ "/oc/check/:id": {"GET"}, - "/oc/logs": {"GET"}, + "/oc/logs/:id": {"GET"}, }) go planner.InitPlanner() go scheduling_resources.InitSchedulingResource() diff --git a/routers/commentsRouter.go b/routers/commentsRouter.go index 829ca3a..4f443cc 100644 --- a/routers/commentsRouter.go +++ b/routers/commentsRouter.go @@ -64,7 +64,7 @@ func init() { beego.GlobalControllerRouter["oc-scheduler/controllers:LokiController"] = append(beego.GlobalControllerRouter["oc-scheduler/controllers:LokiController"], beego.ControllerComments{ Method: "GetLogs", - Router: `/`, + Router: `/:id`, AllowHTTPMethods: []string{"post"}, MethodParams: param.Make(), Filters: nil, diff --git a/routers/router.go b/routers/router.go index fdf2bda..83102d4 100644 --- a/routers/router.go +++ b/routers/router.go @@ -15,7 +15,7 @@ import ( ) func init() { - ns := beego.NewNamespace("/oc/", + ns := beego.NewNamespace("/oc", beego.NSInclude( &controllers.WorkflowSchedulerController{}, ), @@ -51,5 +51,5 @@ func init() { // WebSocket routes registered outside the Beego pipeline to avoid the // spurious WriteHeader that prevents the 101 Switching Protocols upgrade. beego.Handler("/oc/check/:id", http.HandlerFunc(controllers.CheckStreamHandler)) - beego.Handler("/oc/logs", http.HandlerFunc(controllers.LogsStreamHandler)) + beego.Handler("/oc/logs/:id", http.HandlerFunc(controllers.LogsStreamHandler)) } diff --git a/swagger/swagger.json b/swagger/swagger.json index cf05e50..2b72f8f 100644 --- a/swagger/swagger.json +++ b/swagger/swagger.json @@ -266,7 +266,7 @@ } } }, - "/loki/": { + "/loki/{id}": { "post": { "tags": [ "loki" diff --git a/swagger/swagger.yml b/swagger/swagger.yml index 54c7369..2b3847b 100644 --- a/swagger/swagger.yml +++ b/swagger/swagger.yml @@ -210,7 +210,7 @@ paths: responses: "200": description: '{workspace} models.workspace' - /loki/: + /loki/{id}: post: tags: - loki