kra-new/internal/integration/connectivity.go

88 lines
2.7 KiB
Go

package integration
import (
"context"
"encoding/json"
"errors"
"fmt"
integrationbiz "kra/internal/biz/integration"
"strings"
"kra/internal/config"
"kra/internal/integration/mq"
"kra/internal/integration/runtimeconfig"
websocketintegration "kra/internal/integration/websocket"
)
// ConnectivityTester probes candidate communication settings without changing
// the active clients or writing anything to sys_integration_configs.
type ConnectivityTester struct {
store *runtimeconfig.Store
}
func NewConnectivityTester(store *runtimeconfig.Store) *ConnectivityTester {
return &ConnectivityTester{store: store}
}
func (t *ConnectivityTester) TestIntegration(ctx context.Context, config *integrationbiz.IntegrationConfig) error {
if config == nil {
return errors.New("集成配置请求为空")
}
values := map[string]any{}
if err := json.Unmarshal(config.Values, &values); err != nil {
return fmt.Errorf("解析集成配置失败: %w", err)
}
if err := t.restoreMaskedSecrets(config.Kind, config.Provider, values); err != nil {
return err
}
raw, err := json.Marshal(values)
if err != nil {
return fmt.Errorf("编码集成配置失败: %w", err)
}
switch strings.ToLower(strings.TrimSpace(config.Kind)) {
case integrationbiz.IntegrationKindMQ:
return mq.TestConfig(ctx, config.Provider, raw)
case integrationbiz.IntegrationKindWebSocket:
if strings.ToLower(strings.TrimSpace(config.Provider)) != websocketintegration.ProviderMelody {
return fmt.Errorf("不支持的 WebSocket provider %q", config.Provider)
}
return websocketintegration.TestConfig(ctx, raw)
default:
return fmt.Errorf("不支持测试集成类型 %q", config.Kind)
}
}
func (t *ConnectivityTester) restoreMaskedSecrets(kind, provider string, values map[string]any) error {
definition, ok := integrationbiz.IntegrationDefinition(kind, provider)
if !ok {
return fmt.Errorf("不支持的集成 %s/%s", kind, provider)
}
masked := make(map[string]struct{})
for _, field := range definition.Fields {
if field.Secret || integrationbiz.IsIntegrationSecretKey(field.Key) {
masked[field.Key] = struct{}{}
}
}
if len(masked) == 0 {
return nil
}
currentValues := map[string]any{}
if t != nil && t.store != nil {
if current, exists := t.store.Get(kind, provider); exists {
_ = json.Unmarshal(current.Values, &currentValues)
}
}
for key := range masked {
value, _ := values[key].(string)
if !config.IsMaskedSecret(strings.TrimSpace(value)) {
continue
}
prior, _ := currentValues[key].(string)
if config.IsMaskedSecret(strings.TrimSpace(prior)) {
return fmt.Errorf("配置字段 %s 已脱敏,请重新填写后再测试", key)
}
values[key] = prior
}
return nil
}