-
Notifications
You must be signed in to change notification settings - Fork 689
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5726 from emissary-ingress/flynn/v4-5715
v4 fixes for 5702 and 5714
- Loading branch information
Showing
15 changed files
with
818 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
package entrypoint | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
) | ||
|
||
type IRResource struct { | ||
Active bool `json:"_active"` | ||
CacheKey string `json:"_cache_key,omitempty"` | ||
Errored bool `json:"_errored"` | ||
ReferencedBy []string `json:"_referenced_by,omitempty"` | ||
RKey string `json:"_rkey,omitempty"` | ||
Location string `json:"location,omitempty"` | ||
Kind string `json:"kind"` | ||
Name string `json:"name"` | ||
Namespace string `json:"namespace,omitempty"` | ||
} | ||
|
||
type IRClusterHealthCheck struct { | ||
IRResource | ||
} | ||
|
||
type IRClusterTarget struct { | ||
IP string `json:"ip"` | ||
Port int `json:"port"` | ||
TargetKind string `json:"target_kind"` | ||
} | ||
|
||
type IRCluster struct { | ||
IRResource | ||
BarHostname string `json:"_hostname"` // Why this _and_ hostname? | ||
BarNamespace string `json:"_namespace"` // Why this _and_ namespace? | ||
Port int `json:"_port"` | ||
Resolver string `json:"_resolver"` | ||
ConnectTimeoutMs int `json:"connect_timeout_ms"` | ||
EnableEndpoints bool `json:"enable_endpoints"` | ||
EnableIPv4 bool `json:"enable_ipv4"` | ||
EnableIPv6 bool `json:"enable_ipv6"` | ||
EnvoyName string `json:"envoy_name"` | ||
HealthChecks IRClusterHealthCheck `json:"health_checks,omitempty"` | ||
IgnoreCluster bool `json:"ignore_cluster"` | ||
LBType string `json:"lb_type"` | ||
RespectDNSTTL bool `json:"respect_dns_ttl"` | ||
Service string `json:"service"` | ||
StatsName string `json:"stats_name"` | ||
Targets []IRClusterTarget `json:"targets"` | ||
Type string `json:"type"` | ||
URLs []string `json:"urls"` | ||
} | ||
|
||
type IRQueryParameter struct { | ||
Name string `json:"name,omitempty"` | ||
Value string `json:"value,omitempty"` | ||
Regex bool `json:"regex,omitempty"` | ||
} | ||
|
||
type IRRegexRewrite struct { | ||
Pattern string `json:"pattern,omitempty"` | ||
Substitution string `json:"substitution,omitempty"` | ||
} | ||
|
||
// Route weights are really annoying: in Python they're a | ||
// List[Union[str, int]], which is a pain to represent in Go. | ||
|
||
type IRRouteWeightElement struct { | ||
Int int | ||
Str string | ||
} | ||
|
||
type IRRouteWeight []IRRouteWeightElement | ||
|
||
func (rw IRRouteWeight) MarshalJSON() ([]byte, error) { | ||
arr := make([]interface{}, len(rw)) | ||
|
||
for i, elem := range rw { | ||
if elem.Str != "" { | ||
arr[i] = elem.Str | ||
} else { | ||
arr[i] = elem.Int | ||
} | ||
} | ||
|
||
return json.Marshal(arr) | ||
} | ||
|
||
func (rw *IRRouteWeight) UnmarshalJSON(data []byte) error { | ||
var arr []interface{} | ||
|
||
if err := json.Unmarshal(data, &arr); err != nil { | ||
return err | ||
} | ||
|
||
*rw = make([]IRRouteWeightElement, len(arr)) | ||
|
||
for i, elem := range arr { | ||
switch v := elem.(type) { | ||
case string: | ||
(*rw)[i] = IRRouteWeightElement{Str: v} | ||
case float64: | ||
(*rw)[i] = IRRouteWeightElement{Int: int(v)} | ||
default: | ||
return fmt.Errorf("unexpected type in IRRouteWeight: %T", elem) | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
type IRMapping struct { | ||
IRResource | ||
// CumulativeWeight is the _computed_ cumulative weight assigned to a | ||
// Mapping within its groups; Weight is the value specified in the | ||
// Mapping's spec.weight (it's a pointer because that value is optional). | ||
// | ||
// If you have mappings in a Group with weights 10, 40, and unset, the | ||
// Weights will be pointer-to-10, pointer-to-40, and nil, and the | ||
// CumulativeWeights will be 10, 50, and 100. | ||
CumulativeWeight int `json:"_weight"` | ||
Weight *int `json:"weight"` | ||
Cluster IRCluster `json:"cluster"` | ||
ClusterKey string `json:"cluster_key"` | ||
DefaultClass string `json:"default_class"` | ||
GroupID string `json:"group_id"` | ||
Headers []IRHeader `json:"headers"` | ||
Host string `json:"host"` | ||
Precedence int `json:"precedence"` | ||
Prefix string `json:"prefix"` | ||
QueryParameters []IRQueryParameter `json:"query_parameters,omitempty"` | ||
RegexRewrite IRRegexRewrite `json:"regex_rewrite,omitempty"` | ||
Resolver string `json:"resolver"` | ||
Rewrite string `json:"rewrite"` | ||
RouteWeight IRRouteWeight `json:"route_weight"` | ||
Service string `json:"service"` | ||
TimeoutMS int `json:"timeout_ms"` | ||
} | ||
|
||
type IRRequestPolicy struct { | ||
Action string `json:"action"` | ||
} | ||
|
||
type IRHost struct { | ||
IRResource | ||
Hostname string `json:"hostname"` | ||
InsecureAction string `json:"insecure_action"` | ||
RequestPolicy map[string]IRRequestPolicy `json:"requestPolicy"` // Yes, really. | ||
SecureAction string `json:"secure_action"` | ||
SNI string `json:"sni"` | ||
} | ||
|
||
type IRHeader struct { | ||
Name string `json:"name"` | ||
Regex bool `json:"regex"` | ||
Value string `json:"value"` | ||
} | ||
|
||
type IRGroup struct { | ||
IRResource | ||
DefaultClass string `json:"default_class"` | ||
GroupID string `json:"group_id"` | ||
GroupWeight IRRouteWeight `json:"group_weight"` | ||
Headers []IRHeader `json:"headers"` | ||
Host string `json:"host"` | ||
Mappings []IRMapping `json:"mappings"` | ||
Precedence int `json:"precedence"` | ||
Prefix string `json:"prefix"` | ||
QueryParameters []IRQueryParameter `json:"query_parameters"` | ||
RegexRewrite IRRegexRewrite `json:"regex_rewrite"` | ||
Rewrite string `json:"rewrite"` | ||
TimeoutMS int `json:"timeout_ms"` | ||
} | ||
|
||
type IR struct { | ||
Clusters map[string]IRCluster `json:"clusters"` | ||
Groups []IRGroup `json:"groups"` | ||
Hosts []IRHost `json:"hosts"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
package entrypoint_test | ||
|
||
import ( | ||
"encoding/json" | ||
"testing" | ||
|
||
"github.com/emissary-ingress/emissary/v3/cmd/entrypoint" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestIRRouteWeight(t *testing.T) { | ||
rw := entrypoint.IRRouteWeight{ | ||
{Int: 1}, | ||
{Str: "foo"}, | ||
{Int: 2}, | ||
} | ||
|
||
// MarshalJSON | ||
expectedJSON := `[1,"foo",2]` | ||
actualJSON, err := json.Marshal(rw) | ||
assert.Nil(t, err) | ||
assert.Equal(t, expectedJSON, string(actualJSON)) | ||
|
||
var check entrypoint.IRRouteWeight | ||
err = json.Unmarshal(actualJSON, &check) | ||
assert.Nil(t, err) | ||
assert.Equal(t, rw, check) | ||
|
||
// UnmarshalJSON | ||
jsonData := []byte(`[1,"bar",3]`) | ||
expectedRW := entrypoint.IRRouteWeight{ | ||
{Int: 1}, | ||
{Str: "bar"}, | ||
{Int: 3}, | ||
} | ||
var actualRW entrypoint.IRRouteWeight | ||
err = json.Unmarshal(jsonData, &actualRW) | ||
assert.Nil(t, err) | ||
assert.Equal(t, expectedRW, actualRW) | ||
} | ||
|
||
func TestIRCluster(t *testing.T) { | ||
clusterJSON := `{ | ||
"_active": true, | ||
"_cache_key": "Cluster-cluster_127_0_0_1_8877_default", | ||
"_errored": false, | ||
"_hostname": "127.0.0.1", | ||
"_namespace": "default", | ||
"_port": 8877, | ||
"_referenced_by": [ | ||
"--internal--" | ||
], | ||
"_resolver": "kubernetes-service", | ||
"_rkey": "cluster_127_0_0_1_8877_default", | ||
"connect_timeout_ms": 3000, | ||
"enable_endpoints": false, | ||
"enable_ipv4": true, | ||
"enable_ipv6": false, | ||
"envoy_name": "cluster_127_0_0_1_8877_default", | ||
"health_checks": { | ||
"_active": true, | ||
"_errored": false, | ||
"_rkey": "ir.health_checks", | ||
"kind": "IRHealthChecks", | ||
"location": "--internal--", | ||
"name": "health_checks", | ||
"namespace": "default" | ||
}, | ||
"ignore_cluster": false, | ||
"kind": "IRCluster", | ||
"lb_type": "round_robin", | ||
"location": "--internal--", | ||
"name": "cluster_127_0_0_1_8877_default", | ||
"namespace": "default", | ||
"respect_dns_ttl": false, | ||
"service": "127.0.0.1:8877", | ||
"stats_name": "127_0_0_1_8877", | ||
"targets": [ | ||
{ | ||
"ip": "127.0.0.1", | ||
"port": 8877, | ||
"target_kind": "IPaddr" | ||
} | ||
], | ||
"type": "strict_dns", | ||
"urls": [ | ||
"tcp://127.0.0.1:8877" | ||
] | ||
}` | ||
|
||
expectedCluster := entrypoint.IRCluster{ | ||
IRResource: entrypoint.IRResource{ | ||
Active: true, | ||
CacheKey: "Cluster-cluster_127_0_0_1_8877_default", | ||
Errored: false, | ||
ReferencedBy: []string{"--internal--"}, | ||
RKey: "cluster_127_0_0_1_8877_default", | ||
Location: "--internal--", | ||
Kind: "IRCluster", | ||
Name: "cluster_127_0_0_1_8877_default", | ||
Namespace: "default", | ||
}, | ||
BarHostname: "127.0.0.1", | ||
BarNamespace: "default", | ||
Port: 8877, | ||
Resolver: "kubernetes-service", | ||
ConnectTimeoutMs: 3000, | ||
EnableEndpoints: false, | ||
EnableIPv4: true, | ||
EnableIPv6: false, | ||
EnvoyName: "cluster_127_0_0_1_8877_default", | ||
HealthChecks: entrypoint.IRClusterHealthCheck{ | ||
IRResource: entrypoint.IRResource{ | ||
Active: true, | ||
Errored: false, | ||
RKey: "ir.health_checks", | ||
Kind: "IRHealthChecks", | ||
Location: "--internal--", | ||
Name: "health_checks", | ||
Namespace: "default", | ||
}, | ||
}, | ||
IgnoreCluster: false, | ||
LBType: "round_robin", | ||
RespectDNSTTL: false, | ||
Service: "127.0.0.1:8877", | ||
StatsName: "127_0_0_1_8877", | ||
Targets: []entrypoint.IRClusterTarget{ | ||
{ | ||
IP: "127.0.0.1", | ||
Port: 8877, | ||
TargetKind: "IPaddr", | ||
}, | ||
}, | ||
Type: "strict_dns", | ||
URLs: []string{ | ||
"tcp://127.0.0.1:8877", | ||
}, | ||
} | ||
|
||
var unmarshaledCluster entrypoint.IRCluster | ||
err := json.Unmarshal([]byte(clusterJSON), &unmarshaledCluster) | ||
assert.Nil(t, err) | ||
assert.Equal(t, expectedCluster, unmarshaledCluster) | ||
|
||
remarshaledJSON, err := json.Marshal(unmarshaledCluster) | ||
assert.Nil(t, err) | ||
|
||
var unmarshaledCluster2 entrypoint.IRCluster | ||
err = json.Unmarshal(remarshaledJSON, &unmarshaledCluster2) | ||
assert.Nil(t, err) | ||
assert.Equal(t, expectedCluster, unmarshaledCluster2) | ||
} |
Oops, something went wrong.