k8s.io/client-go@v0.31.1/openapi3/root_test.go (about) 1 /* 2 Copyright 2023 The Kubernetes 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 openapi3 18 19 import ( 20 "fmt" 21 "reflect" 22 "testing" 23 24 "github.com/stretchr/testify/assert" 25 "github.com/stretchr/testify/require" 26 "k8s.io/apimachinery/pkg/runtime/schema" 27 "k8s.io/client-go/openapi" 28 "k8s.io/client-go/openapi/openapitest" 29 ) 30 31 func TestOpenAPIV3Root_GroupVersions(t *testing.T) { 32 tests := []struct { 33 name string 34 paths map[string]openapi.GroupVersion 35 expectedGVs []schema.GroupVersion 36 forcedErr error 37 }{ 38 { 39 name: "OpenAPI V3 Root: No openapi.Paths() equals no GroupVersions.", 40 expectedGVs: []schema.GroupVersion{}, 41 }, 42 { 43 name: "OpenAPI V3 Root: Single openapi.Path equals one GroupVersion.", 44 paths: map[string]openapi.GroupVersion{ 45 "apis/apps/v1": nil, 46 }, 47 expectedGVs: []schema.GroupVersion{ 48 {Group: "apps", Version: "v1"}, 49 }, 50 }, 51 { 52 name: "OpenAPI V3 Root: Multiple openapi.Paths equals multiple GroupVersions.", 53 paths: map[string]openapi.GroupVersion{ 54 "apis/apps/v1": nil, 55 "api/v1": nil, 56 "apis/batch/v1beta1": nil, 57 }, 58 // Alphabetical ordering, since GV's are returned sorted. 59 expectedGVs: []schema.GroupVersion{ 60 {Group: "apps", Version: "v1"}, 61 {Group: "batch", Version: "v1beta1"}, 62 {Group: "", Version: "v1"}, 63 }, 64 }, 65 { 66 name: "Multiple GroupVersions, some invalid", 67 paths: map[string]openapi.GroupVersion{ 68 "apis/batch/v1beta1": nil, 69 "api/v1": nil, 70 "foo/apps/v1": nil, // bad prefix 71 "apis/networking.k8s.io/v1alpha1": nil, 72 "api": nil, // No version 73 "apis/apps": nil, // Missing Version 74 "apis/apps/v1": nil, 75 }, 76 // Alphabetical ordering, since GV's are returned sorted. 77 expectedGVs: []schema.GroupVersion{ 78 {Group: "apps", Version: "v1"}, 79 {Group: "batch", Version: "v1beta1"}, 80 {Group: "networking.k8s.io", Version: "v1alpha1"}, 81 {Group: "", Version: "v1"}, 82 }, 83 }, 84 { 85 name: "OpenAPI V3 Root: Forced error returns error.", 86 forcedErr: fmt.Errorf("openapi client error"), 87 }, 88 } 89 90 for _, test := range tests { 91 t.Run(test.name, func(t *testing.T) { 92 fakeClient := openapitest.FakeClient{ 93 PathsMap: test.paths, 94 ForcedErr: test.forcedErr, 95 } 96 root := NewRoot(fakeClient) 97 actualGVs, err := root.GroupVersions() 98 if test.forcedErr != nil { 99 require.Error(t, err) 100 } else { 101 require.NoError(t, err) 102 } 103 if !reflect.DeepEqual(test.expectedGVs, actualGVs) { 104 t.Errorf("expected GroupVersions (%s), got (%s): (%s)\n", 105 test.expectedGVs, actualGVs, err) 106 } 107 }) 108 } 109 } 110 111 func TestOpenAPIV3Root_GVSpec(t *testing.T) { 112 tests := []struct { 113 name string 114 gv schema.GroupVersion 115 expectedPaths []string 116 err error 117 }{ 118 { 119 name: "OpenAPI V3 for apps/v1 works", 120 gv: schema.GroupVersion{Group: "apps", Version: "v1"}, 121 expectedPaths: []string{ 122 "/apis/apps/v1/", 123 "/apis/apps/v1/deployments", 124 "/apis/apps/v1/replicasets", 125 "/apis/apps/v1/daemonsets", 126 }, 127 }, 128 { 129 name: "OpenAPI V3 for networking/v1alpha1 works", 130 gv: schema.GroupVersion{Group: "networking.k8s.io", Version: "v1alpha1"}, 131 expectedPaths: []string{ 132 "/apis/networking.k8s.io/v1alpha1/", 133 }, 134 }, 135 { 136 name: "OpenAPI V3 for batch/v1 works", 137 gv: schema.GroupVersion{Group: "batch", Version: "v1"}, 138 expectedPaths: []string{ 139 "/apis/batch/v1/", 140 "/apis/batch/v1/jobs", 141 "/apis/batch/v1/cronjobs", 142 }, 143 }, 144 { 145 name: "OpenAPI V3 spec not found", 146 gv: schema.GroupVersion{Group: "not", Version: "found"}, 147 err: &GroupVersionNotFoundError{gv: schema.GroupVersion{Group: "not", Version: "found"}}, 148 }, 149 } 150 151 for _, test := range tests { 152 t.Run(test.name, func(t *testing.T) { 153 client := openapitest.NewEmbeddedFileClient() 154 root := NewRoot(client) 155 gvSpec, err := root.GVSpec(test.gv) 156 if test.err != nil { 157 assert.True(t, reflect.DeepEqual(test.err, err)) 158 return 159 } 160 require.NoError(t, err) 161 for _, path := range test.expectedPaths { 162 if _, found := gvSpec.Paths.Paths[path]; !found { 163 assert.True(t, found, "expected path not found (%s)\n", path) 164 } 165 } 166 }) 167 } 168 } 169 170 func TestOpenAPIV3Root_GVSpecAsMap(t *testing.T) { 171 tests := []struct { 172 name string 173 gv schema.GroupVersion 174 expectedPaths []string 175 err error 176 }{ 177 { 178 name: "OpenAPI V3 for apps/v1 works", 179 gv: schema.GroupVersion{Group: "apps", Version: "v1"}, 180 expectedPaths: []string{ 181 "/apis/apps/v1/", 182 "/apis/apps/v1/deployments", 183 "/apis/apps/v1/replicasets", 184 "/apis/apps/v1/daemonsets", 185 }, 186 }, 187 { 188 name: "OpenAPI V3 for networking/v1alpha1 works", 189 gv: schema.GroupVersion{Group: "networking.k8s.io", Version: "v1alpha1"}, 190 expectedPaths: []string{ 191 "/apis/networking.k8s.io/v1alpha1/", 192 }, 193 }, 194 { 195 name: "OpenAPI V3 for batch/v1 works", 196 gv: schema.GroupVersion{Group: "batch", Version: "v1"}, 197 expectedPaths: []string{ 198 "/apis/batch/v1/", 199 "/apis/batch/v1/jobs", 200 "/apis/batch/v1/cronjobs", 201 }, 202 }, 203 { 204 name: "OpenAPI V3 spec not found", 205 gv: schema.GroupVersion{Group: "not", Version: "found"}, 206 err: &GroupVersionNotFoundError{gv: schema.GroupVersion{Group: "not", Version: "found"}}, 207 }, 208 } 209 210 for _, test := range tests { 211 t.Run(test.name, func(t *testing.T) { 212 root := NewRoot(openapitest.NewEmbeddedFileClient()) 213 gvSpecAsMap, err := root.GVSpecAsMap(test.gv) 214 if test.err != nil { 215 assert.True(t, reflect.DeepEqual(test.err, err)) 216 return 217 } 218 require.NoError(t, err) 219 for _, path := range test.expectedPaths { 220 pathsMap := gvSpecAsMap["paths"] 221 if _, found := pathsMap.(map[string]interface{})[path]; !found { 222 assert.True(t, found, "expected path not found (%s)\n", path) 223 } 224 } 225 }) 226 } 227 } 228 229 func TestOpenAPIV3Root_GroupVersionToPath(t *testing.T) { 230 tests := []struct { 231 name string 232 groupVersion schema.GroupVersion 233 expectedPath string 234 }{ 235 { 236 name: "OpenAPI V3 Root: Path to GroupVersion apps group", 237 groupVersion: schema.GroupVersion{ 238 Group: "apps", 239 Version: "v1", 240 }, 241 expectedPath: "apis/apps/v1", 242 }, 243 { 244 name: "OpenAPI V3 Root: Path to GroupVersion batch group", 245 groupVersion: schema.GroupVersion{ 246 Group: "batch", 247 Version: "v1beta1", 248 }, 249 expectedPath: "apis/batch/v1beta1", 250 }, 251 { 252 name: "OpenAPI V3 Root: Path to GroupVersion core group", 253 groupVersion: schema.GroupVersion{ 254 Version: "v1", 255 }, 256 expectedPath: "api/v1", 257 }, 258 } 259 260 for _, test := range tests { 261 t.Run(test.name, func(t *testing.T) { 262 actualPath := gvToAPIPath(test.groupVersion) 263 assert.Equal(t, test.expectedPath, actualPath, "expected API path (%s), got (%s)", 264 test.expectedPath, actualPath) 265 }) 266 } 267 } 268 269 func TestOpenAPIV3Root_PathToGroupVersion(t *testing.T) { 270 tests := []struct { 271 name string 272 path string 273 expectedGV schema.GroupVersion 274 expectedErr bool 275 }{ 276 { 277 name: "OpenAPI V3 Root: Path to GroupVersion apps/v1 group", 278 path: "apis/apps/v1", 279 expectedGV: schema.GroupVersion{ 280 Group: "apps", 281 Version: "v1", 282 }, 283 }, 284 { 285 name: "Group without Version throws error", 286 path: "apis/apps", 287 expectedErr: true, 288 }, 289 { 290 name: "OpenAPI V3 Root: Path to GroupVersion batch group", 291 path: "apis/batch/v1beta1", 292 expectedGV: schema.GroupVersion{ 293 Group: "batch", 294 Version: "v1beta1", 295 }, 296 }, 297 { 298 name: "OpenAPI V3 Root: Path to GroupVersion core group", 299 path: "api/v1", 300 expectedGV: schema.GroupVersion{ 301 Version: "v1", 302 }, 303 }, 304 } 305 306 for _, test := range tests { 307 t.Run(test.name, func(t *testing.T) { 308 actualGV, err := pathToGroupVersion(test.path) 309 if test.expectedErr { 310 require.Error(t, err, "should have received error for path: %s", test.path) 311 } else { 312 require.NoError(t, err, "expected no error, got (%v)", err) 313 assert.Equal(t, test.expectedGV, actualGV, "expected GroupVersion (%s), got (%s)", 314 test.expectedGV, actualGV) 315 } 316 }) 317 } 318 }