...

Source file src/k8s.io/client-go/openapi3/root_test.go

Documentation: k8s.io/client-go/openapi3

     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  }
   319  

View as plain text