mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-06-29 23:41:12 +08:00
### What problem does this PR solve? ``` RAGFlow(admin)> mq publish 'msg2'; SUCCESS RAGFlow(admin)> mq publish 'msg3'; SUCCESS RAGFlow(admin)> mq list; +---------+---------------+ | message | subject | +---------+---------------+ | msg1 | tasks.RAGFLOW | | msg2 | tasks.RAGFLOW | | msg3 | tasks.RAGFLOW | +---------+---------------+ RAGFlow(admin)> mq pull 2; +---------+---------------+ | message | subject | +---------+---------------+ | msg1 | tasks.RAGFLOW | | msg2 | tasks.RAGFLOW | +---------+---------------+ RAGFlow(admin)> mq pull noack; +---------+---------------+ | message | subject | +---------+---------------+ | abc | tasks.RAGFLOW | +---------+---------------+ RAGFlow(admin)> mq show +-------------------+----------------+--------+---------------+---------------+-------------------+---------------+ | ack_pending_count | consumer_count | memory | message_count | pending_count | redelivered_count | waiting_count | +-------------------+----------------+--------+---------------+---------------+-------------------+---------------+ | 2 | 1 | 0 | 2 | 0 | 1 | 0 | +-------------------+----------------+--------+---------------+---------------+-------------------+---------------+ RAGFlow(admin)> list ingestors; +--------------+-------------------------------------------+--------+ | host | name | status | +--------------+-------------------------------------------+--------+ | 192.168.1.38 | ingestor-8f0e4bd5650a4ac58b0151969fbf6935 | alive | +--------------+-------------------------------------------+--------+ RAGFlow(admin)> list ingestion tasks; +----------------------------------+----------------------------------+-----------+------+-------------+----------------------------------+ | document_id | id | status | step | user | user_id | +----------------------------------+----------------------------------+-----------+------+-------------+----------------------------------+ | ffe64fae423411f1a2d938a74640adcc | 90d3d0f6528941c1ac8eb0360effccc4 | COMPLETED | 5 | aaa@aaa.com | 2ba4881420fa11f19e9c38a74640adcc | +----------------------------------+----------------------------------+-----------+------+-------------+----------------------------------+ RAGFlow(admin)> remove ingestion tasks '90d3d0f6528941c1ac8eb0360effccc4'; +---------+----------------------------------+ | delete | task_id | +---------+----------------------------------+ | success | 90d3d0f6528941c1ac8eb0360effccc4 | +---------+----------------------------------+ RAGFlow(admin)> stop ingestion tasks 'e89e20d9a25848a1b79bd9345ddbfe1d'; +----------+----------------------------------+ | status | task_id | +----------+----------------------------------+ | STOPPING | e89e20d9a25848a1b79bd9345ddbfe1d | +----------+----------------------------------+ # Publish a message RAGFlow(admin)> mq publish 'cdd'; SUCCESS # List current tasks in the message queue RAGFlow(admin)> mq list +----------------------------------+---------------+ | message | subject | +----------------------------------+---------------+ | 7ce392a3c1624cd2be4b5276e8825059 | tasks.RAGFLOW | +----------------------------------+---------------+ # Consume a task from the message queue RAGFlow(admin)> mq pull +------+-----+----------------+ | ack | id | type | +------+-----+----------------+ | true | cdd | ingestion_test | +------+-----+----------------+ # User mode # List ingestion tasks, followed by dataset id RAGFlow(user)> list ingestion tasks from '0abe79f9423311f1ad8d38a74640adcc'; +---------------------------+---------------+----------------------------------+----------------------------------+----------------------------------+--------+-----------+---------------------------+---------------+----------------------------------+ | create_date | create_time | dataset_id | document_id | id | schema | status | update_date | update_time | user_id | +---------------------------+---------------+----------------------------------+----------------------------------+----------------------------------+--------+-----------+---------------------------+---------------+----------------------------------+ | 2026-05-30T20:21:06+08:00 | 1780143666289 | 0abe79f9423311f1ad8d38a74640adcc | ffe64fae423411f1a2d938a74640adcc | 8d758cd14a8b4ba8ab505003fb52017d | | COMPLETED | 2026-05-30T20:21:26+08:00 | 1780143686431 | 2ba4881420fa11f19e9c38a74640adcc | +---------------------------+---------------+----------------------------------+----------------------------------+----------------------------------+--------+-----------+---------------------------+---------------+----------------------------------+ RAGFlow(user)> list ingestion tasks; +---------------------------+---------------+----------------------------------+----------------------------------+----------------------------------+--------+-----------+---------------------------+---------------+----------------------------------+ | create_date | create_time | dataset_id | document_id | id | schema | status | update_date | update_time | user_id | +---------------------------+---------------+----------------------------------+----------------------------------+----------------------------------+--------+-----------+---------------------------+---------------+----------------------------------+ | 2026-06-02T19:02:31+08:00 | 1780398151417 | 0abe79f9423311f1ad8d38a74640adcc | ffe64fae423411f1a2d938a74640adcc | e89e20d9a25848a1b79bd9345ddbfe1d | | COMPLETED | 2026-06-02T19:02:52+08:00 | 1780398172208 | 2ba4881420fa11f19e9c38a74640adcc | +---------------------------+---------------+----------------------------------+----------------------------------+----------------------------------+--------+-----------+---------------------------+---------------+----------------------------------+ # Create an ingestion task # First argument is document id, second argument is dataset id RAGFlow(user)> start ingestion 'ffe64fae423411f1a2d938a74640adcc' from '0abe79f9423311f1ad8d38a74640adcc'; +----------------------------------+-------------------------------------------+ | document_id | result | +----------------------------------+-------------------------------------------+ | ffe64fae423411f1a2d938a74640adcc | task_id: 8d758cd14a8b4ba8ab505003fb52017d | +----------------------------------+-------------------------------------------+ # Pause an ingestion task, first argument is ingestion id RAGFlow(user)> stop ingestion '8d758cd14a8b4ba8ab505003fb52017d'; +---------------------------+---------------+----------------------------------+----------------------------------+----------------------------------+--------+-----------+---------------------------+---------------+----------------------------------+ | create_date | create_time | dataset_id | document_id | id | schema | status | update_date | update_time | user_id | +---------------------------+---------------+----------------------------------+----------------------------------+----------------------------------+--------+-----------+---------------------------+---------------+----------------------------------+ | 2026-05-30T20:21:06+08:00 | 1780143666289 | 0abe79f9423311f1ad8d38a74640adcc | ffe64fae423411f1a2d938a74640adcc | 8d758cd14a8b4ba8ab505003fb52017d | | COMPLETED | 2026-05-30T20:21:26+08:00 | 1780143686431 | 2ba4881420fa11f19e9c38a74640adcc | +---------------------------+---------------+----------------------------------+----------------------------------+----------------------------------+--------+-----------+---------------------------+---------------+----------------------------------+ # Delete an ingestion task RAGFlow(api/default)> remove ingestion tasks 'f366450a27d54677aec1c7090add30f0'; +---------+----------------------------------+ | remove | task_id | +---------+----------------------------------+ | success | f366450a27d54677aec1c7090add30f0 | +---------+----------------------------------+ ``` ### Type of change - [x] New Feature (non-breaking change which adds functionality) --------- Signed-off-by: Jin Hai <haijin.chn@gmail.com>
1615 lines
48 KiB
Go
1615 lines
48 KiB
Go
//
|
|
// Copyright 2026 The InfiniFlow Authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
package cli
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/url"
|
|
)
|
|
|
|
// PingServer pings the server to check if it's alive
|
|
// Returns benchmark result map if iterations > 1, otherwise prints status
|
|
func (c *CLI) PingAdmin(cmd *Command) (ResponseIf, error) {
|
|
// Get iterations from command params (for benchmark)
|
|
iterations := 1
|
|
if val, ok := cmd.Params["iterations"].(int); ok && val > 1 {
|
|
iterations = val
|
|
}
|
|
|
|
if iterations > 1 {
|
|
// Benchmark mode: multiple iterations
|
|
return c.AdminServerClient.RequestWithIterations("GET", "/admin/ping", "web", nil, nil, iterations)
|
|
}
|
|
|
|
// Single mode
|
|
resp, err := c.AdminServerClient.Request("GET", "/admin/ping", "web", nil, nil)
|
|
if err != nil {
|
|
fmt.Printf("Error: %v\n", err)
|
|
fmt.Println("Server is down")
|
|
return nil, err
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to ping: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result SimpleResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("list users failed: invalid JSON (%w)", err)
|
|
}
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// Show admin version to show RAGFlow admin version
|
|
// Returns benchmark result map if iterations > 1, otherwise prints status
|
|
func (c *CLI) ShowAdminVersion(cmd *Command) (ResponseIf, error) {
|
|
// Get iterations from command params (for benchmark)
|
|
iterations := 1
|
|
if val, ok := cmd.Params["iterations"].(int); ok && val > 1 {
|
|
iterations = val
|
|
}
|
|
|
|
if iterations > 1 {
|
|
// Benchmark mode: multiple iterations
|
|
return c.AdminServerClient.RequestWithIterations("GET", "/admin/version", "web", nil, nil, iterations)
|
|
}
|
|
|
|
// Single mode
|
|
resp, err := c.AdminServerClient.Request("GET", "/admin/version", "web", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to show admin version: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to show admin version: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonDataResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("show admin version failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// ListRoles to list roles (admin mode only)
|
|
func (c *CLI) ListRoles(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
// Check for benchmark iterations
|
|
iterations := 1
|
|
if val, ok := cmd.Params["iterations"].(int); ok && val > 1 {
|
|
iterations = val
|
|
}
|
|
|
|
if iterations > 1 {
|
|
// Benchmark mode - return raw result for benchmark stats
|
|
return c.AdminServerClient.RequestWithIterations("GET", "/admin/roles", "admin", nil, nil, iterations)
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("GET", "/admin/roles", "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list roles: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to list roles: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("list roles failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
for _, user := range result.Data {
|
|
delete(user, "extra")
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// ShowRole to show role (admin mode only)
|
|
func (c *CLI) ShowRole(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
roleName := cmd.Params["role_name"].(string)
|
|
|
|
// Check for benchmark iterations
|
|
iterations := 1
|
|
if val, ok := cmd.Params["iterations"].(int); ok && val > 1 {
|
|
iterations = val
|
|
}
|
|
|
|
endPoint := fmt.Sprintf("/admin/roles/%s/", roleName)
|
|
|
|
if iterations > 1 {
|
|
// Benchmark mode - return raw result for benchmark stats
|
|
return c.AdminServerClient.RequestWithIterations("GET", endPoint, "admin", nil, nil, iterations)
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("GET", endPoint, "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to show role: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to show role: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonDataResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("show role failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// CreateRole creates a new role (admin mode only)
|
|
func (c *CLI) CreateRole(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
roleName, ok := cmd.Params["role_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("user_name not provided")
|
|
}
|
|
|
|
description, ok := cmd.Params["description"].(string)
|
|
payload := map[string]interface{}{
|
|
"role_name": roleName,
|
|
}
|
|
if ok {
|
|
payload["description"] = description
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("POST", "/admin/roles", "admin", nil, payload)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create role: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to create role: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result SimpleResponse
|
|
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("create role failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// DropRole deletes the role (admin mode only)
|
|
func (c *CLI) DropRole(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
roleName, ok := cmd.Params["role_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("role_name not provided")
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("DELETE", fmt.Sprintf("/admin/roles/%s", roleName), "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to drop role: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to drop role: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result SimpleResponse
|
|
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("drop role failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// AlterRole alters the role rights (admin mode only)
|
|
func (c *CLI) AlterRole(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
roleName, ok := cmd.Params["role_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("user_name not provided")
|
|
}
|
|
|
|
description, ok := cmd.Params["description"].(string)
|
|
payload := map[string]interface{}{
|
|
"role_name": roleName,
|
|
}
|
|
if ok {
|
|
payload["description"] = description
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("PUT", fmt.Sprintf("/admin/roles/%s", roleName), "admin", nil, payload)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to alter role: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to alter role: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result SimpleResponse
|
|
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("alter role failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// GrantAdmin grants admin privileges to a user (admin mode only)
|
|
func (c *CLI) GrantAdmin(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
userName, ok := cmd.Params["user_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("user_name not provided")
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("PUT", fmt.Sprintf("/admin/users/%s/admin", userName), "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to grant admin: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to grant admin: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result SimpleResponse
|
|
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("grant admin failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// RevokeAdmin revokes admin privileges from a user (admin mode only)
|
|
func (c *CLI) RevokeAdmin(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
userName, ok := cmd.Params["user_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("user_name not provided")
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("DELETE", fmt.Sprintf("/admin/users/%s/admin", userName), "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to revoke admin: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to revoke admin: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result SimpleResponse
|
|
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("revoke admin failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// CreateUser creates a new user (admin mode only)
|
|
func (c *CLI) CreateUser(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
userName, ok := cmd.Params["user_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("user_name not provided")
|
|
}
|
|
|
|
password, ok := cmd.Params["password"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("password not provided")
|
|
}
|
|
|
|
// Encrypt password using RSA
|
|
encryptedPassword, err := EncryptPassword(password)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to encrypt password: %w", err)
|
|
}
|
|
|
|
payload := map[string]interface{}{
|
|
"username": userName,
|
|
"password": encryptedPassword,
|
|
"role": "user",
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("POST", "/admin/users", "admin", nil, payload)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create user: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to create user: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result SimpleResponse
|
|
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("create user failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// ActivateUser activates or deactivates a user (admin mode only)
|
|
func (c *CLI) ActivateUser(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
userName, ok := cmd.Params["user_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("user_name not provided")
|
|
}
|
|
|
|
activateStatus, ok := cmd.Params["activate_status"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("activate_status not provided")
|
|
}
|
|
|
|
// Validate activate_status
|
|
if activateStatus != "on" && activateStatus != "off" {
|
|
return nil, fmt.Errorf("activate_status must be 'on' or 'off'")
|
|
}
|
|
|
|
payload := map[string]interface{}{
|
|
"activate_status": activateStatus,
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("PUT", fmt.Sprintf("/admin/users/%s/activate", userName), "admin", nil, payload)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to update user status: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to update user status: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result SimpleResponse
|
|
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("update user status failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// AlterUserPassword changes a user's password (admin mode only)
|
|
func (c *CLI) AlterUserPassword(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
userName, ok := cmd.Params["user_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("user_name not provided")
|
|
}
|
|
|
|
password, ok := cmd.Params["password"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("password not provided")
|
|
}
|
|
|
|
// Encrypt password using RSA
|
|
encryptedPassword, err := EncryptPassword(password)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to encrypt password: %w", err)
|
|
}
|
|
|
|
payload := map[string]interface{}{
|
|
"new_password": encryptedPassword,
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("PUT", fmt.Sprintf("/admin/users/%s/password", userName), "admin", nil, payload)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to change user password: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to change user password: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result SimpleResponse
|
|
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("change user password failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
type listServicesResponse struct {
|
|
Code int `json:"code"`
|
|
Data []map[string]interface{} `json:"data"`
|
|
Message string `json:"message"`
|
|
}
|
|
|
|
// ListServices lists all services (admin mode only)
|
|
func (c *CLI) ListServices(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
// Check for benchmark iterations
|
|
iterations := 1
|
|
if val, ok := cmd.Params["iterations"].(int); ok && val > 1 {
|
|
iterations = val
|
|
}
|
|
|
|
if iterations > 1 {
|
|
// Benchmark mode - return raw result for benchmark stats
|
|
return c.AdminServerClient.RequestWithIterations("GET", "/admin/services", "admin", nil, nil, iterations)
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("GET", "/admin/services", "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list services: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to list services: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("list users failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
for _, user := range result.Data {
|
|
delete(user, "extra")
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// Show service show service (admin mode only)
|
|
func (c *CLI) ShowService(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
serviceIndex := cmd.Params["number"].(int)
|
|
|
|
// Check for benchmark iterations
|
|
iterations := 1
|
|
if val, ok := cmd.Params["iterations"].(int); ok && val > 1 {
|
|
iterations = val
|
|
}
|
|
|
|
endPoint := fmt.Sprintf("/admin/services/%d", serviceIndex)
|
|
|
|
if iterations > 1 {
|
|
// Benchmark mode - return raw result for benchmark stats
|
|
return c.AdminServerClient.RequestWithIterations("GET", endPoint, "admin", nil, nil, iterations)
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("GET", endPoint, "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to show service: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to show service: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonDataResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("show service failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
func normalizeVariableRows(rows []map[string]interface{}) {
|
|
for _, row := range rows {
|
|
if _, ok := row["setting_type"]; ok {
|
|
delete(row, "source")
|
|
continue
|
|
}
|
|
if _, ok := row["source"]; ok {
|
|
row["setting_type"] = "config"
|
|
delete(row, "source")
|
|
}
|
|
}
|
|
}
|
|
|
|
// ListVariables lists all system variables (admin mode only).
|
|
func (c *CLI) ListVariables(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
iterations := 1
|
|
if val, ok := cmd.Params["iterations"].(int); ok && val > 1 {
|
|
iterations = val
|
|
}
|
|
|
|
if iterations > 1 {
|
|
return c.AdminServerClient.RequestWithIterations("GET", "/admin/variables", "admin", nil, nil, iterations)
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("GET", "/admin/variables", "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list variables: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to list variables: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("list variables failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
normalizeVariableRows(result.Data)
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// ShowVariable shows system variables by exact name or name prefix (admin mode only).
|
|
func (c *CLI) ShowVariable(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
varName, ok := cmd.Params["var_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("var_name not provided")
|
|
}
|
|
|
|
iterations := 1
|
|
if val, ok := cmd.Params["iterations"].(int); ok && val > 1 {
|
|
iterations = val
|
|
}
|
|
|
|
payload := map[string]interface{}{"var_name": varName}
|
|
if iterations > 1 {
|
|
return c.AdminServerClient.RequestWithIterations("GET", "/admin/variables", "admin", nil, payload, iterations)
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("GET", "/admin/variables", "admin", nil, payload)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to show variable: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to show variable: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("show variable failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
normalizeVariableRows(result.Data)
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// SetVariable updates a system variable (admin mode only).
|
|
func (c *CLI) SetVariable(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
varName, ok := cmd.Params["var_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("var_name not provided")
|
|
}
|
|
varValue, ok := cmd.Params["var_value"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("var_value not provided")
|
|
}
|
|
|
|
payload := map[string]interface{}{
|
|
"var_name": varName,
|
|
"var_value": varValue,
|
|
}
|
|
resp, err := c.AdminServerClient.Request("PUT", "/admin/variables", "admin", nil, payload)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to set variable: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to set variable: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result MessageResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("set variable failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// ListUsers lists all users (admin mode only)
|
|
// Returns (result_map, error) - result_map is non-nil for benchmark mode
|
|
func (c *CLI) ListUsers(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
// Check for benchmark iterations
|
|
iterations := 1
|
|
if val, ok := cmd.Params["iterations"].(int); ok && val > 1 {
|
|
iterations = val
|
|
}
|
|
|
|
if iterations > 1 {
|
|
// Benchmark mode - return raw result for benchmark stats
|
|
return c.AdminServerClient.RequestWithIterations("GET", "/admin/users", "admin", nil, nil, iterations)
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("GET", "/admin/users", "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list users: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to list users: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("list users failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
for _, user := range result.Data {
|
|
delete(user, "create_date")
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// DropUser deletes a user (admin mode only)
|
|
func (c *CLI) DropUser(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
userName, ok := cmd.Params["user_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("user_name not provided")
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("DELETE", fmt.Sprintf("/admin/users/%s", userName), "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to drop user: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to drop user: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result SimpleResponse
|
|
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("drop user failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// Show user show user (admin mode only)
|
|
func (c *CLI) ShowUser(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
userName, ok := cmd.Params["user_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("user_name not provided")
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("GET", fmt.Sprintf("/admin/users/%s", userName), "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to show user: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to show user: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonDataResponse
|
|
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("show user failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// ListUserDatasets lists datasets for a specific user (admin mode)
|
|
// Returns (result_map, error) - result_map is non-nil for benchmark mode
|
|
func (c *CLI) ListUserDatasets(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
userName, ok := cmd.Params["user_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("user_name not provided")
|
|
}
|
|
|
|
// Check for benchmark iterations
|
|
iterations := 1
|
|
if val, ok := cmd.Params["iterations"].(int); ok && val > 1 {
|
|
iterations = val
|
|
}
|
|
|
|
if iterations > 1 {
|
|
// Benchmark mode - return raw result for benchmark stats
|
|
return c.AdminServerClient.RequestWithIterations("GET", fmt.Sprintf("/admin/users/%s/datasets", userName), "admin", nil, nil, iterations)
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("GET", fmt.Sprintf("/admin/users/%s/datasets", userName), "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list datasets: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to list datasets: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
resJSON, err := resp.JSON()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("invalid JSON response: %w", err)
|
|
}
|
|
|
|
data, ok := resJSON["data"].([]interface{})
|
|
if !ok {
|
|
return nil, fmt.Errorf("invalid response format")
|
|
}
|
|
|
|
// Convert to slice of maps and remove avatar
|
|
tableData := make([]map[string]interface{}, 0, len(data))
|
|
for _, item := range data {
|
|
if itemMap, ok := item.(map[string]interface{}); ok {
|
|
delete(itemMap, "avatar")
|
|
tableData = append(tableData, itemMap)
|
|
}
|
|
}
|
|
|
|
PrintTableSimple(tableData)
|
|
return nil, nil
|
|
}
|
|
|
|
// ListAgents lists agents for a specific user (admin mode)
|
|
// Returns (result_map, error) - result_map is non-nil for benchmark mode
|
|
func (c *CLI) ListAgents(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
userName, ok := cmd.Params["user_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("user_name not provided")
|
|
}
|
|
|
|
// Check for benchmark iterations
|
|
iterations := 1
|
|
if val, ok := cmd.Params["iterations"].(int); ok && val > 1 {
|
|
iterations = val
|
|
}
|
|
|
|
if iterations > 1 {
|
|
// Benchmark mode - return raw result for benchmark stats
|
|
return c.AdminServerClient.RequestWithIterations("GET", fmt.Sprintf("/admin/users/%s/agents", userName), "admin", nil, nil, iterations)
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("GET", fmt.Sprintf("/admin/users/%s/agents", userName), "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list agents: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to list agents: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
resJSON, err := resp.JSON()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("invalid JSON response: %w", err)
|
|
}
|
|
|
|
data, ok := resJSON["data"].([]interface{})
|
|
if !ok {
|
|
return nil, fmt.Errorf("invalid response format")
|
|
}
|
|
|
|
// Convert to slice of maps and remove avatar
|
|
tableData := make([]map[string]interface{}, 0, len(data))
|
|
for _, item := range data {
|
|
if itemMap, ok := item.(map[string]interface{}); ok {
|
|
delete(itemMap, "avatar")
|
|
tableData = append(tableData, itemMap)
|
|
}
|
|
}
|
|
|
|
PrintTableSimple(tableData)
|
|
return nil, nil
|
|
}
|
|
|
|
// GrantPermission grants permission to a role (admin mode only)
|
|
func (c *CLI) GrantPermission(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
userName, ok := cmd.Params["user_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("user_name not provided")
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("GET", fmt.Sprintf("/admin/users/%s/keys", userName), "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list tokens: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to list tokens: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("list tokens failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
// Remove extra field from data
|
|
for _, item := range result.Data {
|
|
delete(item, "extra")
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// RevokePermission revokes permission from a role (admin mode only)
|
|
func (c *CLI) RevokePermission(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
roleName, ok := cmd.Params["role_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("role_name not provided")
|
|
}
|
|
|
|
resource, ok := cmd.Params["resource"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("resource not provided")
|
|
}
|
|
|
|
actionsRaw, ok := cmd.Params["actions"].([]interface{})
|
|
if !ok {
|
|
return nil, fmt.Errorf("actions not provided")
|
|
}
|
|
|
|
actions := make([]string, 0, len(actionsRaw))
|
|
for _, action := range actionsRaw {
|
|
if actionStr, ok := action.(string); ok {
|
|
actions = append(actions, actionStr)
|
|
}
|
|
}
|
|
|
|
payload := map[string]interface{}{
|
|
"resource": resource,
|
|
"actions": actions,
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("DELETE", fmt.Sprintf("/admin/roles/%s/permission", roleName), "admin", nil, payload)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to revoke permission: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to revoke permission: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("revoke permission failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
// Remove extra field from data
|
|
for _, item := range result.Data {
|
|
delete(item, "extra")
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// AlterUserRole alters user's role (admin mode only)
|
|
func (c *CLI) AlterUserRole(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
userName, ok := cmd.Params["user_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("user_name not provided")
|
|
}
|
|
|
|
roleName, ok := cmd.Params["role_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("role_name not provided")
|
|
}
|
|
|
|
payload := map[string]interface{}{
|
|
"role_name": roleName,
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("PUT", fmt.Sprintf("/admin/users/%s/role", userName), "admin", nil, payload)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to alter user role: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to alter user role: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("alter user role failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
// Remove extra field from data
|
|
for _, item := range result.Data {
|
|
delete(item, "extra")
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// ShowUserPermission shows user's permissions (admin mode only)
|
|
func (c *CLI) ShowUserPermission(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
userName, ok := cmd.Params["user_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("user_name not provided")
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("GET", fmt.Sprintf("/admin/users/%s/permission", userName), "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to show user permission: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to show user permission: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("show user permission failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
// Remove extra field from data
|
|
for _, item := range result.Data {
|
|
delete(item, "extra")
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// GenerateAdminToken generates an API token for a user (admin mode only)
|
|
func (c *CLI) GenerateAdminToken(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
userName, ok := cmd.Params["user_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("user_name not provided")
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("POST", fmt.Sprintf("/admin/users/%s/keys", userName), "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to generate token: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to generate token: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonDataResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("generate token failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
delete(result.Data, "update_date")
|
|
delete(result.Data, "update_time")
|
|
delete(result.Data, "create_time")
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// ListAdminTokens lists all API tokens for a user (admin mode only)
|
|
func (c *CLI) ListAdminTokens(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
userName, ok := cmd.Params["user_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("user_name not provided")
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("GET", fmt.Sprintf("/admin/users/%s/keys", userName), "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list tokens: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to list tokens: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("list tokens failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
// Remove extra field from data
|
|
for _, item := range result.Data {
|
|
delete(item, "dialog_id")
|
|
delete(item, "source")
|
|
delete(item, "update_date")
|
|
delete(item, "update_time")
|
|
delete(item, "create_time")
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
// DropToken drops an API token for a user (admin mode only)
|
|
func (c *CLI) DropAdminToken(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
userName, ok := cmd.Params["user_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("user_name not provided")
|
|
}
|
|
|
|
token, ok := cmd.Params["token"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("token not provided")
|
|
}
|
|
|
|
// URL encode the token to handle special characters
|
|
encodedToken := url.QueryEscape(token)
|
|
|
|
resp, err := c.AdminServerClient.Request("DELETE", fmt.Sprintf("/admin/users/%s/keys/%s", userName, encodedToken), "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to drop token: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to drop token: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result SimpleResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("drop token failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
func (c *CLI) ListAdminTasks(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("GET", "/admin/tasks", "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to drop token: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to drop token: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("drop token failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
func (c *CLI) ListAdminIngestors(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
resp, err := c.AdminServerClient.Request("GET", "/admin/ingestors", "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list ingestors: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to list ingestors: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("list ingestors failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
func (c *CLI) ListAdminIngestionTasks(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("GET", "/admin/ingestion/tasks", "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list admin tasks: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to list admin tasks: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("list admin tasks failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
func (c *CLI) AdminStopIngestionCommand(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
tasks, ok := cmd.Params["tasks"].([]string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("uri not provided")
|
|
}
|
|
payload := map[string]interface{}{
|
|
"tasks": tasks,
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("PUT", "/admin/ingestion/tasks", "admin", nil, payload)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to ingest file: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to ingest file: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("ingest file failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
func (c *CLI) AdminRemoveIngestionCommand(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
tasks, ok := cmd.Params["tasks"].([]string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("uri not provided")
|
|
}
|
|
payload := map[string]interface{}{
|
|
"tasks": tasks,
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("DELETE", "/admin/ingestion/tasks", "admin", nil, payload)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to ingest file: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to ingest file: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("ingest file failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
func (c *CLI) AdminShutdownIngestor(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
ingestorName, ok := cmd.Params["ingestor_name"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("ingestor_name not provided")
|
|
}
|
|
payload := map[string]interface{}{
|
|
"ingestor_name": ingestorName,
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("DELETE", "/admin/ingestors", "admin", nil, payload)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to shutdown ingestor: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to shutdown ingestor: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonDataResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("shutdown ingestor failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
func (c *CLI) UserListMessageQueueCommand(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
pending, ok := cmd.Params["pending"].(bool)
|
|
if !ok {
|
|
return nil, fmt.Errorf("pending not provided")
|
|
}
|
|
payload := map[string]interface{}{
|
|
"pending": pending,
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("GET", "/admin/queue/messages", "admin", nil, payload)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list tasks in message queue: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to list tasks in message queue: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("list tasks in message queue failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
func (c *CLI) UserPublishMessageCommand(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
message, ok := cmd.Params["message"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("message not provided")
|
|
}
|
|
payload := map[string]interface{}{
|
|
"message": message,
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("POST", "/admin/queue/messages", "admin", nil, payload)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to publish message: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to publish message: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result SimpleResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("publish message failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
func (c *CLI) UserPullMessageCommand(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
messageCount, ok := cmd.Params["message_count"].(int)
|
|
if !ok {
|
|
return nil, fmt.Errorf("message_count not provided")
|
|
}
|
|
ackPolicy, ok := cmd.Params["ack_policy"].(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("ack_policy not provided")
|
|
}
|
|
|
|
payload := map[string]interface{}{
|
|
"message_count": messageCount,
|
|
"ack_policy": ackPolicy,
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("PUT", "/admin/queue/messages", "admin", nil, payload)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to pull message: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to pull message: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("pull message failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
func (c *CLI) UserShowMessageQueueCommand(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("GET", "/admin/queue", "admin", nil, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to show message queue: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to show message queue: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result CommonDataResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("show message queue failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|
|
|
|
func (c *CLI) AdminRemoveServiceCommand(cmd *Command) (ResponseIf, error) {
|
|
if c.Config.CLIMode != AdminMode || c.AdminServerClient.LoginToken == nil {
|
|
return nil, fmt.Errorf("this command is only allowed in ADMIN mode or already login")
|
|
}
|
|
serviceNumber, ok := cmd.Params["service_number"].(int)
|
|
if !ok {
|
|
return nil, fmt.Errorf("service_number not provided")
|
|
}
|
|
|
|
payload := map[string]interface{}{
|
|
"service_number": serviceNumber,
|
|
}
|
|
|
|
resp, err := c.AdminServerClient.Request("DELETE", "/admin/services", "admin", nil, payload)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to remove unavailable service: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("failed to remove unavailable service: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
|
}
|
|
|
|
var result SimpleResponse
|
|
if err = json.Unmarshal(resp.Body, &result); err != nil {
|
|
return nil, fmt.Errorf("remove unavailable service failed: invalid JSON (%w)", err)
|
|
}
|
|
|
|
if result.Code != 0 {
|
|
return nil, fmt.Errorf("%s", result.Message)
|
|
}
|
|
|
|
result.Duration = resp.Duration
|
|
return &result, nil
|
|
}
|