mirror of
https://github.com/lukaszraczylo/kportal.git
synced 2026-07-10 06:52:00 +00:00
Add aliases and conversion from the kftray.
This commit is contained in:
@@ -12,12 +12,14 @@ contexts:
|
|||||||
protocol: tcp
|
protocol: tcp
|
||||||
port: 8080
|
port: 8080
|
||||||
localPort: 8080
|
localPort: 8080
|
||||||
|
alias: prod-api
|
||||||
|
|
||||||
# Forward to PostgreSQL database
|
# Forward to PostgreSQL database
|
||||||
- resource: service/postgres
|
- resource: service/postgres
|
||||||
protocol: tcp
|
protocol: tcp
|
||||||
port: 5432
|
port: 5432
|
||||||
localPort: 5432
|
localPort: 5432
|
||||||
|
alias: prod-db
|
||||||
|
|
||||||
- name: monitoring
|
- name: monitoring
|
||||||
forwards:
|
forwards:
|
||||||
@@ -27,6 +29,7 @@ contexts:
|
|||||||
protocol: tcp
|
protocol: tcp
|
||||||
port: 9090
|
port: 9090
|
||||||
localPort: 9090
|
localPort: 9090
|
||||||
|
alias: prometheus
|
||||||
|
|
||||||
# Staging context
|
# Staging context
|
||||||
- name: staging
|
- name: staging
|
||||||
@@ -38,9 +41,11 @@ contexts:
|
|||||||
protocol: tcp
|
protocol: tcp
|
||||||
port: 8080
|
port: 8080
|
||||||
localPort: 8081
|
localPort: 8081
|
||||||
|
alias: staging-http
|
||||||
|
|
||||||
# Forward multiple ports from same pod
|
# Forward multiple ports from same pod
|
||||||
- resource: pod/myapp
|
- resource: pod/myapp
|
||||||
protocol: tcp
|
protocol: tcp
|
||||||
port: 9090
|
port: 9090
|
||||||
localPort: 9091
|
localPort: 9091
|
||||||
|
alias: staging-metrics
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ go build -o kportal ./cmd/kportal
|
|||||||
|
|
||||||
# Validate configuration without starting
|
# Validate configuration without starting
|
||||||
./kportal --check
|
./kportal --check
|
||||||
|
|
||||||
|
# Convert kftray JSON config to kportal YAML
|
||||||
|
./kportal --convert configs.json --convert-output .kportal.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
### Configuration File
|
### Configuration File
|
||||||
@@ -65,12 +68,14 @@ contexts:
|
|||||||
protocol: tcp
|
protocol: tcp
|
||||||
port: 8080
|
port: 8080
|
||||||
localPort: 8080
|
localPort: 8080
|
||||||
|
alias: my-api # Optional: cleaner log output
|
||||||
|
|
||||||
# Service forwarding
|
# Service forwarding with alias
|
||||||
- resource: service/postgres
|
- resource: service/postgres
|
||||||
protocol: tcp
|
protocol: tcp
|
||||||
port: 5432
|
port: 5432
|
||||||
localPort: 5432
|
localPort: 5432
|
||||||
|
alias: prod-db
|
||||||
|
|
||||||
- name: monitoring
|
- name: monitoring
|
||||||
forwards:
|
forwards:
|
||||||
@@ -80,6 +85,7 @@ contexts:
|
|||||||
protocol: tcp
|
protocol: tcp
|
||||||
port: 9090
|
port: 9090
|
||||||
localPort: 9090
|
localPort: 9090
|
||||||
|
alias: prometheus
|
||||||
|
|
||||||
- name: staging
|
- name: staging
|
||||||
namespaces:
|
namespaces:
|
||||||
@@ -89,10 +95,12 @@ contexts:
|
|||||||
- resource: pod/test-app
|
- resource: pod/test-app
|
||||||
port: 8080
|
port: 8080
|
||||||
localPort: 8081
|
localPort: 8081
|
||||||
|
alias: test-http
|
||||||
|
|
||||||
- resource: pod/test-app
|
- resource: pod/test-app
|
||||||
port: 9090
|
port: 9090
|
||||||
localPort: 9091
|
localPort: 9091
|
||||||
|
alias: test-metrics
|
||||||
```
|
```
|
||||||
|
|
||||||
### Resource Types
|
### Resource Types
|
||||||
@@ -122,6 +130,72 @@ Dynamically selects pods matching the label selector.
|
|||||||
```
|
```
|
||||||
Most stable option - forwards to service endpoints.
|
Most stable option - forwards to service endpoints.
|
||||||
|
|
||||||
|
#### Using Aliases
|
||||||
|
|
||||||
|
Aliases provide cleaner, more readable log output:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- resource: service/victoria-metrics-cluster-vmselect
|
||||||
|
port: 8481
|
||||||
|
localPort: 8481
|
||||||
|
alias: vmetrics # Shows "vmetrics:8481→8481" instead of full path
|
||||||
|
```
|
||||||
|
|
||||||
|
**Without alias:**
|
||||||
|
```
|
||||||
|
[home/monitoring/service/victoria-metrics-cluster-vmselect:8481] Forwarding...
|
||||||
|
```
|
||||||
|
|
||||||
|
**With alias:**
|
||||||
|
```
|
||||||
|
[vmetrics:8481] Forwarding vmetrics:8481→8481 → localhost:8481
|
||||||
|
```
|
||||||
|
|
||||||
|
### Converting from kftray
|
||||||
|
|
||||||
|
kportal can automatically convert kftray JSON configurations to kportal YAML format:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Convert kftray config
|
||||||
|
kportal --convert kftray-config.json --convert-output .kportal.yaml
|
||||||
|
|
||||||
|
# The converter will:
|
||||||
|
# 1. Read the kftray JSON format
|
||||||
|
# 2. Group forwards by context and namespace
|
||||||
|
# 3. Generate kportal YAML with all aliases preserved
|
||||||
|
# 4. Display a summary of the conversion
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example kftray JSON:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"service": "postgres",
|
||||||
|
"namespace": "default",
|
||||||
|
"local_port": 5432,
|
||||||
|
"remote_port": 5432,
|
||||||
|
"context": "production",
|
||||||
|
"workload_type": "service",
|
||||||
|
"protocol": "tcp",
|
||||||
|
"alias": "prod-db"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Converts to kportal YAML:**
|
||||||
|
```yaml
|
||||||
|
contexts:
|
||||||
|
- name: production
|
||||||
|
namespaces:
|
||||||
|
- name: default
|
||||||
|
forwards:
|
||||||
|
- resource: service/postgres
|
||||||
|
protocol: tcp
|
||||||
|
port: 5432
|
||||||
|
localPort: 5432
|
||||||
|
alias: prod-db
|
||||||
|
```
|
||||||
|
|
||||||
## How It Works
|
## How It Works
|
||||||
|
|
||||||
### Pod Restart Handling
|
### Pod Restart Handling
|
||||||
|
|||||||
@@ -26,11 +26,12 @@ type Namespace struct {
|
|||||||
|
|
||||||
// Forward represents a single port-forward configuration
|
// Forward represents a single port-forward configuration
|
||||||
type Forward struct {
|
type Forward struct {
|
||||||
Resource string `yaml:"resource"` // e.g., "pod/my-app", "service/postgres", "pod"
|
Resource string `yaml:"resource"` // e.g., "pod/my-app", "service/postgres", "pod"
|
||||||
Selector string `yaml:"selector"` // Label selector for pod resolution (e.g., "app=nginx,env=prod")
|
Selector string `yaml:"selector"` // Label selector for pod resolution (e.g., "app=nginx,env=prod")
|
||||||
Protocol string `yaml:"protocol"` // tcp or udp
|
Protocol string `yaml:"protocol"` // tcp or udp
|
||||||
Port int `yaml:"port"` // Remote port
|
Port int `yaml:"port"` // Remote port
|
||||||
LocalPort int `yaml:"localPort"` // Local port
|
LocalPort int `yaml:"localPort"` // Local port
|
||||||
|
Alias string `yaml:"alias,omitempty"` // Optional human-readable alias for this forward
|
||||||
|
|
||||||
// Runtime fields (not in YAML)
|
// Runtime fields (not in YAML)
|
||||||
contextName string
|
contextName string
|
||||||
@@ -38,14 +39,20 @@ type Forward struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ID returns a unique identifier for this forward configuration.
|
// ID returns a unique identifier for this forward configuration.
|
||||||
// Format: context/namespace/resource:localPort
|
// Format: alias:localPort (if alias provided) or context/namespace/resource:localPort
|
||||||
func (f *Forward) ID() string {
|
func (f *Forward) ID() string {
|
||||||
|
if f.Alias != "" {
|
||||||
|
return fmt.Sprintf("%s:%d", f.Alias, f.LocalPort)
|
||||||
|
}
|
||||||
return fmt.Sprintf("%s/%s/%s:%d", f.contextName, f.namespaceName, f.Resource, f.LocalPort)
|
return fmt.Sprintf("%s/%s/%s:%d", f.contextName, f.namespaceName, f.Resource, f.LocalPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a human-readable representation of the forward.
|
// String returns a human-readable representation of the forward.
|
||||||
// Format: context/namespace/resource:port→localPort
|
// Format: alias:port→localPort (if alias provided) or context/namespace/resource:port→localPort
|
||||||
func (f *Forward) String() string {
|
func (f *Forward) String() string {
|
||||||
|
if f.Alias != "" {
|
||||||
|
return fmt.Sprintf("%s:%d→%d", f.Alias, f.Port, f.LocalPort)
|
||||||
|
}
|
||||||
if f.Selector != "" {
|
if f.Selector != "" {
|
||||||
return fmt.Sprintf("%s/%s/%s[%s]:%d→%d",
|
return fmt.Sprintf("%s/%s/%s[%s]:%d→%d",
|
||||||
f.contextName, f.namespaceName, f.Resource, f.Selector, f.Port, f.LocalPort)
|
f.contextName, f.namespaceName, f.Resource, f.Selector, f.Port, f.LocalPort)
|
||||||
|
|||||||
@@ -140,6 +140,18 @@ func TestForward_ID(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expectedID: "staging/web/pod:8081",
|
expectedID: "staging/web/pod:8081",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "forward with alias",
|
||||||
|
forward: Forward{
|
||||||
|
Resource: "service/postgres",
|
||||||
|
Port: 5432,
|
||||||
|
LocalPort: 5432,
|
||||||
|
Alias: "shared-postgres",
|
||||||
|
contextName: "home",
|
||||||
|
namespaceName: "shared-resources",
|
||||||
|
},
|
||||||
|
expectedID: "shared-postgres:5432",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@@ -190,6 +202,18 @@ func TestForward_String(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expectedString: "staging/web/pod[app=nginx,env=prod]:80→8081",
|
expectedString: "staging/web/pod[app=nginx,env=prod]:80→8081",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "forward with alias",
|
||||||
|
forward: Forward{
|
||||||
|
Resource: "service/redis",
|
||||||
|
Port: 6379,
|
||||||
|
LocalPort: 6379,
|
||||||
|
Alias: "redis-at-home",
|
||||||
|
contextName: "home",
|
||||||
|
namespaceName: "shared-resources",
|
||||||
|
},
|
||||||
|
expectedString: "redis-at-home:6379→6379",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|||||||
@@ -0,0 +1,202 @@
|
|||||||
|
package converter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/nvm/kportal/internal/config"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
// KFTrayConfig represents a single port-forward entry from kftray JSON format
|
||||||
|
type KFTrayConfig struct {
|
||||||
|
Service string `json:"service"`
|
||||||
|
Namespace string `json:"namespace"`
|
||||||
|
LocalPort int `json:"local_port"`
|
||||||
|
RemotePort int `json:"remote_port"`
|
||||||
|
Context string `json:"context"`
|
||||||
|
WorkloadType string `json:"workload_type"`
|
||||||
|
Protocol string `json:"protocol"`
|
||||||
|
Alias string `json:"alias"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConvertKFTrayToKPortal converts kftray JSON configuration to kportal YAML format
|
||||||
|
func ConvertKFTrayToKPortal(inputFile, outputFile string) error {
|
||||||
|
// Read kftray JSON config
|
||||||
|
data, err := os.ReadFile(inputFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to read input file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var kftrayConfigs []KFTrayConfig
|
||||||
|
if err := json.Unmarshal(data, &kftrayConfigs); err != nil {
|
||||||
|
return fmt.Errorf("failed to parse JSON: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to kportal format
|
||||||
|
kportalConfig := convertToKPortal(kftrayConfigs)
|
||||||
|
|
||||||
|
// Write kportal YAML config
|
||||||
|
yamlData, err := yaml.Marshal(kportalConfig)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to generate YAML: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add header comment
|
||||||
|
header := "# kportal configuration converted from kftray format\n# Generated by kportal --convert\n\n"
|
||||||
|
yamlData = append([]byte(header), yamlData...)
|
||||||
|
|
||||||
|
if err := os.WriteFile(outputFile, yamlData, 0644); err != nil {
|
||||||
|
return fmt.Errorf("failed to write output file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetConversionSummary returns statistics about the kftray configuration
|
||||||
|
func GetConversionSummary(inputFile string) (map[string]map[string]int, int, error) {
|
||||||
|
data, err := os.ReadFile(inputFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, fmt.Errorf("failed to read input file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var kftrayConfigs []KFTrayConfig
|
||||||
|
if err := json.Unmarshal(data, &kftrayConfigs); err != nil {
|
||||||
|
return nil, 0, fmt.Errorf("failed to parse JSON: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
contextMap := make(map[string]map[string]int)
|
||||||
|
for _, cfg := range kftrayConfigs {
|
||||||
|
if _, ok := contextMap[cfg.Context]; !ok {
|
||||||
|
contextMap[cfg.Context] = make(map[string]int)
|
||||||
|
}
|
||||||
|
contextMap[cfg.Context][cfg.Namespace]++
|
||||||
|
}
|
||||||
|
|
||||||
|
return contextMap, len(kftrayConfigs), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertToKPortal(kftrayConfigs []KFTrayConfig) config.Config {
|
||||||
|
// Group by context and namespace
|
||||||
|
contextMap := make(map[string]map[string][]forwardEntry)
|
||||||
|
|
||||||
|
for _, cfg := range kftrayConfigs {
|
||||||
|
// Initialize context if not exists
|
||||||
|
if _, ok := contextMap[cfg.Context]; !ok {
|
||||||
|
contextMap[cfg.Context] = make(map[string][]forwardEntry)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build resource string based on workload type
|
||||||
|
resource := fmt.Sprintf("%s/%s", cfg.WorkloadType, cfg.Service)
|
||||||
|
|
||||||
|
// Create forward entry
|
||||||
|
forward := forwardEntry{
|
||||||
|
Resource: resource,
|
||||||
|
Protocol: cfg.Protocol,
|
||||||
|
Port: cfg.RemotePort,
|
||||||
|
LocalPort: cfg.LocalPort,
|
||||||
|
Alias: cfg.Alias,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to namespace
|
||||||
|
contextMap[cfg.Context][cfg.Namespace] = append(
|
||||||
|
contextMap[cfg.Context][cfg.Namespace],
|
||||||
|
forward,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert map to structured config
|
||||||
|
var contexts []contextEntry
|
||||||
|
|
||||||
|
// Sort contexts for consistent output
|
||||||
|
contextNames := make([]string, 0, len(contextMap))
|
||||||
|
for name := range contextMap {
|
||||||
|
contextNames = append(contextNames, name)
|
||||||
|
}
|
||||||
|
sort.Strings(contextNames)
|
||||||
|
|
||||||
|
for _, contextName := range contextNames {
|
||||||
|
namespaceMap := contextMap[contextName]
|
||||||
|
|
||||||
|
// Sort namespaces
|
||||||
|
namespaceNames := make([]string, 0, len(namespaceMap))
|
||||||
|
for name := range namespaceMap {
|
||||||
|
namespaceNames = append(namespaceNames, name)
|
||||||
|
}
|
||||||
|
sort.Strings(namespaceNames)
|
||||||
|
|
||||||
|
var namespaces []namespaceEntry
|
||||||
|
for _, namespaceName := range namespaceNames {
|
||||||
|
forwards := namespaceMap[namespaceName]
|
||||||
|
|
||||||
|
// Sort forwards by local port for consistent output
|
||||||
|
sort.Slice(forwards, func(i, j int) bool {
|
||||||
|
return forwards[i].LocalPort < forwards[j].LocalPort
|
||||||
|
})
|
||||||
|
|
||||||
|
namespaces = append(namespaces, namespaceEntry{
|
||||||
|
Name: namespaceName,
|
||||||
|
Forwards: forwards,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
contexts = append(contexts, contextEntry{
|
||||||
|
Name: contextName,
|
||||||
|
Namespaces: namespaces,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return config.Config{
|
||||||
|
Contexts: convertToConfigContexts(contexts),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal types for conversion (to avoid circular dependencies)
|
||||||
|
type contextEntry struct {
|
||||||
|
Name string
|
||||||
|
Namespaces []namespaceEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
type namespaceEntry struct {
|
||||||
|
Name string
|
||||||
|
Forwards []forwardEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
type forwardEntry struct {
|
||||||
|
Resource string `yaml:"resource"`
|
||||||
|
Protocol string `yaml:"protocol"`
|
||||||
|
Port int `yaml:"port"`
|
||||||
|
LocalPort int `yaml:"localPort"`
|
||||||
|
Alias string `yaml:"alias,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert internal types to config package types
|
||||||
|
func convertToConfigContexts(contexts []contextEntry) []config.Context {
|
||||||
|
var result []config.Context
|
||||||
|
for _, ctx := range contexts {
|
||||||
|
var namespaces []config.Namespace
|
||||||
|
for _, ns := range ctx.Namespaces {
|
||||||
|
var forwards []config.Forward
|
||||||
|
for _, fwd := range ns.Forwards {
|
||||||
|
forwards = append(forwards, config.Forward{
|
||||||
|
Resource: fwd.Resource,
|
||||||
|
Protocol: fwd.Protocol,
|
||||||
|
Port: fwd.Port,
|
||||||
|
LocalPort: fwd.LocalPort,
|
||||||
|
Alias: fwd.Alias,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
namespaces = append(namespaces, config.Namespace{
|
||||||
|
Name: ns.Name,
|
||||||
|
Forwards: forwards,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
result = append(result, config.Context{
|
||||||
|
Name: ctx.Name,
|
||||||
|
Namespaces: namespaces,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -0,0 +1,212 @@
|
|||||||
|
package converter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConvertToKPortal_SingleContext(t *testing.T) {
|
||||||
|
kftrayConfigs := []KFTrayConfig{
|
||||||
|
{
|
||||||
|
Service: "postgres",
|
||||||
|
Namespace: "default",
|
||||||
|
LocalPort: 5432,
|
||||||
|
RemotePort: 5432,
|
||||||
|
Context: "production",
|
||||||
|
WorkloadType: "service",
|
||||||
|
Protocol: "tcp",
|
||||||
|
Alias: "prod-db",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
result := convertToKPortal(kftrayConfigs)
|
||||||
|
|
||||||
|
assert.Len(t, result.Contexts, 1)
|
||||||
|
assert.Equal(t, "production", result.Contexts[0].Name)
|
||||||
|
assert.Len(t, result.Contexts[0].Namespaces, 1)
|
||||||
|
assert.Equal(t, "default", result.Contexts[0].Namespaces[0].Name)
|
||||||
|
assert.Len(t, result.Contexts[0].Namespaces[0].Forwards, 1)
|
||||||
|
|
||||||
|
forward := result.Contexts[0].Namespaces[0].Forwards[0]
|
||||||
|
assert.Equal(t, "service/postgres", forward.Resource)
|
||||||
|
assert.Equal(t, "tcp", forward.Protocol)
|
||||||
|
assert.Equal(t, 5432, forward.Port)
|
||||||
|
assert.Equal(t, 5432, forward.LocalPort)
|
||||||
|
assert.Equal(t, "prod-db", forward.Alias)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConvertToKPortal_MultipleContexts(t *testing.T) {
|
||||||
|
kftrayConfigs := []KFTrayConfig{
|
||||||
|
{
|
||||||
|
Service: "api",
|
||||||
|
Namespace: "default",
|
||||||
|
LocalPort: 8080,
|
||||||
|
RemotePort: 8080,
|
||||||
|
Context: "production",
|
||||||
|
WorkloadType: "service",
|
||||||
|
Protocol: "tcp",
|
||||||
|
Alias: "prod-api",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Service: "api",
|
||||||
|
Namespace: "default",
|
||||||
|
LocalPort: 8081,
|
||||||
|
RemotePort: 8080,
|
||||||
|
Context: "staging",
|
||||||
|
WorkloadType: "service",
|
||||||
|
Protocol: "tcp",
|
||||||
|
Alias: "staging-api",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
result := convertToKPortal(kftrayConfigs)
|
||||||
|
|
||||||
|
assert.Len(t, result.Contexts, 2)
|
||||||
|
|
||||||
|
// Contexts should be sorted alphabetically
|
||||||
|
assert.Equal(t, "production", result.Contexts[0].Name)
|
||||||
|
assert.Equal(t, "staging", result.Contexts[1].Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConvertToKPortal_MultipleNamespaces(t *testing.T) {
|
||||||
|
kftrayConfigs := []KFTrayConfig{
|
||||||
|
{
|
||||||
|
Service: "api",
|
||||||
|
Namespace: "default",
|
||||||
|
LocalPort: 8080,
|
||||||
|
RemotePort: 8080,
|
||||||
|
Context: "production",
|
||||||
|
WorkloadType: "service",
|
||||||
|
Protocol: "tcp",
|
||||||
|
Alias: "api",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Service: "postgres",
|
||||||
|
Namespace: "database",
|
||||||
|
LocalPort: 5432,
|
||||||
|
RemotePort: 5432,
|
||||||
|
Context: "production",
|
||||||
|
WorkloadType: "service",
|
||||||
|
Protocol: "tcp",
|
||||||
|
Alias: "db",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
result := convertToKPortal(kftrayConfigs)
|
||||||
|
|
||||||
|
assert.Len(t, result.Contexts, 1)
|
||||||
|
assert.Len(t, result.Contexts[0].Namespaces, 2)
|
||||||
|
|
||||||
|
// Namespaces should be sorted alphabetically
|
||||||
|
assert.Equal(t, "database", result.Contexts[0].Namespaces[0].Name)
|
||||||
|
assert.Equal(t, "default", result.Contexts[0].Namespaces[1].Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConvertToKPortal_MultipleForwardsInNamespace(t *testing.T) {
|
||||||
|
kftrayConfigs := []KFTrayConfig{
|
||||||
|
{
|
||||||
|
Service: "api",
|
||||||
|
Namespace: "default",
|
||||||
|
LocalPort: 8080,
|
||||||
|
RemotePort: 8080,
|
||||||
|
Context: "production",
|
||||||
|
WorkloadType: "service",
|
||||||
|
Protocol: "tcp",
|
||||||
|
Alias: "api",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Service: "postgres",
|
||||||
|
Namespace: "default",
|
||||||
|
LocalPort: 5432,
|
||||||
|
RemotePort: 5432,
|
||||||
|
Context: "production",
|
||||||
|
WorkloadType: "service",
|
||||||
|
Protocol: "tcp",
|
||||||
|
Alias: "db",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Service: "redis",
|
||||||
|
Namespace: "default",
|
||||||
|
LocalPort: 6379,
|
||||||
|
RemotePort: 6379,
|
||||||
|
Context: "production",
|
||||||
|
WorkloadType: "service",
|
||||||
|
Protocol: "tcp",
|
||||||
|
Alias: "redis",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
result := convertToKPortal(kftrayConfigs)
|
||||||
|
|
||||||
|
assert.Len(t, result.Contexts, 1)
|
||||||
|
assert.Len(t, result.Contexts[0].Namespaces, 1)
|
||||||
|
assert.Len(t, result.Contexts[0].Namespaces[0].Forwards, 3)
|
||||||
|
|
||||||
|
// Forwards should be sorted by local port
|
||||||
|
forwards := result.Contexts[0].Namespaces[0].Forwards
|
||||||
|
assert.Equal(t, 5432, forwards[0].LocalPort) // postgres
|
||||||
|
assert.Equal(t, 6379, forwards[1].LocalPort) // redis
|
||||||
|
assert.Equal(t, 8080, forwards[2].LocalPort) // api
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConvertToKPortal_PodWorkloadType(t *testing.T) {
|
||||||
|
kftrayConfigs := []KFTrayConfig{
|
||||||
|
{
|
||||||
|
Service: "my-app",
|
||||||
|
Namespace: "default",
|
||||||
|
LocalPort: 8080,
|
||||||
|
RemotePort: 8080,
|
||||||
|
Context: "production",
|
||||||
|
WorkloadType: "pod",
|
||||||
|
Protocol: "tcp",
|
||||||
|
Alias: "app",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
result := convertToKPortal(kftrayConfigs)
|
||||||
|
|
||||||
|
forward := result.Contexts[0].Namespaces[0].Forwards[0]
|
||||||
|
assert.Equal(t, "pod/my-app", forward.Resource)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConvertToKPortal_WithoutAlias(t *testing.T) {
|
||||||
|
kftrayConfigs := []KFTrayConfig{
|
||||||
|
{
|
||||||
|
Service: "postgres",
|
||||||
|
Namespace: "default",
|
||||||
|
LocalPort: 5432,
|
||||||
|
RemotePort: 5432,
|
||||||
|
Context: "production",
|
||||||
|
WorkloadType: "service",
|
||||||
|
Protocol: "tcp",
|
||||||
|
Alias: "", // No alias
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
result := convertToKPortal(kftrayConfigs)
|
||||||
|
|
||||||
|
forward := result.Contexts[0].Namespaces[0].Forwards[0]
|
||||||
|
assert.Equal(t, "", forward.Alias)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConvertToKPortal_DifferentPorts(t *testing.T) {
|
||||||
|
kftrayConfigs := []KFTrayConfig{
|
||||||
|
{
|
||||||
|
Service: "api",
|
||||||
|
Namespace: "default",
|
||||||
|
LocalPort: 8080,
|
||||||
|
RemotePort: 3000,
|
||||||
|
Context: "production",
|
||||||
|
WorkloadType: "service",
|
||||||
|
Protocol: "tcp",
|
||||||
|
Alias: "api",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
result := convertToKPortal(kftrayConfigs)
|
||||||
|
|
||||||
|
forward := result.Contexts[0].Namespaces[0].Forwards[0]
|
||||||
|
assert.Equal(t, 3000, forward.Port, "Remote port should be 3000")
|
||||||
|
assert.Equal(t, 8080, forward.LocalPort, "Local port should be 8080")
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user