edge-connect-client/internal/infrastructure/config/example_test.go
Stephan Lo 7b062612f5 refactor(arch): Separate infrastructure from driven adapter
This commit introduces a significant architectural refactoring to decouple the driven adapter from low-level infrastructure concerns, adhering more strictly to the principles of Hexagonal Architecture.

Problem:
The driven adapter in `internal/adapters/driven/edgeconnect` was responsible for both adapting data structures and handling direct HTTP communication, authentication, and request/response logic. This violated the separation of concerns, making the adapter difficult to test and maintain.

Solution:
A new infrastructure layer has been created at `internal/infrastructure`. This layer now contains all the low-level details of interacting with the EdgeConnect API.

Key Changes:
- **New Infrastructure Layer:** Created `internal/infrastructure` to house components that connect to external systems.
- **Generic HTTP Client:** A new, generic `edgeconnect_client` was created in `internal/infrastructure/edgeconnect_client`. It is responsible for authentication, making HTTP requests, and handling raw responses. It has no knowledge of the application's domain models.
- **Config & Transport Moved:** The `config` and `http` (now `transport`) packages were moved into the infrastructure layer, as they are details of how the application is configured and communicates.
- **Consolidated Driven Adapter:** The logic from the numerous old adapter files (`apps.go`, `cloudlet.go`, etc.) has been consolidated into a single, true adapter at `internal/adapters/driven/edgeconnect/adapter.go`.
- **Clear Responsibility:** The new `adapter.go` is now solely responsible for:
  1. Implementing the driven port (repository) interfaces.
  2. Translating domain models into the data structures required by the `edgeconnect_client`.
  3. Calling the `edgeconnect_client` to perform the API operations.
  4. Translating the results back into domain models.
- **Updated Dependency Injection:** The application's entry point (`cmd/cli/main.go`) has been updated to construct and inject dependencies according to the new architecture: `infra_client` -> `adapter` -> `service` -> `cli_command`.
- **SDK & Apply Command:** The SDK examples and the `apply` command have been updated to use the new adapter and its repository methods, removing all direct client instantiation.
2025-10-09 00:47:45 +02:00

101 lines
2.9 KiB
Go

// ABOUTME: Integration test with the actual EdgeConnectConfig.yaml example file
// ABOUTME: Validates that our parser correctly handles the real example configuration
package config
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestParseExampleConfig(t *testing.T) {
// The base path is relative to the location of this test file
parser := NewParser()
cfg, _, err := parser.ParseFile("../../../sdk/examples/comprehensive/EdgeConnectConfig.yaml")
require.NoError(t, err)
require.NotNil(t, cfg)
// Basic validation
assert.Equal(t, "edgeconnect-deployment", cfg.Kind)
assert.Equal(t, "edge-app-demo", cfg.Metadata.Name)
assert.NotNil(t, cfg.Spec.K8sApp)
assert.NotEmpty(t, cfg.Spec.K8sApp.ManifestFile)
// Check infrastructure template
require.Len(t, cfg.Spec.InfraTemplate, 1)
infra := cfg.Spec.InfraTemplate[0]
assert.Equal(t, "EU", infra.Region)
assert.Equal(t, "TelekomOP", infra.CloudletOrg)
assert.Equal(t, "Munich", infra.CloudletName)
assert.Equal(t, "EU.small", infra.FlavorName)
// Check network configuration
require.NotNil(t, cfg.Spec.Network)
require.Len(t, cfg.Spec.Network.OutboundConnections, 2)
conn1 := cfg.Spec.Network.OutboundConnections[0]
assert.Equal(t, "tcp", conn1.Protocol)
assert.Equal(t, 80, conn1.PortRangeMin)
assert.Equal(t, 80, conn1.PortRangeMax)
assert.Equal(t, "0.0.0.0/0", conn1.RemoteCIDR)
conn2 := cfg.Spec.Network.OutboundConnections[1]
assert.Equal(t, "tcp", conn2.Protocol)
assert.Equal(t, 443, conn2.PortRangeMin)
assert.Equal(t, 443, conn2.PortRangeMax)
assert.Equal(t, "0.0.0.0/0", conn2.RemoteCIDR)
// Test utility methods
assert.Equal(t, "edge-app-demo", cfg.Metadata.Name)
assert.Contains(t, cfg.Spec.GetManifestFile(), "k8s-deployment.yaml")
assert.True(t, cfg.Spec.IsK8sApp())
assert.False(t, cfg.Spec.IsDockerApp())
}
func TestValidateExampleStructure(t *testing.T) {
parser := &ConfigParser{}
// Create a config that matches the example but with valid paths
config := &EdgeConnectConfig{
Kind: "edgeconnect-deployment",
Metadata: Metadata{
Name: "edge-app-demo",
AppVersion: "1.0.0",
Organization: "edp2",
},
Spec: Spec{
DockerApp: &DockerApp{ // Use DockerApp to avoid manifest file validation
Image: "nginx:latest",
},
InfraTemplate: []InfraTemplate{
{
Region: "EU",
CloudletOrg: "TelekomOP",
CloudletName: "Munich",
FlavorName: "EU.small",
},
},
Network: &NetworkConfig{
OutboundConnections: []OutboundConnection{
{
Protocol: "tcp",
PortRangeMin: 80,
PortRangeMax: 80,
RemoteCIDR: "0.0.0.0/0",
},
{
Protocol: "tcp",
PortRangeMin: 443,
PortRangeMax: 443,
RemoteCIDR: "0.0.0.0/0",
},
},
},
},
}
// This should validate successfully
err := parser.Validate(config)
assert.NoError(t, err)
}