Skip to content

Commit 25f6230

Browse files
authored
Merge pull request #15 from layer5io/smi-conformace
Smi conformace
2 parents a1712ce + 780f700 commit 25f6230

11 files changed

Lines changed: 957 additions & 32 deletions

File tree

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
# To check for smi conformance of a deployed service mesh
2+
We use kuttl to check for SMI conformance. All the tests are writtten in smi-test directory of this repository.
3+
Execute the following command to run the smi-conformace tests:-
4+
5+
```shell
6+
kubectl kuttl test --skip-cluster-delete=true --start-kind=false ./smi-test
7+
```
8+
19
<p style="text-align:center;" align="center">
210
<img align="center" src="https://raw.githubusercontent.com/layer5io/layer5/master/assets/images/layer5/layer5-tag-white-bg.png" width="45%" /></p>
311

go.mod

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module github.com/layer5/learn-layer5
2+
3+
go 1.13
4+
5+
replace github.com/kudobuilder/kuttl => /home/naveen/go/src/github.com/kanishkarj/kuttl
6+
7+
require (
8+
github.com/kudobuilder/kuttl v0.0.0-00010101000000-000000000000
9+
k8s.io/api v0.17.3
10+
k8s.io/apimachinery v0.17.3
11+
k8s.io/client-go v0.17.3
12+
sigs.k8s.io/controller-runtime v0.5.1
13+
)

go.sum

Lines changed: 563 additions & 0 deletions
Large diffs are not rendered by default.

smi-test/main.go

Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"encoding/json"
7+
"fmt"
8+
"io/ioutil"
9+
"net/http"
10+
"testing"
11+
12+
harness "github.com/kudobuilder/kuttl/pkg/apis/testharness/v1beta1"
13+
"github.com/kudobuilder/kuttl/pkg/test"
14+
testutils "github.com/kudobuilder/kuttl/pkg/test/utils"
15+
v1 "k8s.io/api/core/v1"
16+
"k8s.io/client-go/discovery"
17+
"sigs.k8s.io/controller-runtime/pkg/client"
18+
)
19+
20+
type URLstruct struct {
21+
URL string
22+
Method string
23+
Headers map[string]string
24+
}
25+
type MetricResponse struct {
26+
ReqReceived []string
27+
RespSucceeded []URLstruct
28+
RespFailed []URLstruct
29+
}
30+
31+
func getCustomTestsForAccess() map[string]test.CustomTest {
32+
testHandlers := make(map[string]test.CustomTest)
33+
testHandlers["traffic"] = func(
34+
t *testing.T,
35+
namespace string,
36+
clientFn func(forceNew bool) (client.Client, error),
37+
DiscoveryClient func() (discovery.DiscoveryInterface, error),
38+
Logger testutils.Logger,
39+
) []error {
40+
cl2, err := clientFn(true)
41+
if err != nil {
42+
Logger.Log(err)
43+
return nil
44+
}
45+
deps := &v1.ServiceList{}
46+
err = cl2.List(context.TODO(), deps, client.InNamespace(namespace))
47+
if err != nil {
48+
Logger.Log(err)
49+
return nil
50+
}
51+
ipMap := make(map[string]string)
52+
for _, svc := range deps.Items {
53+
ipMap[svc.Name] = svc.Spec.ClusterIP
54+
}
55+
{
56+
ip2 := "http://" + ipMap["service-b"] + ":9091"
57+
var jsonStr = []byte(`{"url":"` + ip2 + `/echo", "body":"", "method": "GET", "headers": {"head": "tail"}}`)
58+
59+
url := "http://" + ipMap["service-a"] + ":9091/call"
60+
61+
req, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
62+
if err != nil {
63+
Logger.Log(err)
64+
return nil
65+
}
66+
// req.Header.Set("head", "tail")
67+
// client := &http.Client{}
68+
// resp, err := client.Do(req)
69+
if err != nil {
70+
Logger.Log(req)
71+
72+
} else {
73+
// defer resp.Body.Close()
74+
// Logger.Log("response Status:", resp.Status)
75+
// Logger.Log("response Headers:", resp.Header)
76+
// body, _ := ioutil.ReadAll(resp.Body)
77+
// Logger.Log("response Body:", string(body))
78+
}
79+
}
80+
{
81+
ip1 := "http://" + ipMap["service-a"] + ":9091/metrics"
82+
83+
resp, err := http.Get(ip1)
84+
if err != nil {
85+
Logger.Log(ip1)
86+
Logger.Log(err)
87+
return nil
88+
}
89+
defer resp.Body.Close()
90+
Logger.Log("A:response Status:", resp.Status)
91+
Logger.Log("response Headers:", resp.Header)
92+
body, _ := ioutil.ReadAll(resp.Body)
93+
Logger.Log("response Body:", string(body))
94+
var metric MetricResponse
95+
json.Unmarshal(body, &metric)
96+
if len(metric.RespSucceeded) != 0 {
97+
t.Fail()
98+
Logger.Log("Doesn't fail the request without headers")
99+
}
100+
101+
}
102+
{
103+
ip2 := "http://" + ipMap["service-b"] + ":9091/metrics"
104+
105+
resp, err := http.Get(ip2)
106+
if err != nil {
107+
Logger.Log(err)
108+
return nil
109+
}
110+
defer resp.Body.Close()
111+
Logger.Log("B:response Status:", resp.Status)
112+
Logger.Log("response Headers:", resp.Header)
113+
body, _ := ioutil.ReadAll(resp.Body)
114+
Logger.Log("response Body:", string(body))
115+
}
116+
{
117+
ip3 := "http://" + ipMap["service-c"] + ":9091/metrics"
118+
119+
resp, err := http.Get(ip3)
120+
if err != nil {
121+
Logger.Log(err)
122+
return nil
123+
}
124+
defer resp.Body.Close()
125+
Logger.Log("c:response Status:", resp.Status)
126+
Logger.Log("response Headers:", resp.Header)
127+
body, _ := ioutil.ReadAll(resp.Body)
128+
Logger.Log("response Body:", string(body))
129+
}
130+
return nil
131+
}
132+
testHandlers["allow"] = func(
133+
t *testing.T,
134+
namespace string,
135+
clientFn func(forceNew bool) (client.Client, error),
136+
DiscoveryClient func() (discovery.DiscoveryInterface, error),
137+
Logger testutils.Logger,
138+
) []error {
139+
cl2, err := clientFn(true)
140+
if err != nil {
141+
Logger.Log(err)
142+
return nil
143+
}
144+
deps := &v1.ServiceList{}
145+
err = cl2.List(context.TODO(), deps, client.InNamespace(namespace))
146+
if err != nil {
147+
Logger.Log(err)
148+
return nil
149+
}
150+
ipMap := make(map[string]string)
151+
for _, svc := range deps.Items {
152+
ipMap[svc.Name] = svc.Spec.ClusterIP
153+
}
154+
{
155+
ip2 := "http://" + ipMap["service-b"] + ":9091"
156+
var jsonStr = []byte(`{"url":"` + ip2 + `/echo", "body":"", "method": "GET", "headers": {"head": "tail"}}`)
157+
158+
url := "http://" + ipMap["service-a"] + ":9091/call"
159+
160+
req, err := http.Post(url, "application/json", bytes.NewBuffer(jsonStr))
161+
if err != nil {
162+
Logger.Log(err)
163+
return nil
164+
}
165+
// req.Header.Set("head", "tail")
166+
// client := &http.Client{}
167+
// resp, err := client.Do(req)
168+
if err != nil {
169+
Logger.Log(req)
170+
171+
} else {
172+
// defer resp.Body.Close()
173+
// Logger.Log("response Status:", resp.Status)
174+
// Logger.Log("response Headers:", resp.Header)
175+
// body, _ := ioutil.ReadAll(resp.Body)
176+
// Logger.Log("response Body:", string(body))
177+
}
178+
}
179+
{
180+
ip1 := "http://" + ipMap["service-a"] + ":9091/metrics"
181+
182+
resp, err := http.Get(ip1)
183+
if err != nil {
184+
Logger.Log(ip1)
185+
Logger.Log(err)
186+
return nil
187+
}
188+
defer resp.Body.Close()
189+
Logger.Log("A:response Status:", resp.Status)
190+
Logger.Log("response Headers:", resp.Header)
191+
body, _ := ioutil.ReadAll(resp.Body)
192+
Logger.Log("response Body:", string(body))
193+
var metric MetricResponse
194+
json.Unmarshal(body, &metric)
195+
if len(metric.RespSucceeded) == 0 {
196+
t.Fail()
197+
Logger.Log("Doesn't fail the request without headers")
198+
}
199+
200+
}
201+
{
202+
ip2 := "http://" + ipMap["service-b"] + ":9091/metrics"
203+
204+
resp, err := http.Get(ip2)
205+
if err != nil {
206+
Logger.Log(err)
207+
return nil
208+
}
209+
defer resp.Body.Close()
210+
Logger.Log("B:response Status:", resp.Status)
211+
Logger.Log("response Headers:", resp.Header)
212+
body, _ := ioutil.ReadAll(resp.Body)
213+
Logger.Log("response Body:", string(body))
214+
}
215+
{
216+
ip3 := "http://" + ipMap["service-c"] + ":9091/metrics"
217+
218+
resp, err := http.Get(ip3)
219+
if err != nil {
220+
Logger.Log(err)
221+
return nil
222+
}
223+
defer resp.Body.Close()
224+
Logger.Log("c:response Status:", resp.Status)
225+
Logger.Log("response Headers:", resp.Header)
226+
body, _ := ioutil.ReadAll(resp.Body)
227+
Logger.Log("response Body:", string(body))
228+
}
229+
return nil
230+
}
231+
return testHandlers
232+
}
233+
234+
func main() {
235+
manifestDirs := []string{}
236+
testToRun := ""
237+
startKIND := false
238+
// skipClusterDelete := false
239+
options := harness.TestSuite{}
240+
// path, err := (os.Getwd())
241+
// if err != nil {
242+
// return
243+
// }
244+
args := []string{"./"}
245+
246+
options.TestDirs = args
247+
// If a config is not set and kudo-test.yaml exists, set configPath to kudo-test.yaml.
248+
options.TestDirs = manifestDirs
249+
options.StartKIND = startKIND
250+
options.SkipDelete = false
251+
if options.KINDContext == "" {
252+
options.KINDContext = harness.DefaultKINDContext
253+
}
254+
// options.SkipDelete = skipClusterDelete
255+
if len(args) != 0 {
256+
options.TestDirs = args
257+
}
258+
testHandlers := make(map[string]map[string]test.CustomTest)
259+
testHandlers["trafficAccess"] = getCustomTestsForAccess()
260+
// testHandlers["trafficAccess"]["install"] = func(
261+
// t *testing.T,
262+
// namespace string,
263+
// client func(forceNew bool) (client.Client, error),
264+
// DiscoveryClient func() (discovery.DiscoveryInterface, error),
265+
// Logger testutils.Logger,
266+
// ) []error {
267+
// Logger.Logf("This is a sample test log")
268+
// // time.Sleep(2 * time.Minute)
269+
// cl2, err := DiscoveryClient()
270+
// var runtimeInfo runtime.Object
271+
// err = cl2.RESTClient().Get().Do().Into(runtimeInfo)
272+
// if err != nil {
273+
// Logger.Log(err)
274+
// return nil
275+
// }
276+
// Logger.Log(runtimeInfo)
277+
// if err != nil {
278+
// Logger.Log(err)
279+
280+
// t.Fail()
281+
// }
282+
// return nil
283+
// }
284+
testutils.RunTests("kudo", testToRun, options.Parallel, func(t *testing.T) {
285+
harness := test.Harness{
286+
TestSuite: options,
287+
T: t,
288+
SuiteCustomTests: testHandlers,
289+
}
290+
s, _ := json.MarshalIndent(options, "", " ")
291+
fmt.Printf("Running integration tests with following options:\n%s\n", string(s))
292+
harness.Run()
293+
})
294+
}

smi-test/trafficAccess/01-assert.yaml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ spec:
1111
app: app-a
1212
template:
1313
metadata:
14+
# annotations:
15+
# 'consul.hashicorp.com/connect-inject': 'true'
1416
labels:
1517
app: app-a
1618
spec:
@@ -39,6 +41,8 @@ spec:
3941
app: app-b
4042
template:
4143
metadata:
44+
# annotations:
45+
# 'consul.hashicorp.com/connect-inject': 'true'
4246
labels:
4347
app: app-b
4448
spec:
@@ -67,6 +71,8 @@ spec:
6771
app: app-c
6872
template:
6973
metadata:
74+
# annotations:
75+
# 'consul.hashicorp.com/connect-inject': 'true'
7076
labels:
7177
app: app-c
7278
spec:
@@ -101,7 +107,7 @@ kind: Service
101107
metadata:
102108
name: service-b
103109
spec:
104-
type: ClusterIP
110+
type: NodePort
105111
selector:
106112
app: app-b
107113
ports:
@@ -115,7 +121,7 @@ kind: Service
115121
metadata:
116122
name: service-c
117123
spec:
118-
type: ClusterIP
124+
type: NodePort
119125
selector:
120126
app: app-c
121127
ports:

0 commit comments

Comments
 (0)