mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-05-06 20:03:05 +08:00
- 新增 JMX/Endpoint/Agent 三种 JVM 连接模式与配置归一化链路 - 支持资源浏览、变更预览、写入应用、审计记录与只读约束 - 接入 AI 结构化写入计划与诊断计划回填能力 - 新增 Agent Bridge、Arthas Tunnel、JMX Helper 诊断传输实现 - 增加诊断控制台、命令模板、输出历史与自动补全交互 - 补齐前后端契约、运行夹具与 JVM 相关回归测试
151 lines
3.8 KiB
Go
151 lines
3.8 KiB
Go
package jvm
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"time"
|
|
|
|
"GoNavi-Wails/internal/connection"
|
|
)
|
|
|
|
type HTTPProvider struct{}
|
|
|
|
func NewHTTPProvider() Provider { return &HTTPProvider{} }
|
|
|
|
func (p *HTTPProvider) Mode() string { return ModeEndpoint }
|
|
|
|
func (p *HTTPProvider) TestConnection(ctx context.Context, cfg connection.ConnectionConfig) error {
|
|
runtime, err := newEndpointRuntime(cfg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
resp, err := doContractProbe(ctx, runtime.contractRuntime, http.MethodHead)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if resp.StatusCode == http.StatusMethodNotAllowed || resp.StatusCode == http.StatusNotImplemented {
|
|
_ = resp.Body.Close()
|
|
resp, err = doContractProbe(ctx, runtime.contractRuntime, http.MethodGet)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
defer resp.Body.Close()
|
|
if isReachableStatus(resp.StatusCode) {
|
|
return nil
|
|
}
|
|
return fmt.Errorf("endpoint returned unexpected status: %d", resp.StatusCode)
|
|
}
|
|
|
|
func (p *HTTPProvider) ProbeCapabilities(_ context.Context, cfg connection.ConnectionConfig) ([]Capability, error) {
|
|
if _, err := newEndpointRuntime(cfg); err != nil {
|
|
return nil, err
|
|
}
|
|
readOnly := cfg.JVM.ReadOnly != nil && *cfg.JVM.ReadOnly
|
|
return []Capability{{
|
|
Mode: ModeEndpoint,
|
|
CanBrowse: true,
|
|
CanWrite: !readOnly,
|
|
CanPreview: true,
|
|
DisplayLabel: "Endpoint",
|
|
Reason: func() string {
|
|
if readOnly {
|
|
return "当前连接只读"
|
|
}
|
|
return ""
|
|
}(),
|
|
}}, nil
|
|
}
|
|
|
|
func (p *HTTPProvider) ListResources(ctx context.Context, cfg connection.ConnectionConfig, parentPath string) ([]ResourceSummary, error) {
|
|
runtime, err := newEndpointRuntime(cfg)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
query := url.Values{}
|
|
query.Set("parentPath", parentPath)
|
|
|
|
var resources []ResourceSummary
|
|
if err := runtime.doJSON(ctx, http.MethodGet, "list resources", "resources", query, nil, &resources); err != nil {
|
|
return nil, err
|
|
}
|
|
return resources, nil
|
|
}
|
|
|
|
func (p *HTTPProvider) GetValue(ctx context.Context, cfg connection.ConnectionConfig, resourcePath string) (ValueSnapshot, error) {
|
|
runtime, err := newEndpointRuntime(cfg)
|
|
if err != nil {
|
|
return ValueSnapshot{}, err
|
|
}
|
|
|
|
query := url.Values{}
|
|
query.Set("resourcePath", resourcePath)
|
|
|
|
var snapshot ValueSnapshot
|
|
if err := runtime.doJSON(ctx, http.MethodGet, "get value", "value", query, nil, &snapshot); err != nil {
|
|
return ValueSnapshot{}, err
|
|
}
|
|
return snapshot, nil
|
|
}
|
|
|
|
func (p *HTTPProvider) PreviewChange(ctx context.Context, cfg connection.ConnectionConfig, req ChangeRequest) (ChangePreview, error) {
|
|
runtime, err := newEndpointRuntime(cfg)
|
|
if err != nil {
|
|
return ChangePreview{}, err
|
|
}
|
|
|
|
var preview ChangePreview
|
|
if err := runtime.doJSON(ctx, http.MethodPost, "preview change", "preview", nil, req, &preview); err != nil {
|
|
return ChangePreview{}, err
|
|
}
|
|
return preview, nil
|
|
}
|
|
|
|
func (p *HTTPProvider) ApplyChange(ctx context.Context, cfg connection.ConnectionConfig, req ChangeRequest) (ApplyResult, error) {
|
|
runtime, err := newEndpointRuntime(cfg)
|
|
if err != nil {
|
|
return ApplyResult{}, err
|
|
}
|
|
|
|
var result ApplyResult
|
|
if err := runtime.doJSON(ctx, http.MethodPost, "apply change", "apply", nil, req, &result); err != nil {
|
|
return ApplyResult{}, err
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
type endpointRuntime struct {
|
|
contractRuntime
|
|
}
|
|
|
|
func newEndpointRuntime(cfg connection.ConnectionConfig) (endpointRuntime, error) {
|
|
runtime, err := newContractRuntime(
|
|
cfg.JVM.Endpoint.BaseURL,
|
|
cfg.JVM.Endpoint.APIKey,
|
|
resolveEndpointTimeout(cfg),
|
|
"endpoint",
|
|
)
|
|
if err != nil {
|
|
return endpointRuntime{}, err
|
|
}
|
|
|
|
return endpointRuntime{
|
|
contractRuntime: runtime,
|
|
}, nil
|
|
}
|
|
|
|
func resolveEndpointTimeout(cfg connection.ConnectionConfig) time.Duration {
|
|
timeout := time.Duration(cfg.JVM.Endpoint.TimeoutSeconds) * time.Second
|
|
if timeout <= 0 {
|
|
timeout = time.Duration(cfg.Timeout) * time.Second
|
|
}
|
|
if timeout <= 0 {
|
|
timeout = 5 * time.Second
|
|
}
|
|
return timeout
|
|
}
|