knative.dev/pkg@v0.0.0-20260602142205-ac97e43f6622/apis/duck/v1/destination_test.go (about) 1 /* 2 Copyright 2019 The Knative Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package v1 18 19 import ( 20 "context" 21 "testing" 22 23 "github.com/google/go-cmp/cmp" 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 "knative.dev/pkg/apis" 26 ) 27 28 const ( 29 kind = "SomeKind" 30 apiVersion = "v1mega1" 31 name = "a-name" 32 namespace = "b-namespace" 33 ) 34 35 var ( 36 testCert = `-----BEGIN CERTIFICATE----- 37 MIIDmjCCAoKgAwIBAgIUYzA4bTMXevuk3pl2Mn8hpCYL2C0wDQYJKoZIhvcNAQEL 38 BQAwLzELMAkGA1UEBhMCVVMxIDAeBgNVBAMMF0tuYXRpdmUtRXhhbXBsZS1Sb290 39 LUNBMB4XDTIzMDQwNTEzMTUyNFoXDTI2MDEyMzEzMTUyNFowbTELMAkGA1UEBhMC 40 VVMxEjAQBgNVBAgMCVlvdXJTdGF0ZTERMA8GA1UEBwwIWW91ckNpdHkxHTAbBgNV 41 BAoMFEV4YW1wbGUtQ2VydGlmaWNhdGVzMRgwFgYDVQQDDA9sb2NhbGhvc3QubG9j 42 YWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5teo+En6U5nhqn7Sc 43 uanqswUmPlgs9j/8l21Rhb4T+ezlYKGQGhbJyFFMuiCE1Rjn8bpCwi7Nnv12Y2nz 44 FhEv2Jx0yL3Tqx0Q593myqKDq7326EtbO7wmDT0XD03twH5i9XZ0L0ihPWn1mjUy 45 WxhnHhoFpXrsnQECJorZY6aTrFbGVYelIaj5AriwiqyL0fET8pueI2GwLjgWHFSH 46 X8XsGAlcLUhkQG0Z+VO9usy4M1Wpt+cL6cnTiQ+sRmZ6uvaj8fKOT1Slk/oUeAi4 47 WqFkChGzGzLik0QrhKGTdw3uUvI1F2sdQj0GYzXaWqRz+tP9qnXdzk1GrszKKSlm 48 WBTLAgMBAAGjcDBuMB8GA1UdIwQYMBaAFJJcCftus4vj98N0zQQautsjEu82MAkG 49 A1UdEwQCMAAwCwYDVR0PBAQDAgTwMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDAdBgNV 50 HQ4EFgQUnu/3vqA3VEzm128x/hLyZzR9JlgwDQYJKoZIhvcNAQELBQADggEBAFc+ 51 1cKt/CNjHXUsirgEhry2Mm96R6Yxuq//mP2+SEjdab+FaXPZkjHx118u3PPX5uTh 52 gTT7rMfka6J5xzzQNqJbRMgNpdEFH1bbc11aYuhi0khOAe0cpQDtktyuDJQMMv3/ 53 3wu6rLr6fmENo0gdcyUY9EiYrglWGtdXhlo4ySRY8UZkUScG2upvyOhHTxVCAjhP 54 efbMkNjmDuZOMK+wqanqr5YV6zMPzkQK7DspfRgasMAQmugQu7r2MZpXg8Ilhro1 55 s/wImGnMVk5RzpBVrq2VB9SkX/ThTVYEC/Sd9BQM364MCR+TA1l8/ptaLFLuwyw8 56 O2dgzikq8iSy1BlRsVw= 57 -----END CERTIFICATE-----` 58 59 csr = `-----BEGIN CERTIFICATE REQUEST----- 60 MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDzANBgNV 61 BAcMBkxpbmRvbjEWMBQGA1UECgwNRGlnaUNlcnQgSW5jLjERMA8GA1UECwwIRGln 62 aUNlcnQxHTAbBgNVBAMMFGV4YW1wbGUuZGlnaWNlcnQuY29tMIIBIjANBgkqhkiG 63 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8+To7d+2kPWeBv/orU3LVbJwDrSQbeKamCmo 64 wp5bqDxIwV20zqRb7APUOKYoVEFFOEQs6T6gImnIolhbiH6m4zgZ/CPvWBOkZc+c 65 1Po2EmvBz+AD5sBdT5kzGQA6NbWyZGldxRthNLOs1efOhdnWFuhI162qmcflgpiI 66 WDuwq4C9f+YkeJhNn9dF5+owm8cOQmDrV8NNdiTqin8q3qYAHHJRW28glJUCZkTZ 67 wIaSR6crBQ8TbYNE0dc+Caa3DOIkz1EOsHWzTx+n0zKfqcbgXi4DJx+C1bjptYPR 68 BPZL8DAeWuA8ebudVT44yEp82G96/Ggcf7F33xMxe0yc+Xa6owIDAQABoAAwDQYJ 69 KoZIhvcNAQEFBQADggEBAB0kcrFccSmFDmxox0Ne01UIqSsDqHgL+XmHTXJwre6D 70 hJSZwbvEtOK0G3+dr4Fs11WuUNt5qcLsx5a8uk4G6AKHMzuhLsJ7XZjgmQXGECpY 71 Q4mC3yT3ZoCGpIXbw+iP3lmEEXgaQL0Tx5LFl/okKbKYwIqNiyKWOMj7ZR/wxWg/ 72 ZDGRs55xuoeLDJ/ZRFf9bI+IaCUd1YrfYcHIl3G87Av+r49YVwqRDT0VDV7uLgqn 73 29XI1PpVUNCPQGn9p/eX6Qo7vpDaPybRtA2R7XLKjQaF9oXWeCUqy1hvJac9QFO2 74 97Ob1alpHPoZ7mWiEuJwjBPii6a9M9G30nUo39lBi1w= 75 -----END CERTIFICATE REQUEST-----` 76 77 invaidCert = "certificate" 78 ) 79 80 func TestValidateDestination(t *testing.T) { 81 ctx := context.Background() 82 83 validRef := KReference{ 84 Kind: kind, 85 APIVersion: apiVersion, 86 Name: name, 87 Namespace: namespace, 88 } 89 90 validURL := apis.URL{ 91 Scheme: "http", 92 Host: "host", 93 } 94 95 tests := map[string]struct { 96 dest *Destination 97 want string 98 }{"nil valid": { 99 dest: nil, 100 }, "valid ref": { 101 dest: &Destination{ 102 Ref: &validRef, 103 }, 104 }, "invalid ref, missing name": { 105 dest: &Destination{ 106 Ref: &KReference{ 107 Namespace: namespace, 108 Kind: kind, 109 APIVersion: apiVersion, 110 }, 111 }, 112 want: "missing field(s): ref.name", 113 }, "invalid ref, missing api version": { 114 dest: &Destination{ 115 Ref: &KReference{ 116 Namespace: namespace, 117 Kind: kind, 118 Name: name, 119 }, 120 }, 121 want: "missing field(s): ref.apiVersion", 122 }, "invalid ref, missing kind": { 123 dest: &Destination{ 124 Ref: &KReference{ 125 Namespace: namespace, 126 APIVersion: apiVersion, 127 Name: name, 128 }, 129 }, 130 want: "missing field(s): ref.kind", 131 }, "valid uri": { 132 dest: &Destination{ 133 URI: &validURL, 134 }, 135 }, "invalid, uri has no host": { 136 dest: &Destination{ 137 URI: &apis.URL{ 138 Scheme: "http", 139 }, 140 }, 141 want: "invalid value: Relative URI is not allowed when Ref and [apiVersion, kind, name] is absent: uri", 142 }, "invalid, uri is not absolute url": { 143 dest: &Destination{ 144 URI: &apis.URL{ 145 Host: "host", 146 }, 147 }, 148 want: "invalid value: Relative URI is not allowed when Ref and [apiVersion, kind, name] is absent: uri", 149 }, "invalid, both uri and ref, uri is absolute URL": { 150 dest: &Destination{ 151 URI: &validURL, 152 Ref: &validRef, 153 }, 154 want: "Absolute URI is not allowed when Ref or [apiVersion, kind, name] is present: [apiVersion, kind, name], ref, uri", 155 }, "invalid, both ref, [apiVersion, kind, name] and uri are nil": { 156 dest: &Destination{}, 157 want: "expected at least one, got none: ref, uri", 158 }, "valid, both uri and ref, uri is not a absolute URL": { 159 dest: &Destination{ 160 URI: &apis.URL{ 161 Path: "/handler", 162 }, 163 Ref: &validRef, 164 }, 165 }, "valid, CACert is valid": { 166 dest: &Destination{ 167 URI: &apis.URL{ 168 Path: "/handler", 169 }, 170 Ref: &validRef, 171 CACerts: &testCert, 172 }, 173 }, "invalid,CACert is invalid": { 174 dest: &Destination{ 175 URI: &apis.URL{ 176 Path: "/handler", 177 }, 178 Ref: &validRef, 179 CACerts: &invaidCert, 180 }, 181 want: "invalid value: CA Cert provided is invalid: caCert", 182 }, "invalid,CSR provided not CA Cert": { 183 dest: &Destination{ 184 URI: &apis.URL{ 185 Path: "/handler", 186 }, 187 Ref: &validRef, 188 CACerts: &csr, 189 }, 190 want: "invalid value: CA Cert provided is not a certificate: caCert", 191 }} 192 193 for name, tc := range tests { 194 t.Run(name, func(t *testing.T) { 195 gotErr := tc.dest.Validate(ctx) 196 197 if tc.want != "" { 198 if got, want := gotErr.Error(), tc.want; got != want { 199 t.Errorf("%s: Error() = %v, wanted %v", name, got, want) 200 } 201 } else if gotErr != nil { 202 t.Errorf("%s: Validate() = %v, wanted nil", name, gotErr) 203 } 204 }) 205 } 206 } 207 208 func TestDestinationGetRef(t *testing.T) { 209 ref := &KReference{ 210 APIVersion: apiVersion, 211 Kind: kind, 212 Name: name, 213 } 214 tests := map[string]struct { 215 dest *Destination 216 want *KReference 217 }{"nil destination": { 218 dest: nil, 219 want: nil, 220 }, "uri": { 221 dest: &Destination{ 222 URI: &apis.URL{ 223 Host: "foo", 224 }, 225 }, 226 want: nil, 227 }, "ref": { 228 dest: &Destination{ 229 Ref: ref, 230 }, 231 want: ref, 232 }} 233 234 for n, tc := range tests { 235 t.Run(n, func(t *testing.T) { 236 got := tc.dest.GetRef() 237 if diff := cmp.Diff(tc.want, got); diff != "" { 238 t.Error("Unexpected result (-want +got):", diff) 239 } 240 }) 241 } 242 } 243 244 func TestDestinationSetDefaults(t *testing.T) { 245 ctx := context.Background() 246 247 const parentNamespace = "parentNamespace" 248 249 tests := map[string]struct { 250 d *Destination 251 ctx context.Context 252 want string 253 }{"destination nil ": { 254 d: nil, 255 ctx: ctx, 256 }, "uri set, nothing in ref, not modified ": { 257 d: &Destination{URI: apis.HTTP("example.com")}, 258 ctx: ctx, 259 }, "namespace set, nothing in context, not modified ": { 260 d: &Destination{Ref: &KReference{Namespace: namespace}}, 261 ctx: ctx, 262 want: namespace, 263 }, "namespace set, context set, not modified ": { 264 d: &Destination{Ref: &KReference{Namespace: namespace}}, 265 ctx: apis.WithinParent(ctx, metav1.ObjectMeta{Namespace: parentNamespace}), 266 want: namespace, 267 }, "namespace set, uri set, context set, not modified ": { 268 d: &Destination{Ref: &KReference{Namespace: namespace}, URI: apis.HTTP("example.com")}, 269 ctx: apis.WithinParent(ctx, metav1.ObjectMeta{Namespace: parentNamespace}), 270 want: namespace, 271 }, "namespace not set, context set, defaulted": { 272 d: &Destination{Ref: &KReference{}}, 273 ctx: apis.WithinParent(ctx, metav1.ObjectMeta{Namespace: parentNamespace}), 274 want: parentNamespace, 275 }, "namespace not set, uri set, context set, defaulted": { 276 d: &Destination{Ref: &KReference{}, URI: apis.HTTP("example.com")}, 277 ctx: apis.WithinParent(ctx, metav1.ObjectMeta{Namespace: parentNamespace}), 278 want: parentNamespace, 279 }} 280 for name, tc := range tests { 281 t.Run(name, func(t *testing.T) { 282 tc.d.SetDefaults(tc.ctx) 283 if tc.d != nil { 284 if tc.d.Ref != nil && tc.d.Ref.Namespace != tc.want { 285 t.Errorf("Got: %s wanted %s", tc.d.Ref.Namespace, tc.want) 286 } 287 if tc.d.Ref == nil && tc.want != "" { 288 t.Error("Got: nil Ref wanted", tc.want) 289 } 290 } 291 }) 292 } 293 }