优化结构
This commit is contained in:
@@ -74,7 +74,7 @@ func (t *ConnectivityTester) restoreMaskedSecrets(kind, provider string, values
|
||||
}
|
||||
for key := range masked {
|
||||
value, _ := values[key].(string)
|
||||
if !config.IsMaskedSecret(strings.TrimSpace(value)) {
|
||||
if strings.TrimSpace(value) != config.MaskedSecret {
|
||||
continue
|
||||
}
|
||||
prior, _ := currentValues[key].(string)
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
integrationbiz "kra/internal/biz/integration"
|
||||
)
|
||||
|
||||
type kafkaConnectivityRepo struct{}
|
||||
|
||||
func (*kafkaConnectivityRepo) ListIntegrationConfigs(context.Context, string) ([]*integrationbiz.IntegrationConfig, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (*kafkaConnectivityRepo) FindIntegrationConfig(context.Context, string, string) (*integrationbiz.IntegrationConfig, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (*kafkaConnectivityRepo) SaveIntegrationConfig(context.Context, *integrationbiz.IntegrationConfig) error {
|
||||
return nil
|
||||
}
|
||||
func (*kafkaConnectivityRepo) DeleteIntegrationConfig(context.Context, string, string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestKafkaConnectivityIntegration(t *testing.T) {
|
||||
rawBrokers := strings.TrimSpace(os.Getenv("KRA_KAFKA_TEST_BROKERS"))
|
||||
if rawBrokers == "" {
|
||||
t.Skip("KRA_KAFKA_TEST_BROKERS is not configured")
|
||||
}
|
||||
brokers := make([]string, 0)
|
||||
for _, broker := range strings.Split(rawBrokers, ",") {
|
||||
if broker = strings.TrimSpace(broker); broker != "" {
|
||||
brokers = append(brokers, broker)
|
||||
}
|
||||
}
|
||||
values := integrationbiz.DefaultIntegrationConfig(integrationbiz.IntegrationKindMQ, "kafka")
|
||||
values["brokers"] = brokers
|
||||
values["client_id"] = fmt.Sprintf("kra-connectivity-%d", time.Now().UnixNano())
|
||||
values["group_id"] = fmt.Sprintf("kra-connectivity-%d", time.Now().UnixNano())
|
||||
testMQConnectivityIntegration(t, "kafka", values)
|
||||
}
|
||||
|
||||
func TestEMQXConnectivityIntegration(t *testing.T) {
|
||||
broker := strings.TrimSpace(os.Getenv("KRA_EMQX_TEST_BROKER"))
|
||||
if broker == "" {
|
||||
t.Skip("KRA_EMQX_TEST_BROKER is not configured")
|
||||
}
|
||||
values := integrationbiz.DefaultIntegrationConfig(integrationbiz.IntegrationKindMQ, "emqx")
|
||||
values["broker"] = broker
|
||||
values["client_id"] = fmt.Sprintf("kra-connectivity-%d", time.Now().UnixNano())
|
||||
testMQConnectivityIntegration(t, "emqx", values)
|
||||
}
|
||||
|
||||
func TestRabbitMQConnectivityIntegration(t *testing.T) {
|
||||
address := strings.TrimSpace(os.Getenv("KRA_RABBITMQ_TEST_ADDR"))
|
||||
if address == "" {
|
||||
t.Skip("KRA_RABBITMQ_TEST_ADDR is not configured")
|
||||
}
|
||||
host, portText, err := net.SplitHostPort(address)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
port, err := strconv.Atoi(portText)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
values := integrationbiz.DefaultIntegrationConfig(integrationbiz.IntegrationKindMQ, "rabbitmq")
|
||||
values["host"] = host
|
||||
values["port"] = port
|
||||
testMQConnectivityIntegration(t, "rabbitmq", values)
|
||||
}
|
||||
|
||||
func testMQConnectivityIntegration(t *testing.T, provider string, values map[string]any) {
|
||||
t.Helper()
|
||||
raw, err := json.Marshal(values)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
usecase := integrationbiz.NewIntegrationConfigUsecase(&kafkaConnectivityRepo{}, NewConnectivityTester(nil))
|
||||
if err = usecase.Test(context.Background(), &integrationbiz.IntegrationConfig{
|
||||
Kind: integrationbiz.IntegrationKindMQ,
|
||||
Provider: provider,
|
||||
Values: raw,
|
||||
}); err != nil {
|
||||
t.Fatalf("test JSON-decoded %s defaults: %v", provider, err)
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,17 @@ func TestConnectivityTesterRestoreMaskedSecrets(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("keeps an empty optional secret", func(t *testing.T) {
|
||||
values := map[string]any{"password": ""}
|
||||
|
||||
if err := tester.restoreMaskedSecrets("mq", "kafka", values); err != nil {
|
||||
t.Fatalf("restoreMaskedSecrets() error = %v", err)
|
||||
}
|
||||
if got := values["password"]; got != "" {
|
||||
t.Fatalf("password = %q, want empty value", got)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("does not treat non-secret fields as masked secrets", func(t *testing.T) {
|
||||
values := map[string]any{
|
||||
"username": "******",
|
||||
|
||||
@@ -279,7 +279,13 @@ func configStrings(values map[string]any, key string) []string {
|
||||
}
|
||||
stringsValue, ok := values[key].([]string)
|
||||
if ok {
|
||||
return append([]string(nil), stringsValue...)
|
||||
result := make([]string, 0, len(stringsValue))
|
||||
for _, item := range stringsValue {
|
||||
if value := strings.TrimSpace(item); value != "" {
|
||||
result = append(result, value)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -327,6 +333,9 @@ func (r *Reloadable) retryOnce() {
|
||||
client := r.clientLocked(provider)
|
||||
if client != nil && client.Connected() {
|
||||
if r.pending[provider] {
|
||||
if retryAt := r.nextRetry[provider]; !retryAt.IsZero() && now.Before(retryAt) {
|
||||
continue
|
||||
}
|
||||
if err := r.reconcileProviderLocked(provider); err != nil {
|
||||
r.scheduleRetryLocked(provider, config.Values)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"log/slog"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -209,3 +210,69 @@ func TestReloadableLegacySubscribeDoesNotLeaveOfflineDeclaration(t *testing.T) {
|
||||
t.Fatalf("offline legacy declaration remained: %#v", r.subscriptions[ProviderEMQX])
|
||||
}
|
||||
}
|
||||
|
||||
func TestReloadableExposesKafkaNamedClient(t *testing.T) {
|
||||
r := &Reloadable{}
|
||||
client := r.Client(" KAFKA ")
|
||||
if client == nil {
|
||||
t.Fatal("kafka named client is nil")
|
||||
}
|
||||
if client.Connected() {
|
||||
t.Fatal("unconfigured kafka named client reported connected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigStringsDecodesJSONArrays(t *testing.T) {
|
||||
values := map[string]any{"brokers": []any{" kafka-1:9092 ", "", "kafka-2:9092"}}
|
||||
brokers := configStrings(values, "brokers")
|
||||
if len(brokers) != 2 || brokers[0] != "kafka-1:9092" || brokers[1] != "kafka-2:9092" {
|
||||
t.Fatalf("brokers = %#v", brokers)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigStringsNormalizesTypedSlices(t *testing.T) {
|
||||
values := map[string]any{"brokers": []string{" kafka-1:9092 ", "", "kafka-2:9092"}}
|
||||
brokers := configStrings(values, "brokers")
|
||||
if len(brokers) != 2 || brokers[0] != "kafka-1:9092" || brokers[1] != "kafka-2:9092" {
|
||||
t.Fatalf("brokers = %#v", brokers)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReloadableRejectsUnsupportedKafkaQoS(t *testing.T) {
|
||||
r := &Reloadable{}
|
||||
err := r.Register(platformmq.SubscriptionSet{
|
||||
Owner: "orders",
|
||||
Provider: ProviderKafka,
|
||||
Topics: []platformmq.TopicSubscription{{Topic: "orders.created", QoS: platformmq.ExactlyOnce, Handler: func(context.Context, platformmq.Message) {}}},
|
||||
})
|
||||
if err == nil || !strings.Contains(err.Error(), "supports qos 0 or 1") {
|
||||
t.Fatalf("Register() error = %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRetryOnceHonorsPendingSubscriptionDeadline(t *testing.T) {
|
||||
client := &fakeClient{}
|
||||
r := &Reloadable{
|
||||
clients: map[string]platformmq.Client{ProviderKafka: client},
|
||||
configs: map[string]runtimeconfig.Config{
|
||||
ProviderKafka: {Kind: "mq", Provider: ProviderKafka, Enabled: true},
|
||||
},
|
||||
subscriptions: map[string]map[string]map[string]subscription{
|
||||
ProviderKafka: {
|
||||
"orders.created": {"orders": {qos: platformmq.AtLeastOnce, handler: func(context.Context, platformmq.Message) {}}},
|
||||
},
|
||||
},
|
||||
bindings: map[string]map[string]byte{ProviderKafka: {}},
|
||||
pending: map[string]bool{ProviderKafka: true},
|
||||
nextRetry: map[string]time.Time{ProviderKafka: time.Now().Add(time.Minute)},
|
||||
}
|
||||
r.retryOnce()
|
||||
if len(client.subscribed) != 0 {
|
||||
t.Fatalf("subscription retried before deadline: %v", client.subscribed)
|
||||
}
|
||||
r.nextRetry[ProviderKafka] = time.Now().Add(-time.Second)
|
||||
r.retryOnce()
|
||||
if len(client.subscribed) != 1 || client.subscribed[0] != "orders.created" {
|
||||
t.Fatalf("subscription was not retried after deadline: %v", client.subscribed)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user