sdk

package
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 1, 2026 License: MIT Imports: 16 Imported by: 0

README

Controller API SDK

这是一个用于调用 Controller API 的 Go SDK,提供了同步和异步两种方式来执行远程命令。

功能特性

  • 异步执行:提交任务后立即返回,不等待结果
  • 同步执行:提交任务并自动轮询,直到任务完成
  • 批量查询:支持一次查询多个任务的结果
  • 状态回调:同步执行时支持状态更新回调
  • 灵活配置:可自定义超时、轮询间隔等参数
  • 类型安全:完整的类型定义,编译时检查

快速开始

1. 创建客户端
import (
    "github.com/netxops/unicontroller/controller/pkg/sdk"
    "time"
)

// 使用默认配置
config := sdk.DefaultAsyncExecuteClientConfig("http://localhost:8081")
client := sdk.NewAsyncExecuteClient(config)

// 或自定义配置
config := &sdk.AsyncExecuteClientConfig{
    BaseURL:         "http://localhost:8081",
    DefaultTimeout:  30 * time.Second,
    PollInterval:    1 * time.Second,
    MaxPollDuration: 5 * time.Minute,
    MaxPollAttempts: 300,
}
client := sdk.NewAsyncExecuteClient(config)
2. 异步执行(推荐用于长时间运行的任务)
import (
    "context"
    "github.com/netxops/unicontroller/controller/pkg/sdk"
    "github.com/netxops/unicontroller/controller/pkg/structs"
)

req := &sdk.AsyncExecuteRequest{
    ID: "task-123",
    RemoteInfo: structs.L2DeviceRemoteInfo{
        Ip:       "192.168.1.1",
        Username: "admin",
        Password: "password",
        Platform: "linux",
    },
    Commands: []string{
        "ls -la",
        "pwd",
    },
    Timeout: 60,
}

// 提交任务
ctx := context.Background()
resp, err := client.AsyncExecute(ctx, req)
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Task ID: %s\n", resp.TaskID)

// 稍后查询结果
result, err := client.GetSingleResult(ctx, resp.TaskID, true)
if err != nil {
    log.Fatal(err)
}

if result.IsSuccess() {
    fmt.Printf("Output: %s\n", result.GetCombinedOutput())
}
3. 同步执行(推荐用于快速任务)
req := &sdk.AsyncExecuteRequest{
    ID: "task-123",
    RemoteInfo: structs.L2DeviceRemoteInfo{
        Ip:       "192.168.1.1",
        Username: "admin",
        Password: "password",
        Platform: "linux",
    },
    Commands: []string{"ls -la"},
    Timeout: 60,
}

// 同步执行(带状态回调)
opts := &sdk.SyncExecuteOptions{
    PollInterval:    500 * time.Millisecond,
    MaxPollDuration: 2 * time.Minute,
    OnStatusUpdate: func(status sdk.TaskStatus, result *sdk.AsyncTaskResult) {
        fmt.Printf("Status: %s - %s\n", status, result.Message)
    },
}

ctx := context.Background()
result, err := client.SyncExecute(ctx, req, opts)
if err != nil {
    log.Fatal(err)
}

if result.IsSuccess() {
    fmt.Printf("Success! Output:\n%s\n", result.GetCombinedOutput())
} else {
    fmt.Printf("Failed: %s\n", result.GetCombinedError())
}
4. 批量查询
taskIDs := []string{"task-1", "task-2", "task-3"}
resp, err := client.GetResult(ctx, taskIDs, true)
if err != nil {
    log.Fatal(err)
}

for taskID, result := range resp.Results {
    fmt.Printf("Task %s: %s\n", taskID, result.Status)
}

for taskID, errMsg := range resp.Errors {
    fmt.Printf("Task %s error: %s\n", taskID, errMsg)
}

API 参考

AsyncExecuteClientConfig

客户端配置结构:

type AsyncExecuteClientConfig struct {
    BaseURL         string        // API 基础 URL
    HTTPClient      *http.Client  // 自定义 HTTP 客户端(可选)
    DefaultTimeout  time.Duration // 默认请求超时时间
    PollInterval    time.Duration // 轮询间隔(同步调用时使用)
    MaxPollDuration time.Duration // 最大轮询时间
    MaxPollAttempts int           // 最大轮询次数
}
AsyncExecuteClient

异步执行客户端:

type AsyncExecuteClient struct {
    // 内部字段
}

// 创建客户端
func NewAsyncExecuteClient(config *AsyncExecuteClientConfig) *AsyncExecuteClient

// 获取默认配置
func DefaultAsyncExecuteClientConfig(baseURL string) *AsyncExecuteClientConfig
AsyncExecuteRequest

异步执行请求:

type AsyncExecuteRequest struct {
    ID         string                  // 任务ID(由客户端提供)
    RemoteInfo structs.L2DeviceRemoteInfo // 设备连接信息
    Commands   []string                // 命令列表(可选)
    Script     string                  // 内联脚本(可选)
    ScriptPath string                  // 文件脚本路径(可选)
    Background bool                    // 是否后台执行
    Timeout    int                     // 超时时间(秒),默认60秒
}

注意CommandsScriptScriptPath 至少需要提供一个。

AsyncTaskResult

任务结果结构:

type AsyncTaskResult struct {
    Status   TaskStatus      // 任务状态
    TaskInfo TaskInfo        // 任务信息
    StartTime time.Time      // 开始时间
    EndTime   *time.Time     // 结束时间
    Duration  *int64         // 执行时长(毫秒)
    Result   *ExecutionResult // 执行结果(成功时)
    Error    *ErrorDetail     // 错误详情(失败时)
    Message  string           // 状态消息
}
任务状态
  • TaskStatusPending - 待执行
  • TaskStatusRunning - 执行中
  • TaskStatusCompleted - 已完成
  • TaskStatusFailed - 执行失败
  • TaskStatusCancelled - 已取消

使用场景

场景1:快速命令执行(同步)
result, err := client.SyncExecute(ctx, req, nil)
// 直接获取结果,无需手动轮询
场景2:长时间任务(异步)
// 提交任务
resp, err := client.AsyncExecute(ctx, req)

// 在后台定期查询
go func() {
    for {
        result, _ := client.GetSingleResult(ctx, resp.TaskID, true)
        if result.Status.IsCompleted() {
            break
        }
        time.Sleep(5 * time.Second)
    }
}()
场景3:批量任务监控
// 提交多个任务
taskIDs := []string{}
for i := 0; i < 10; i++ {
    req.ID = fmt.Sprintf("task-%d", i)
    resp, _ := client.AsyncExecute(ctx, req)
    taskIDs = append(taskIDs, resp.TaskID)
}

// 批量查询结果
results, _ := client.GetResult(ctx, taskIDs, true)

错误处理

SDK 会返回详细的错误信息:

result, err := client.SyncExecute(ctx, req, nil)
if err != nil {
    // 检查错误类型
    if strings.Contains(err.Error(), "timeout") {
        // 处理超时
    } else if strings.Contains(err.Error(), "network") {
        // 处理网络错误
    }
    return err
}

// 检查任务是否成功
if !result.IsSuccess() {
    // 获取错误详情
    if result.Error != nil {
        fmt.Printf("Error type: %s, Message: %s\n", 
            result.Error.Type, result.Error.Message)
    }
}

最佳实践

  1. 任务ID生成:使用唯一ID,建议使用 UUID 或时间戳
  2. 超时设置:根据任务复杂度合理设置超时时间
  3. 错误重试:对于网络错误,可以实现重试逻辑
  4. 资源清理:长时间运行的程序应定期清理已完成的任务结果
  5. 并发控制:避免同时提交过多任务,注意控制并发数

其他 SDK 功能

除了异步执行 API,SDK 还提供了其他功能:

旧的 Client(用于其他 API)
// 创建客户端(需要用户名和密码)
client := sdk.NewClient("http://localhost:8081", "username", "password")

// 获取控制器状态
status, err := client.GetControllerStatus()

// 创建部署
deployment, err := client.CreateDeployment(req)

// 列出代理
agents, err := client.ListAgents(filter, page, pageSize)
ConfigDriver(用于 etcd 配置管理)
// 创建 ConfigDriver
cd := sdk.NewConfigDriver("agent_config", "DefaultArea", []string{"127.0.0.1:2379"})

// 读取配置
config, err := cd.GetConfig(ctx, "ExampleCode", "uniops-telegraf")

// 写入配置
err := cd.PutConfig(ctx, config, "ExampleCode", "uniops-telegraf")

// 启用/禁用配置
err := cd.Enable(ctx, true, "ExampleCode", "uniops-telegraf")

StackUp 执行接口

StackUp 是一个用于批量执行远程命令的工具,支持通过 YAML 配置文件定义多个命令、脚本和文件上传。

基本使用
import (
    "context"
    "github.com/netxops/unicontroller/controller/pkg/sdk"
    "github.com/netxops/unicontroller/controller/pkg/structs"
)

// 创建客户端
config := sdk.DefaultAsyncExecuteClientConfig("http://localhost:8081")
client := sdk.NewAsyncExecuteClient(config)

// 准备 YAML 配置
yamlConfig := `
commands:
  - name: test1
    run: echo "Hello World"
    timeout: 10
  - name: test2
    run: pwd
    timeout: 10
  - name: test3
    script: |
      #!/bin/bash
      echo "Script test"
      date
env:
  TEST_VAR: "test_value"
`

// 执行 StackUp
req := &sdk.StackUpExecuteRequest{
    RemoteInfo: structs.L2DeviceRemoteInfo{
        Ip:       "192.168.1.1",
        Username: "admin",
        Password: "password",
        Platform: "linux",
    },
    Config:     yamlConfig,
    ConfigType: "yaml",
}

ctx := context.Background()
resp, err := client.StackUpExecute(ctx, req)
if err != nil {
    log.Fatal(err)
}

// 处理结果
if resp.Success {
    fmt.Printf("Success: %s\n", resp.Message)
    for _, result := range resp.Results {
        fmt.Printf("Command %d (%s): Status=%s\n", 
            result.Index, result.Key, result.Status)
        if result.Status == "false" {
            fmt.Printf("  Output: %s\n", result.Output)
        } else {
            fmt.Printf("  Error: %s\n", result.Msg)
        }
    }
}
配置格式

StackUp 配置文件支持以下功能:

  1. 执行命令 (run):
commands:
  - name: my_command
    run: ls -la /tmp
    timeout: 10
  1. 执行脚本 (script):
commands:
  - name: my_script
    script: |
      #!/bin/bash
      echo "Hello"
      date
    timeout: 10
  1. 上传文件 (upload):
commands:
  - name: upload_file
    upload:
      - src: /local/path/file.txt
        dst: /remote/path/file.txt
        timeout: 30
  1. 环境变量 (env):
env:
  VAR1: "value1"
  VAR2: "value2"
StackUpExecuteRequest
type StackUpExecuteRequest struct {
    RemoteInfo    structs.L2DeviceRemoteInfo // 设备连接信息
    Config        string                     // YAML 配置(或 base64 编码)
    ConfigType    string                     // "yaml" 或 "base64",默认 "yaml"
    LocalDataPath string                     // 本地数据路径(可选)
}
StackUpExecuteResponse
type StackUpExecuteResponse struct {
    Success bool                   // 是否成功
    Message string                 // 消息
    Results []StackUpCommandResult // 命令执行结果列表
    Error   string                 // 错误信息(如果有)
}

type StackUpCommandResult struct {
    Index   int    // 命令索引(从1开始)
    Command string // 执行的命令
    Key     string // 命令的 key/name
    Output  string // 命令输出
    Msg     string // 消息
    Status  string // 状态:"false"=成功, "true"=有错误
}

示例代码

完整示例请参考:

  • cmd/controller/sdk_example.go - 异步执行示例
  • pkg/sdk/stackup_test.go - StackUp 接口测试示例

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ExampleStackUpExecute_Base64

func ExampleStackUpExecute_Base64()

ExampleStackUpExecute_Base64 使用 Base64 编码配置执行 StackUp

func ExampleStackUpExecute_MultipleCommands

func ExampleStackUpExecute_MultipleCommands()

ExampleStackUpExecute_MultipleCommands 执行多个命令

func ExampleStackUpExecute_WithLocalDataPath

func ExampleStackUpExecute_WithLocalDataPath()

ExampleStackUpExecute_WithLocalDataPath 使用本地数据路径执行 StackUp

func ExampleStackUpExecute_WithScript

func ExampleStackUpExecute_WithScript()

ExampleStackUpExecute_WithScript 使用脚本执行 StackUp

func ExampleStackUpExecute_YAML

func ExampleStackUpExecute_YAML()

ExampleStackUpExecute_YAML 使用 YAML 配置执行 StackUp

Types

type AsyncExecuteClient

type AsyncExecuteClient struct {
	// contains filtered or unexported fields
}

AsyncExecuteClient SDK 客户端

func NewAsyncExecuteClient

func NewAsyncExecuteClient(config *AsyncExecuteClientConfig) *AsyncExecuteClient

NewAsyncExecuteClient 创建新的 SDK 客户端

func (*AsyncExecuteClient) AsyncExecute

AsyncExecute 异步执行命令(提交任务,不等待结果)

func (*AsyncExecuteClient) GetResult

func (c *AsyncExecuteClient) GetResult(ctx context.Context, taskIDs []string, onlyCurrentController bool) (*GetResultResponse, error)

GetResult 查询任务结果(支持批量查询)

func (*AsyncExecuteClient) GetSingleResult

func (c *AsyncExecuteClient) GetSingleResult(ctx context.Context, taskID string, onlyCurrentController bool) (*AsyncTaskResult, error)

GetSingleResult 查询单个任务结果(便捷方法)

func (*AsyncExecuteClient) StackUpExecute

StackUpExecute 执行 StackUp 命令 接收一个 YAML 格式的配置文件,解析后执行其中的命令

func (*AsyncExecuteClient) SyncExecute

SyncExecute 同步执行命令(提交任务并等待结果) 简洁实现:使用简单的轮询循环,逻辑清晰

type AsyncExecuteClientConfig

type AsyncExecuteClientConfig struct {
	BaseURL         string        // API 基础 URL,例如 "http://localhost:8081"
	HTTPClient      *http.Client  // 自定义 HTTP 客户端(可选)
	DefaultTimeout  time.Duration // 默认请求超时时间
	PollInterval    time.Duration // 轮询间隔(同步调用时使用)
	MaxPollDuration time.Duration // 最大轮询时间(同步调用时使用)
	MaxPollAttempts int           // 最大轮询次数(同步调用时使用)
}

AsyncExecuteClientConfig SDK 客户端配置

func DefaultAsyncExecuteClientConfig

func DefaultAsyncExecuteClientConfig(baseURL string) *AsyncExecuteClientConfig

DefaultAsyncExecuteClientConfig 返回默认配置

type AsyncExecuteRequest

type AsyncExecuteRequest struct {
	ID         string                     `json:"id"`
	RemoteInfo structs.L2DeviceRemoteInfo `json:"remote_info"`
	Commands   []string                   `json:"commands,omitempty"`
	Script     string                     `json:"script,omitempty"`
	ScriptPath string                     `json:"script_path,omitempty"`
	Background bool                       `json:"background,omitempty"`
	Timeout    int                        `json:"timeout,omitempty"`
}

AsyncExecuteRequest 异步执行请求

type AsyncExecuteResponse

type AsyncExecuteResponse struct {
	Success  bool     `json:"success,omitempty"`
	TaskID   string   `json:"id"` // API 返回的字段是 "id"
	Status   string   `json:"status"`
	Message  string   `json:"message"`
	TaskInfo TaskInfo `json:"task_info"`
}

AsyncExecuteResponse 异步执行响应

type AsyncTaskResult

type AsyncTaskResult struct {
	Status   TaskStatus `json:"status"`
	TaskInfo TaskInfo   `json:"task_info"`

	StartTime time.Time  `json:"start_time"`
	EndTime   *time.Time `json:"end_time,omitempty"`
	Duration  *int64     `json:"duration,omitempty"`

	Result *ExecutionResult `json:"result,omitempty"`
	Error  *ErrorDetail     `json:"error,omitempty"`

	Message string `json:"message,omitempty"`
}

AsyncTaskResult 异步任务结果

func (*AsyncTaskResult) GetCombinedError

func (r *AsyncTaskResult) GetCombinedError() string

GetCombinedError 获取合并后的错误输出

func (*AsyncTaskResult) GetCombinedOutput

func (r *AsyncTaskResult) GetCombinedOutput() string

GetCombinedOutput 获取合并后的输出(兼容旧版本)

func (*AsyncTaskResult) IsSuccess

func (r *AsyncTaskResult) IsSuccess() bool

IsSuccess 检查任务是否成功完成

type Client

type Client struct {
	// contains filtered or unexported fields
}

func NewClient

func NewClient(address, username, password string) *Client

func (*Client) CreateDeployment

func (c *Client) CreateDeployment(req models.DeploymentRequest) (*models.Deployment, error)

CreateDeployment creates a new deployment

func (*Client) GetControllerStatus

func (c *Client) GetControllerStatus() (*models.ControllerStatus, error)

func (*Client) GetDeployment

func (c *Client) GetDeployment(deploymentID string) (*models.Deployment, error)

GetDeployment retrieves a deployment by its ID

func (*Client) GetPackageLogs

func (c *Client) GetPackageLogs(agentCode, packageName string, count int) ([]string, error)

GetPackageLogs retrieves logs for a specific package on a specific agent

func (*Client) ListAgents

func (c *Client) ListAgents(filter map[string]string, page, pageSize int) (*models.AgentsResponse, error)

func (*Client) ListDeployments

func (c *Client) ListDeployments() ([]models.Deployment, error)

ListDeployments retrieves a list of all deployments

func (*Client) StartPackage

func (c *Client) StartPackage(agentCode, packageName string) error

StartPackage starts a package on a specific agent

func (*Client) StopPackage

func (c *Client) StopPackage(agentCode, packageName string) error

StopPackage stops a package on a specific agent

type CommandResult

type CommandResult struct {
	Index      int       `json:"index"`
	Command    string    `json:"command"`
	Stdout     string    `json:"stdout,omitempty"`
	Stderr     string    `json:"stderr,omitempty"`
	ExitCode   int       `json:"exit_code,omitempty"`
	Success    bool      `json:"success"`
	Error      string    `json:"error,omitempty"`
	Duration   int64     `json:"duration,omitempty"`
	ExecutedAt time.Time `json:"executed_at"`
}

CommandResult 单个命令的执行结果

type ConfigDriver

type ConfigDriver struct {
	keys.Keys
	EtcdEndpoints []string
	EtcdUsername  string
	EtcdPassword  string
}

func NewConfigDriver

func NewConfigDriver(base, area string, endpoints []string) *ConfigDriver

func NewConfigDriverWithAuth

func NewConfigDriverWithAuth(base, area string, endpoints []string, username, password string) *ConfigDriver

func (*ConfigDriver) Enable

func (cd *ConfigDriver) Enable(ctx context.Context, enable bool, paths ...string) error

func (*ConfigDriver) GetConfig

func (cd *ConfigDriver) GetConfig(ctx context.Context, paths ...string) (map[string]interface{}, error)

func (*ConfigDriver) PutConfig

func (cd *ConfigDriver) PutConfig(ctx context.Context, value interface{}, paths ...string) error

type ErrorDetail

type ErrorDetail struct {
	Type    ErrorType `json:"type"`
	Code    string    `json:"code,omitempty"`
	Message string    `json:"message"`
	Details string    `json:"details,omitempty"`
}

ErrorDetail 错误详情

type ErrorType

type ErrorType string

ErrorType 错误类型

const (
	ErrorTypeNone           ErrorType = "none"
	ErrorTypeNetwork        ErrorType = "network"
	ErrorTypeAuthentication ErrorType = "authentication"
	ErrorTypeExecution      ErrorType = "execution"
	ErrorTypeTimeout        ErrorType = "timeout"
	ErrorTypeCancelled      ErrorType = "cancelled"
	ErrorTypeUnknown        ErrorType = "unknown"
)

type ExecutionResult

type ExecutionResult struct {
	Stdout         string          `json:"stdout,omitempty"`
	Stderr         string          `json:"stderr,omitempty"`
	ExitCode       int             `json:"exit_code,omitempty"`
	OutputSize     int64           `json:"output_size"`
	CommandResults []CommandResult `json:"command_results,omitempty"`
}

ExecutionResult 执行结果详情

type GetResultRequest

type GetResultRequest struct {
	TaskIDs               []string `json:"task_ids"`
	OnlyCurrentController bool     `json:"only_current,omitempty"`
}

GetResultRequest 查询结果请求

type GetResultResponse

type GetResultResponse struct {
	Results map[string]*AsyncTaskResult `json:"results"`
	Errors  map[string]string           `json:"errors,omitempty"`
}

GetResultResponse 查询结果响应

type StackUpCommandResult

type StackUpCommandResult struct {
	Index   int    `json:"index"`   // 命令索引(从1开始)
	Command string `json:"command"` // 执行的命令
	Key     string `json:"key"`     // 命令的 key/name
	Output  string `json:"output"`  // 命令输出
	Msg     string `json:"msg"`     // 消息
	Status  string `json:"status"`  // 状态:"true" 表示有错误,"false" 表示成功
}

StackUpCommandResult 单个命令的执行结果

type StackUpExecuteRequest

type StackUpExecuteRequest struct {
	RemoteInfo    structs.L2DeviceRemoteInfo `json:"remote_info"`               // 设备连接信息
	Config        string                     `json:"config"`                    // YAML 格式的配置文件(可以是 base64 编码或原始字符串)
	ConfigType    string                     `json:"config_type,omitempty"`     // "yaml" 或 "base64",默认为 "yaml"
	LocalDataPath string                     `json:"local_data_path,omitempty"` // 本地数据路径(可选)
}

StackUpExecuteRequest StackUp 执行请求

type StackUpExecuteResponse

type StackUpExecuteResponse struct {
	Success bool                   `json:"success"`
	Message string                 `json:"message,omitempty"`
	Results []StackUpCommandResult `json:"results,omitempty"`
	Error   string                 `json:"error,omitempty"`
}

StackUpExecuteResponse StackUp 执行响应

type SyncExecuteOptions

type SyncExecuteOptions struct {
	PollInterval    time.Duration                                    // 轮询间隔,默认使用 AsyncExecuteClientConfig 中的值
	MaxPollDuration time.Duration                                    // 最大轮询时间,默认使用 AsyncExecuteClientConfig 中的值
	MaxPollAttempts int                                              // 最大轮询次数,默认使用 AsyncExecuteClientConfig 中的值
	OnStatusUpdate  func(status TaskStatus, result *AsyncTaskResult) // 状态更新回调(可选)
}

SyncExecuteOptions 同步执行选项

type TaskInfo

type TaskInfo struct {
	ID           string    `json:"id"`
	ControllerID string    `json:"controller_id"`
	DeviceIP     string    `json:"device_ip"`
	DevicePort   int       `json:"device_port"`
	Username     string    `json:"username"`
	CommandType  string    `json:"command_type"`
	Background   bool      `json:"background"`
	Timeout      int       `json:"timeout"`
	CreatedAt    time.Time `json:"created_at"`
}

TaskInfo 任务信息

type TaskStatus

type TaskStatus string

TaskStatus 任务状态

const (
	TaskStatusPending   TaskStatus = "pending"   // 待执行
	TaskStatusRunning   TaskStatus = "running"   // 执行中
	TaskStatusCompleted TaskStatus = "completed" // 已完成
	TaskStatusFailed    TaskStatus = "failed"    // 执行失败
	TaskStatusTimeout   TaskStatus = "timeout"   // 执行超时
	TaskStatusCancelled TaskStatus = "cancelled" // 已取消
)

func (TaskStatus) IsCompleted

func (s TaskStatus) IsCompleted() bool

IsCompleted 检查任务是否已完成(成功或失败)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL