generated from kubernetes/kubernetes-template-project
-
Notifications
You must be signed in to change notification settings - Fork 67
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Istio provider: add e2e test with file examples/fixtures.
- Loading branch information
1 parent
23e8389
commit d0bc03b
Showing
11 changed files
with
707 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
/* | ||
Copyright 2023 The Kubernetes Authors. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package istio | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"fmt" | ||
"io/fs" | ||
"os" | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/google/go-cmp/cmp" | ||
"github.com/kubernetes-sigs/ingress2gateway/pkg/i2gw" | ||
apiequality "k8s.io/apimachinery/pkg/api/equality" | ||
"k8s.io/apimachinery/pkg/runtime" | ||
"k8s.io/apimachinery/pkg/types" | ||
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" | ||
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" | ||
) | ||
|
||
const fixturesDir = "./fixtures" | ||
|
||
func TestFileConversion(t *testing.T) { | ||
ctx := context.Background() | ||
|
||
filepath.WalkDir(filepath.Join(fixturesDir, "input"), func(path string, d fs.DirEntry, err error) error { | ||
if err != nil { | ||
t.Fatalf(err.Error()) | ||
} | ||
if d.IsDir() { | ||
return nil | ||
} | ||
|
||
istioProvider := NewProvider(&i2gw.ProviderConf{}) | ||
|
||
err = istioProvider.ReadResourcesFromFile(ctx, path) | ||
if err != nil { | ||
t.Fatalf("Failed to read input from file %v: %v", d.Name(), err.Error()) | ||
} | ||
|
||
gotGatewayResources, errList := istioProvider.ToGatewayAPI(i2gw.InputResources{}) | ||
if len(errList) > 0 { | ||
t.Fatalf("unexpected errors during input conversion for file %v: %v", d.Name(), errList.ToAggregate().Error()) | ||
} | ||
|
||
outputFile := filepath.Join(fixturesDir, "output", d.Name()) | ||
wantGatewayResources, err := readGatewayResourcesFromFile(t, outputFile) | ||
if err != nil { | ||
t.Fatalf("failed to read wantGatewayResources from file %v: %v", outputFile, err.Error()) | ||
} | ||
|
||
if !apiequality.Semantic.DeepEqual(gotGatewayResources.Gateways, wantGatewayResources.Gateways) { | ||
t.Errorf("Gateways diff for file %v (-want +got): %s", d.Name(), cmp.Diff(wantGatewayResources.Gateways, gotGatewayResources.Gateways)) | ||
} | ||
|
||
if !apiequality.Semantic.DeepEqual(gotGatewayResources.HTTPRoutes, wantGatewayResources.HTTPRoutes) { | ||
t.Errorf("HTTPRoutes diff for file %v (-want +got): %s", d.Name(), cmp.Diff(wantGatewayResources.HTTPRoutes, gotGatewayResources.HTTPRoutes)) | ||
} | ||
|
||
if !apiequality.Semantic.DeepEqual(gotGatewayResources.TLSRoutes, wantGatewayResources.TLSRoutes) { | ||
t.Errorf("TLSRoutes diff for file %v (-want +got): %s", d.Name(), cmp.Diff(wantGatewayResources.TLSRoutes, gotGatewayResources.TLSRoutes)) | ||
} | ||
|
||
if !apiequality.Semantic.DeepEqual(gotGatewayResources.TCPRoutes, wantGatewayResources.TCPRoutes) { | ||
t.Errorf("TCPRoutes diff for file %v (-want +got): %s", d.Name(), cmp.Diff(wantGatewayResources.TCPRoutes, gotGatewayResources.TCPRoutes)) | ||
} | ||
|
||
if !apiequality.Semantic.DeepEqual(gotGatewayResources.ReferenceGrants, wantGatewayResources.ReferenceGrants) { | ||
t.Errorf("ReferenceGrants diff for file %v (-want +got): %s", d.Name(), cmp.Diff(wantGatewayResources.ReferenceGrants, gotGatewayResources.ReferenceGrants)) | ||
} | ||
|
||
return nil | ||
}) | ||
} | ||
|
||
func readGatewayResourcesFromFile(t *testing.T, filename string) (*i2gw.GatewayResources, error) { | ||
t.Helper() | ||
|
||
stream, err := os.ReadFile(filename) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to read file %v: %w", filename, err) | ||
} | ||
|
||
unstructuredObjects, err := i2gw.ExtractObjectsFromReader(bytes.NewReader(stream), "") | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to extract objects: %w", err) | ||
} | ||
|
||
res := i2gw.GatewayResources{ | ||
Gateways: make(map[types.NamespacedName]gatewayv1.Gateway), | ||
HTTPRoutes: make(map[types.NamespacedName]gatewayv1.HTTPRoute), | ||
TLSRoutes: make(map[types.NamespacedName]gatewayv1alpha2.TLSRoute), | ||
TCPRoutes: make(map[types.NamespacedName]gatewayv1alpha2.TCPRoute), | ||
ReferenceGrants: make(map[types.NamespacedName]gatewayv1alpha2.ReferenceGrant), | ||
} | ||
|
||
for _, obj := range unstructuredObjects { | ||
switch objKind := obj.GetKind(); objKind { | ||
case "Gateway": | ||
var gw gatewayv1.Gateway | ||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), &gw); err != nil { | ||
return nil, fmt.Errorf("failed to parse k8s gateway object: %w", err) | ||
} | ||
res.Gateways[types.NamespacedName{ | ||
Namespace: gw.Namespace, | ||
Name: gw.Name, | ||
}] = gw | ||
case "HTTPRoute": | ||
var httpRoute gatewayv1.HTTPRoute | ||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), &httpRoute); err != nil { | ||
return nil, fmt.Errorf("failed to parse k8s gateway HTTPRoute object: %w", err) | ||
} | ||
|
||
res.HTTPRoutes[types.NamespacedName{ | ||
Namespace: httpRoute.Namespace, | ||
Name: httpRoute.Name, | ||
}] = httpRoute | ||
case "TLSRoute": | ||
var tlsRoute gatewayv1alpha2.TLSRoute | ||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), &tlsRoute); err != nil { | ||
return nil, fmt.Errorf("failed to parse k8s gateway TLSRoute object: %w", err) | ||
} | ||
|
||
res.TLSRoutes[types.NamespacedName{ | ||
Namespace: tlsRoute.Namespace, | ||
Name: tlsRoute.Name, | ||
}] = tlsRoute | ||
case "TCPRoute": | ||
var tcpRoute gatewayv1alpha2.TCPRoute | ||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), &tcpRoute); err != nil { | ||
return nil, fmt.Errorf("failed to parse k8s gateway TCPRoute object: %w", err) | ||
} | ||
|
||
res.TCPRoutes[types.NamespacedName{ | ||
Namespace: tcpRoute.Namespace, | ||
Name: tcpRoute.Name, | ||
}] = tcpRoute | ||
case "ReferenceGrant": | ||
var referenceGrant gatewayv1alpha2.ReferenceGrant | ||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), &referenceGrant); err != nil { | ||
return nil, fmt.Errorf("failed to parse k8s gateway ReferenceGrant object: %w", err) | ||
} | ||
|
||
res.ReferenceGrants[types.NamespacedName{ | ||
Namespace: referenceGrant.Namespace, | ||
Name: referenceGrant.Name, | ||
}] = referenceGrant | ||
default: | ||
return nil, fmt.Errorf("unknown object kind: %v", objKind) | ||
} | ||
} | ||
|
||
return &res, nil | ||
} |
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,85 @@ | ||
apiVersion: networking.istio.io/v1beta1 | ||
kind: Gateway | ||
metadata: | ||
name: my-gateway | ||
namespace: test | ||
spec: | ||
selector: | ||
app: istio-ingressgateway | ||
istio: ingressgateway | ||
servers: | ||
- port: | ||
number: 80 | ||
name: http | ||
protocol: HTTP | ||
hosts: | ||
- test.com | ||
- port: | ||
number: 443 | ||
protocol: HTTPS | ||
hosts: | ||
- "bookinfo/*.bookinfo.com" | ||
- "*" | ||
- "bookinfo" # short service-name inferred hosts are ignored; in future converter may expand this to the fqdn required by k8s api gateway | ||
tls: | ||
httpsRedirect: true | ||
mode: SIMPLE | ||
# all following tls related fields are ignored as there's no direct mapping to the k8s gateway api | ||
serverCertificate: /etc/certs/servercert.pem | ||
privateKey: /etc/certs/privatekey.pem | ||
credentialName: bookinfo-secret | ||
caCertificates: /etc/certs/caCertificates | ||
subjectAltNames: ["v1"] | ||
verifyCertificateSpki: ["v1"] | ||
verifyCertificateHash: ["v1"] | ||
minProtocolVersion: TLSV1_0 | ||
maxProtocolVersion: TLSV1_3 | ||
cipherSuites: ["v1"] | ||
bind: 1.2.3.4 # is ignored | ||
- port: | ||
number: 8080 | ||
protocol: TCP | ||
hosts: | ||
- "*/foo.example.com" | ||
- "./foo.example.com" | ||
- port: | ||
number: 8443 | ||
protocol: TLS | ||
hosts: | ||
- "prod/*.tls.com" | ||
- "*.tls.com" | ||
- port: # converted to HTTP protocol as there's no TLS section | ||
number: 8143 | ||
protocol: HTTP2 | ||
hosts: | ||
- "http2.dev" | ||
- port: # converted to HTTPS protocol as there's TLS section | ||
number: 8144 | ||
protocol: HTTP2 | ||
hosts: | ||
- "http2.dev" | ||
tls: | ||
mode: SIMPLE | ||
- port: # converted to HTTP protocol as there's no TLS section | ||
number: 8180 | ||
protocol: GRPC | ||
hosts: | ||
- "*" | ||
- port: # converted to HTTPS protocol as there's TLS section | ||
number: 8181 | ||
protocol: GRPC | ||
hosts: | ||
- "*" | ||
tls: | ||
mode: SIMPLE | ||
- port: # converted to TCP protocol | ||
number: 2379 | ||
protocol: MONGO | ||
hosts: | ||
- "*" | ||
- port: # this server is ignored because of the unknown protocol | ||
number: 8000 | ||
name: unknown-protocol | ||
protocol: TEST | ||
hosts: | ||
- "*" |
110 changes: 110 additions & 0 deletions
110
pkg/i2gw/providers/istio/fixtures/input/2-virtualservice-http.yaml
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,110 @@ | ||
apiVersion: networking.istio.io/v1beta1 | ||
kind: VirtualService | ||
metadata: | ||
namespace: test | ||
name: reviews-route | ||
spec: | ||
gateways: | ||
- "my-gateway" | ||
hosts: | ||
- reviews.prod.svc.cluster.local | ||
- reviews.test.svc.cluster.local | ||
http: | ||
- name: "v2" | ||
match: | ||
- uri: | ||
prefix: "/wpcatalog" | ||
headers: | ||
h1: | ||
exact: v1 | ||
queryParams: | ||
q1: | ||
exact: v2 | ||
method: | ||
exact: GET | ||
- uri: | ||
exact: "/consumercatalog" | ||
headers: | ||
h2: | ||
regex: v3 | ||
queryParams: | ||
q2: | ||
regex: v4 | ||
- uri: | ||
regex: "/catalog[0-9]+" | ||
# all fields for match below are ignored | ||
scheme: | ||
exact: "value" | ||
authority: | ||
exact: "value" | ||
port: 8080 | ||
sourceLabels: | ||
k: v | ||
ignoreUriCase: true | ||
withoutHeaders: | ||
header1: | ||
exact: value | ||
sourceNamespace: test | ||
statPrefix: stats | ||
gateways: ["gw1"] | ||
redirect: | ||
uri: /v1/bookRatings | ||
redirectCode: 302 | ||
scheme: http | ||
port: 8080 | ||
# authority & derivePort are ignored | ||
authority: newratings.default.svc.cluster.local | ||
rewrite: | ||
uri: "/newcatalog" | ||
# authority & uriRegexRewrite are ignored | ||
authority: test | ||
uriRegexRewrite: | ||
match: pattern | ||
rewrite: new-pattern | ||
mirror: | ||
host: reviews # interpreted as reviews.test.svc.cluster.local | ||
subset: v1 | ||
mirrors: | ||
- destination: | ||
host: reviewsA # interpreted as reviews.test.svc.cluster.local | ||
percentage: | ||
value: 50 | ||
- destination: | ||
host: reviewsB.prod.svc.cluster.local # interpreted as reviews.test.svc.cluster.local | ||
percentage: | ||
value: 50 | ||
route: | ||
- destination: | ||
host: reviews.prod.svc.cluster.local | ||
subset: v2 | ||
timeout: 5s | ||
headers: | ||
request: | ||
add: | ||
h1: v1 | ||
set: | ||
h2: v2 | ||
remove: | ||
- h3 | ||
response: | ||
add: | ||
h4: v4 | ||
set: | ||
h5: v5 | ||
remove: | ||
- h6 | ||
# the remaning fields are ignored | ||
directResponse: | ||
status: 503 | ||
delegate: | ||
name: reviews | ||
retries: | ||
attempts: 3 | ||
fault: | ||
abort: | ||
percentage: | ||
value: 0.1 | ||
httpStatus: 400 | ||
corsPolicy: | ||
allowOrigins: | ||
- exact: https://example.com |
26 changes: 26 additions & 0 deletions
26
pkg/i2gw/providers/istio/fixtures/input/3-virtualservice-tls.yaml
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,26 @@ | ||
apiVersion: networking.istio.io/v1beta1 | ||
kind: VirtualService | ||
metadata: | ||
namespace: test | ||
name: reviews-route | ||
spec: | ||
gateways: | ||
- "my-gateway" | ||
hosts: | ||
- reviews.prod.svc.cluster.local | ||
- reviews.test.svc.cluster.local | ||
tls: | ||
- match: | ||
- port: 443 | ||
sniHosts: | ||
- login.bookinfo.com | ||
route: | ||
- destination: | ||
host: login.prod.svc.cluster.local | ||
- match: | ||
- port: 443 | ||
sniHosts: | ||
- reviews.bookinfo.com | ||
route: | ||
- destination: | ||
host: reviews |
Oops, something went wrong.