### Query Plugin Versions and Details with hub.GetPlugin in Go Source: https://context7.com/tencentblueking/bk-plugin-framework-go/llms.txt Shows how to use the hub package to retrieve information about installed plugins. This includes fetching all installed versions, getting details for a specific plugin version, and accessing its JSON schemas for inputs, context inputs, and outputs. It also demonstrates how to get a plugin instance directly. ```go package main import ( "encoding/json" "fmt" "github.com/TencentBlueKing/bk-plugin-framework-go/hub" ) func listPlugins() { // Get all installed versions (sorted newest to oldest) versions := hub.GetPluginVersions() fmt.Printf("Installed versions: %v\n", versions) // Output: Installed versions: [2.0.0 1.1.0 1.0.0] // Get specific plugin detail detail, err := hub.GetPluginDetail("1.0.0") if err != nil { fmt.Printf("Plugin not found: %v\n", err) return } // Access plugin instance plugin := detail.Plugin() fmt.Printf("Plugin v%s: %s\n", plugin.Version(), plugin.Desc()) // Get JSON schemas contextInputsSchema := detail.ContextInputsSchema() outputsSchema := detail.OutputsSchema() // Get schemas as map for manipulation inputsSchemaJSON := detail.InputsSchemaJSON() contextInputsSchemaJSON := detail.ContextInputsSchemaJSON() outputsSchemaJSON := detail.OutputsSchemaJSON() // Pretty print schemas schemaBytes, _ := json.MarshalIndent(inputsSchemaJSON, "", " ") fmt.Printf("Inputs Schema:\n%s\n", string(schemaBytes)) } func getPluginForExecution(version string) { // Get plugin instance directly plugin, err := hub.GetPlugin(version) if err != nil { fmt.Printf("Failed to get plugin: %v\n", err) return } fmt.Printf("Loaded plugin: %s - %s\n", plugin.Version(), plugin.Desc()) } ``` -------------------------------- ### Implement Runtime Interfaces for Host System (Go) Source: https://context7.com/tencentblueking/bk-plugin-framework-go/llms.txt Provides example implementations for `ContextReader`, `ObjectStore`, `PluginExecuteRuntime`, and `PluginScheduleExecuteRuntime`. These interfaces are crucial for the host system to provide input, store state, and manage plugin execution flow. ```go package myruntime import ( "encoding/json" "time" "github.com/TencentBlueKing/bk-plugin-framework-go/runtime" ) // ContextReader implementation type MyContextReader struct { inputs []byte contextInputs []byte } func (r *MyContextReader) ReadInputs(v interface{}) error { return json.Unmarshal(r.inputs, v) } func (r *MyContextReader) ReadContextInputs(v interface{}) error { return json.Unmarshal(r.contextInputs, v) } // ObjectStore implementation (e.g., Redis-backed) type RedisStore struct { prefix string // redis client } func (s *RedisStore) Write(traceID string, v interface{}) error { data, err := json.Marshal(v) if err != nil { return err } key := s.prefix + ":" + traceID // redis.Set(key, data) return nil } func (s *RedisStore) Read(traceID string, v interface{}) error { key := s.prefix + ":" + traceID // data := redis.Get(key) var data []byte // placeholder return json.Unmarshal(data, v) } // PluginExecuteRuntime implementation type MyRuntime struct { contextStore *RedisStore outputsStore *RedisStore } func (r *MyRuntime) GetContextStore() runtime.ObjectStore { return r.contextStore } func (r *MyRuntime) GetOutputsStore() runtime.ObjectStore { return r.outputsStore } func (r *MyRuntime) SetPoll(traceID, version string, invokeCount int, after time.Duration) error { // Schedule re-execution after duration // e.g., add to delayed queue return nil } // PluginScheduleExecuteRuntime extends PluginExecuteRuntime type MyScheduleRuntime struct { *MyRuntime } func (r *MyScheduleRuntime) SetFail(traceID string, err error) error { // Mark execution as failed return nil } func (r *MyScheduleRuntime) SetSuccess(traceID string) error { // Mark execution as successful return nil } ``` -------------------------------- ### Go Plugin Example: Async Task with Polling Source: https://context7.com/tencentblueking/bk-plugin-framework-go/llms.txt This Go code defines a plugin that starts an asynchronous task and polls for its completion. It handles different states like initial execution and polling, reads inputs and context, simulates task creation, persists state, and schedules polling intervals. It also includes logic for simulating task status and writing outputs upon completion. ```go package v100 import ( "fmt" "time" "github.com/TencentBlueKing/bk-plugin-framework-go/constants" "github.com/TencentBlueKing/bk-plugin-framework-go/kit" ) //go:embed form.json var InputsForm []byte type Inputs struct { TemplateID int `json:"template_id" jsonschema:"title=Template ID,required" TaskName string `json:"task_name" jsonschema:"title=Task Name,required" } type ContextInputs struct { ProjectID int `json:"project_id" jsonschema:"title=Project ID" BKBizID int `json:"bk_biz_id" jsonschema:"title=Business ID" Operator string `json:"operator" jsonschema:"title=Operator" Executor string `json:"executor" jsonschema:"title=Executor" } type Outputs struct { TaskID int `json:"task_id" jsonschema:"title=Task ID" TaskURL string `json:"task_url" jsonschema:"title=Task URL" Duration int `json:"duration" jsonschema:"title=Duration (seconds)" } type Store struct { TaskID int TaskURL string StartTime time.Time } type Plugin struct{} func (p *Plugin) Version() string { return "1.0.0" } func (p *Plugin) Desc() string { return "Execute SOPS Task with Polling" } func (p *Plugin) Execute(c *kit.Context) error { state := c.State() c.Infof("Executing plugin, state=%d, invokeCount=%d", state, c.InvokeCount()) switch state { case constants.StateEmpty: return p.handleInitialExecution(c) case constants.StatePoll: return p.handlePollExecution(c) default: return fmt.Errorf("unexpected state: %d", state) } } func (p *Plugin) handleInitialExecution(c *kit.Context) error { var inputs Inputs if err := c.ReadInputs(&inputs); err != nil { return fmt.Errorf("read inputs: %w", err) } var ctx ContextInputs if err := c.ReadContextInputs(&ctx); err != nil { return fmt.Errorf("read context inputs: %w", err) } c.Infof("Creating task: template=%d, name=%s, biz=%d", inputs.TemplateID, inputs.TaskName, ctx.BKBizID) // Simulate API call to create task taskID := 12345 taskURL := fmt.Sprintf("https://sops.example.com/task/%d", taskID) // Persist state for polling store := Store{ TaskID: taskID, TaskURL: taskURL, StartTime: time.Now(), } if err := c.Write(&store); err != nil { return fmt.Errorf("write store: %w", err) } // Schedule poll in 5 seconds c.WaitPoll(5 * time.Second) c.Info("Task created, entering poll state") return nil } func (p *Plugin) handlePollExecution(c *kit.Context) error { var store Store if err := c.Read(&store); err != nil { return fmt.Errorf("read store: %w", err) } c.Infof("Polling task %d (attempt %d)", store.TaskID, c.InvokeCount()) // Simulate checking task status status := "RUNNING" if c.InvokeCount() >= 3 { status = "FINISHED" } switch status { case "RUNNING": if c.InvokeCount() > 60 { return fmt.Errorf("task %d timed out", store.TaskID) } c.WaitPoll(5 * time.Second) return nil case "FINISHED": duration := int(time.Since(store.StartTime).Seconds()) outputs := Outputs{ TaskID: store.TaskID, TaskURL: store.TaskURL, Duration: duration, } if err := c.WriteOutputs(&outputs); err != nil { return fmt.Errorf("write outputs: %w", err) } c.Infof("Task completed in %d seconds", duration) return nil case "FAILED": return fmt.Errorf("task %d failed", store.TaskID) default: return fmt.Errorf("unknown status: %s", status) } } ``` -------------------------------- ### Register Plugin with Framework Hub in Go Source: https://context7.com/tencentblueking/bk-plugin-framework-go/llms.txt This Go code demonstrates how to register a plugin version with the bk-plugin-framework-go hub using `hub.MustInstall`. It shows how to provide the plugin instance, context inputs, outputs, and a UI form schema for the plugin's inputs. The `runner.Run()` function is called to start the plugin execution environment. ```go package main import ( "encoding/json" v100 "myproject/bk_plugin/v100" "github.com/TencentBlueKing/beego-runtime/runner" "github.com/TencentBlueKing/bk-plugin-framework-go/hub" ) // InputsForm defines the UI form schema (JSON Schema format) var inputsFormJSON = []byte(`{ "type": "object", "properties": { "template_id": { "type": "integer", "title": "Template ID", "ui:component": {"name": "bk-input", "props": {"type": "number"}} }, "task_name": { "type": "string", "title": "Task Name", "ui:component": {"name": "bk-input", "props": {"type": "text"}} } }, "required": ["template_id"] }`) func main() { // Register plugin version 1.0.0 hub.MustInstall( &v100.Plugin{}, // Plugin instance v100.ContextInputs{}, // Context inputs struct for schema generation v100.Outputs{}, // Outputs struct for schema generation inputsFormJSON, // JSON schema form definition ) // Register additional versions // hub.MustInstall(&v110.Plugin{}, v110.ContextInputs{}, v110.Outputs{}, v110InputsForm) runner.Run() } ``` -------------------------------- ### Execution States Constants and Transitions Source: https://context7.com/tencentblueking/bk-plugin-framework-go/llms.txt Defines the five execution states used by the framework: StateEmpty, StatePoll, StateCallback, StateSuccess, and StateFail. Provides an example of how to transition between these states based on the plugin's execution logic. ```go import "github.com/TencentBlueKing/bk-plugin-framework-go/constants" // State constants const ( StateEmpty constants.State = 1 // Initial execution state StatePoll constants.State = 2 // Waiting for poll interval StateCallback constants.State = 3 // Waiting for external callback StateSuccess constants.State = 4 // Terminal: execution succeeded StateFail constants.State = 5 // Terminal: execution failed ) // State transition example func (p *Plugin) Execute(c *kit.Context) error { switch c.State() { case constants.StateEmpty: // Initial execution c.WaitPoll(10 * time.Second) // -> StatePoll return nil case constants.StatePoll: if taskComplete() { return nil // -> StateSuccess } if taskFailed() { return fmt.Errorf("task failed") // -> StateFail } c.WaitPoll(10 * time.Second) // Stay in StatePoll return nil } return nil } ``` -------------------------------- ### Execute and Schedule Plugin Execution (Go) Source: https://context7.com/tencentblueking/bk-plugin-framework-go/llms.txt Demonstrates how to use the `executor.Execute` and `executor.Schedule` functions for plugin invocation and poll-based re-execution. It handles state management, error reporting, and logging. ```go package main import ( "github.com/TencentBlueKing/bk-plugin-framework-go/constants" "github.com/TencentBlueKing/bk-plugin-framework-go/executor" "github.com/TencentBlueKing/bk-plugin-framework-go/runtime" log "github.com/sirupsen/logrus" ) // Execute for initial plugin invocation func runPlugin(traceID, version string, reader runtime.ContextReader, rt runtime.PluginExecuteRuntime) { logger := log.WithFields(log.Fields{ "trace_id": traceID, "version": version, }) // Execute returns the resulting state state, err := executor.Execute(traceID, version, reader, rt, logger) switch state { case constants.StateSuccess: logger.Info("Plugin execution completed successfully") case constants.StateFail: logger.Errorf("Plugin execution failed: %v", err) case constants.StatePoll: logger.Info("Plugin entered poll state, will be scheduled") } } // Schedule for poll-based re-execution func schedulePlugin(traceID, version string, invokeCount int, reader runtime.ContextReader, rt runtime.PluginScheduleExecuteRuntime) { logger := log.WithFields(log.Fields{ "trace_id": traceID, "version": version, "invoke_count": invokeCount, }) // Schedule handles state transitions and error reporting err := executor.Schedule(traceID, version, invokeCount, reader, rt, logger) if err != nil { logger.Errorf("Schedule failed: %v", err) } } ``` -------------------------------- ### Define and Implement Plugin Interface in Go Source: https://context7.com/tencentblueking/bk-plugin-framework-go/llms.txt This Go code defines the necessary structs for plugin inputs, context inputs, and outputs, along with a concrete implementation of the Plugin interface. It demonstrates how to read inputs and context, perform plugin logic, and write outputs using the provided kit.Context. ```go package myplugin import ( "fmt" "github.com/TencentBlueKing/bk-plugin-framework-go/constants" "github.com/TencentBlueKing/bk-plugin-framework-go/kit" ) // Define input schema with JSON tags and jsonschema annotations type Inputs struct { TemplateID int `json:"template_id" jsonschema:"title=Template ID" TaskName string `json:"task_name" jsonschema:"title=Task Name" } // Define context inputs provided by the host system type ContextInputs struct { BKBizID int `json:"bk_biz_id" jsonschema:"title=Business ID" Operator string `json:"operator" jsonschema:"title=Operator" } // Define output schema type Outputs struct { TaskID int `json:"task_id" jsonschema:"title=Task ID" TaskURL string `json:"task_url" jsonschema:"title=Task URL" } // Plugin implementation type Plugin struct{} func (p *Plugin) Version() string { return "1.0.0" } func (p *Plugin) Desc() string { return "Execute standard operations task" } func (p *Plugin) Execute(c *kit.Context) error { var inputs Inputs if err := c.ReadInputs(&inputs); err != nil { return fmt.Errorf("failed to read inputs: %w", err) } var contextInputs ContextInputs if err := c.ReadContextInputs(&contextInputs); err != nil { return fmt.Errorf("failed to read context inputs: %w", err) } // Plugin logic here outputs := Outputs{ TaskID: 12345, TaskURL: "https://example.com/task/12345", } if err := c.WriteOutputs(&outputs); err != nil { return fmt.Errorf("failed to write outputs: %w", err) } return nil // Success state } ``` -------------------------------- ### Read/Write Inputs, Context Inputs, and Outputs using Context Source: https://context7.com/tencentblueking/bk-plugin-framework-go/llms.txt Demonstrates how to use the kit.Context object to read plugin inputs, context inputs, and write outputs within a plugin's Execute method. It utilizes JSON encoding for data serialization and handles potential errors during these operations. ```go func (p *Plugin) Execute(c *kit.Context) error { // Read plugin inputs (user-provided parameters) var inputs Inputs if err := c.ReadInputs(&inputs); err != nil { return err } // Read context inputs (system-provided context like business ID, operator) var contextInputs ContextInputs if err := c.ReadContextInputs(&contextInputs); err != nil { return err } // Get execution metadata traceID := c.TraceID() // Unique execution identifier invokeCount := c.InvokeCount() // Number of times Execute has been called // Perform plugin logic result, err := performTask(inputs.TemplateID, contextInputs.BKBizID) if err != nil { return fmt.Errorf("task failed: %w", err) // Transitions to FAIL state } // Write outputs outputs := Outputs{ TaskID: result.ID, TaskURL: result.URL, } if err := c.WriteOutputs(&outputs); err != nil { return err } // Read outputs back if needed var savedOutputs Outputs if err := c.ReadOutputs(&savedOutputs); err != nil { return err } return nil // Transitions to SUCCESS state } ``` -------------------------------- ### Define UI Forms with kit.Form in Go Source: https://context7.com/tencentblueking/bk-plugin-framework-go/llms.txt Demonstrates how to define UI components for plugin input fields using the kit.Form and kit.F types. This includes specifying component types, properties, and data sources for rendering in the BlueKing UI. It also shows the corresponding Go struct for these inputs. ```go package v100 import "github.com/TencentBlueKing/bk-plugin-framework-go/kit" // Define data source for select component var taskTypeOptions = []map[string]string{ {"label": "Quick Task", "value": "quick"}, {"label": "Standard Task", "value": "standard"}, {"label": "Complex Task", "value": "complex"}, } // InputsForm defines UI components for each input field var InputsForm kit.Form = kit.Form{ "template_id": kit.F{ "ui:component": kit.F{ "name": "bk-input", "props": kit.F{"type": "number", "min": 1}, }, "ui:reactions": []kit.F{}, }, "task_name": kit.F{ "ui:component": kit.F{ "name": "bk-input", "props": kit.F{"type": "text", "placeholder": "Enter task name"}, }, "ui:reactions": []kit.F{}, }, "task_type": kit.F{ "ui:component": kit.F{ "name": "select", "props": kit.F{ "type": "select", "datasource": taskTypeOptions, }, }, "ui:reactions": []kit.F{}, }, "description": kit.F{ "ui:component": kit.F{ "name": "bk-input", "props": kit.F{"type": "textarea", "rows": 4}, }, "ui:reactions": []kit.F{}, }, } // Corresponding Inputs struct type Inputs struct { TemplateID int `json:"template_id" jsonschema:"title=Template ID,required"` TaskName string `json:"task_name" jsonschema:"title=Task Name,required"` TaskType string `json:"task_type" jsonschema:"title=Task Type"` Description string `json:"description" jsonschema:"title=Description"` } ``` -------------------------------- ### State Management and Polling for Long-Running Tasks Source: https://context7.com/tencentblueking/bk-plugin-framework-go/llms.txt Illustrates how to manage long-running tasks using the framework's execution states and polling mechanism. It shows how to persist state data between poll cycles using Write/Read methods and transition between states like StateEmpty and StatePoll. ```go // Store is used to persist data between poll cycles type Store struct { TaskID int TaskURL string StartTime time.Time } func (p *Plugin) Execute(c *kit.Context) error { state := c.State() switch state { case constants.StateEmpty: // First execution - start the task var inputs Inputs if err := c.ReadInputs(&inputs); err != nil { return err } // Start async task taskID, taskURL := startAsyncTask(inputs.TemplateID) // Save state for polling store := Store{ TaskID: taskID, TaskURL: taskURL, StartTime: time.Now(), } if err := c.Write(&store); err != nil { return err } // Enter poll state - will be re-executed after 5 seconds c.WaitPoll(5 * time.Second) return nil case constants.StatePoll: // Polling execution - check task status var store Store if err := c.Read(&store); err != nil { return err } status := checkTaskStatus(store.TaskID) switch status { case "RUNNING": // Still running - continue polling if c.InvokeCount() > 100 { return fmt.Errorf("task %d timed out after 100 polls", store.TaskID) } c.WaitPoll(5 * time.Second) return nil case "FINISHED": // Task completed - write outputs and finish outputs := Outputs{TaskID: store.TaskID, TaskURL: store.TaskURL} if err := c.WriteOutputs(&outputs); err != nil { return err } return nil // SUCCESS state case "FAILED": return fmt.Errorf("task %d failed", store.TaskID) } } return fmt.Errorf("invalid state: %v", state) } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.