1
16
17 package netpol
18
19 import (
20 "fmt"
21 "strings"
22
23 v1 "k8s.io/api/core/v1"
24 "k8s.io/kubernetes/test/e2e/framework"
25 )
26
27
28 type TestCase struct {
29 ToPort int
30 Protocol v1.Protocol
31 Reachability *Reachability
32 }
33
34
35 type PodString string
36
37
38 func NewPodString(namespace string, podName string) PodString {
39 return PodString(fmt.Sprintf("%s/%s", namespace, podName))
40 }
41
42
43 func (pod PodString) String() string {
44 return string(pod)
45 }
46
47 func (pod PodString) split() (string, string) {
48 pieces := strings.Split(string(pod), "/")
49 if len(pieces) != 2 {
50 framework.Failf("expected ns/pod, found %+v", pieces)
51 }
52 return pieces[0], pieces[1]
53 }
54
55
56 func (pod PodString) Namespace() string {
57 ns, _ := pod.split()
58 return ns
59 }
60
61
62 func (pod PodString) PodName() string {
63 _, podName := pod.split()
64 return podName
65 }
66
67
68 type Peer struct {
69 Namespace string
70 Pod string
71 }
72
73
74
75
76
77 func (p *Peer) Matches(pod PodString) bool {
78 return (p.Namespace == "" || p.Namespace == pod.Namespace()) && (p.Pod == "" || p.Pod == pod.PodName())
79 }
80
81
82 type Reachability struct {
83 Expected *TruthTable
84 Observed *TruthTable
85 PodStrings []PodString
86 }
87
88
89 func NewReachability(podStrings []PodString, defaultExpectation bool) *Reachability {
90 var podNames []string
91 for _, podString := range podStrings {
92 podNames = append(podNames, podString.String())
93 }
94 r := &Reachability{
95 Expected: NewTruthTableFromItems(podNames, &defaultExpectation),
96 Observed: NewTruthTableFromItems(podNames, nil),
97 PodStrings: podStrings,
98 }
99 return r
100 }
101
102
103
104 func (r *Reachability) AllowLoopback() {
105 for _, podString := range r.PodStrings {
106 podName := podString.String()
107 r.Expected.Set(podName, podName, true)
108 }
109 }
110
111
112 func (r *Reachability) Expect(from PodString, to PodString, isConnected bool) {
113 r.Expected.Set(string(from), string(to), isConnected)
114 }
115
116
117 func (r *Reachability) ExpectAllIngress(pod PodString, connected bool) {
118 r.Expected.SetAllTo(string(pod), connected)
119 if !connected {
120 framework.Logf("Denying all traffic *to* %s", pod)
121 }
122 }
123
124
125 func (r *Reachability) ExpectAllEgress(pod PodString, connected bool) {
126 r.Expected.SetAllFrom(string(pod), connected)
127 if !connected {
128 framework.Logf("Denying all traffic *from* %s", pod)
129 }
130 }
131
132
133 func (r *Reachability) ExpectPeer(from *Peer, to *Peer, connected bool) {
134 for _, fromPod := range r.PodStrings {
135 if from.Matches(fromPod) {
136 for _, toPod := range r.PodStrings {
137 if to.Matches(toPod) {
138 r.Expected.Set(fromPod.String(), toPod.String(), connected)
139 }
140 }
141 }
142 }
143 }
144
145
146 func (r *Reachability) Observe(fromPod PodString, toPod PodString, isConnected bool) {
147 r.Observed.Set(fromPod.String(), toPod.String(), isConnected)
148 }
149
150
151 func (r *Reachability) Summary(ignoreLoopback bool) (trueObs int, falseObs int, ignoredObs int, comparison *TruthTable) {
152 comparison = r.Expected.Compare(r.Observed)
153 if !comparison.IsComplete() {
154 framework.Failf("observations not complete!")
155 }
156 falseObs, trueObs, ignoredObs = 0, 0, 0
157 for from, dict := range comparison.Values {
158 for to, val := range dict {
159 if ignoreLoopback && from == to {
160
161 ignoredObs++
162 } else if val {
163 trueObs++
164 } else {
165 falseObs++
166 }
167 }
168 }
169 return
170 }
171
172
173 func (r *Reachability) PrintSummary(printExpected bool, printObserved bool, printComparison bool) {
174 right, wrong, ignored, comparison := r.Summary(ignoreLoopback)
175 if ignored > 0 {
176 framework.Logf("warning: this test doesn't take into consideration hairpin traffic, i.e. traffic whose source and destination is the same pod: %d cases ignored", ignored)
177 }
178 framework.Logf("reachability: correct:%v, incorrect:%v, result=%t\n\n", right, wrong, wrong == 0)
179 if printExpected {
180 framework.Logf("expected:\n\n%s\n\n\n", r.Expected.PrettyPrint(""))
181 }
182 if printObserved {
183 framework.Logf("observed:\n\n%s\n\n\n", r.Observed.PrettyPrint(""))
184 }
185 if printComparison {
186 framework.Logf("comparison:\n\n%s\n\n\n", comparison.PrettyPrint(""))
187 }
188 }
189
View as plain text