...

Source file src/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion/converter_test.go

Documentation: k8s.io/apiextensions-apiserver/pkg/apiserver/conversion

     1  /*
     2  Copyright 2019 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 conversion
    18  
    19  import (
    20  	"reflect"
    21  	"strings"
    22  	"testing"
    23  
    24  	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
    25  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    26  	"k8s.io/apimachinery/pkg/runtime"
    27  	"k8s.io/apimachinery/pkg/runtime/schema"
    28  	"k8s.io/apiserver/pkg/util/webhook"
    29  )
    30  
    31  func TestConversion(t *testing.T) {
    32  	tests := []struct {
    33  		Name            string
    34  		ValidVersions   []string
    35  		ClusterScoped   bool
    36  		ToVersion       string
    37  		SourceObject    runtime.Object
    38  		ExpectedObject  runtime.Object
    39  		ExpectedFailure string
    40  	}{
    41  		{
    42  			Name:          "simple_conversion",
    43  			ValidVersions: []string{"example.com/v1", "example.com/v2"},
    44  			ClusterScoped: false,
    45  			ToVersion:     "example.com/v2",
    46  			SourceObject: &unstructured.Unstructured{
    47  				Object: map[string]interface{}{
    48  					"apiVersion": "example.com/v1",
    49  					"other":      "data",
    50  					"kind":       "foo",
    51  				},
    52  			},
    53  			ExpectedObject: &unstructured.Unstructured{
    54  				Object: map[string]interface{}{
    55  					"apiVersion": "example.com/v2",
    56  					"other":      "data",
    57  					"kind":       "foo",
    58  				},
    59  			},
    60  			ExpectedFailure: "",
    61  		},
    62  		{
    63  			Name:          "failed_conversion_invalid_gv",
    64  			ValidVersions: []string{"example.com/v1", "example.com/v2"},
    65  			ClusterScoped: false,
    66  			ToVersion:     "example.com/v3",
    67  			SourceObject: &unstructured.Unstructured{
    68  				Object: map[string]interface{}{
    69  					"apiVersion": "example.com/v1",
    70  					"other":      "data",
    71  				},
    72  			},
    73  			ExpectedFailure: "invalid group/version: example.com/v3",
    74  		},
    75  		{
    76  			Name:          "simple_list_conversion",
    77  			ValidVersions: []string{"example.com/v1", "example.com/v2"},
    78  			ClusterScoped: false,
    79  			ToVersion:     "example.com/v2",
    80  			SourceObject: &unstructured.UnstructuredList{
    81  				Object: map[string]interface{}{
    82  					"apiVersion": "example.com/v1",
    83  					"kind":       "fooList",
    84  				},
    85  				Items: []unstructured.Unstructured{
    86  					{
    87  						Object: map[string]interface{}{
    88  							"apiVersion": "example.com/v1",
    89  							"kind":       "foo",
    90  							"other":      "data",
    91  						},
    92  					},
    93  					{
    94  						Object: map[string]interface{}{
    95  							"apiVersion": "example.com/v1",
    96  							"kind":       "foo",
    97  							"other":      "data2",
    98  						},
    99  					},
   100  				},
   101  			},
   102  			ExpectedObject: &unstructured.UnstructuredList{
   103  				Object: map[string]interface{}{
   104  					"apiVersion": "example.com/v2",
   105  					"kind":       "fooList",
   106  				},
   107  				Items: []unstructured.Unstructured{
   108  					{
   109  						Object: map[string]interface{}{
   110  							"apiVersion": "example.com/v2",
   111  							"kind":       "foo",
   112  							"other":      "data",
   113  						},
   114  					},
   115  					{
   116  						Object: map[string]interface{}{
   117  							"apiVersion": "example.com/v2",
   118  							"kind":       "foo",
   119  							"other":      "data2",
   120  						},
   121  					},
   122  				},
   123  			},
   124  			ExpectedFailure: "",
   125  		},
   126  		{
   127  			Name:          "list_with_invalid_gv",
   128  			ValidVersions: []string{"example.com/v1", "example.com/v2"},
   129  			ClusterScoped: false,
   130  			ToVersion:     "example.com/v2",
   131  			SourceObject: &unstructured.UnstructuredList{
   132  				Object: map[string]interface{}{
   133  					"apiVersion": "example.com/v1",
   134  					"kind":       "fooList",
   135  				},
   136  				Items: []unstructured.Unstructured{
   137  					{
   138  						Object: map[string]interface{}{
   139  							"apiVersion": "example.com/v1",
   140  							"kind":       "foo",
   141  							"other":      "data",
   142  						},
   143  					},
   144  					{
   145  						Object: map[string]interface{}{
   146  							"apiVersion": "example.com/v3",
   147  							"kind":       "foo",
   148  							"other":      "data2",
   149  						},
   150  					},
   151  				},
   152  			},
   153  			ExpectedFailure: "invalid group/version: example.com/v3",
   154  		},
   155  	}
   156  
   157  	CRConverterFactory, err := NewCRConverterFactory(nil, func(resolver webhook.AuthenticationInfoResolver) webhook.AuthenticationInfoResolver { return nil })
   158  	if err != nil {
   159  		t.Fatalf("Cannot create conversion factory: %v", err)
   160  	}
   161  	for _, test := range tests {
   162  		testCRD := apiextensionsv1.CustomResourceDefinition{
   163  			Spec: apiextensionsv1.CustomResourceDefinitionSpec{
   164  				Conversion: &apiextensionsv1.CustomResourceConversion{
   165  					Strategy: apiextensionsv1.NoneConverter,
   166  				},
   167  			},
   168  		}
   169  		for _, v := range test.ValidVersions {
   170  			gv, _ := schema.ParseGroupVersion(v)
   171  			testCRD.Spec.Versions = append(testCRD.Spec.Versions, apiextensionsv1.CustomResourceDefinitionVersion{Name: gv.Version, Served: true})
   172  			testCRD.Spec.Group = gv.Group
   173  		}
   174  		safeConverter, _, err := CRConverterFactory.NewConverter(&testCRD)
   175  		if err != nil {
   176  			t.Fatalf("Cannot create converter: %v", err)
   177  		}
   178  		o := test.SourceObject.DeepCopyObject()
   179  		toVersion, _ := schema.ParseGroupVersion(test.ToVersion)
   180  		toVersions := schema.GroupVersions{toVersion}
   181  		actual, err := safeConverter.ConvertToVersion(o, toVersions)
   182  		if test.ExpectedFailure != "" {
   183  			if err == nil || !strings.Contains(err.Error(), test.ExpectedFailure) {
   184  				t.Fatalf("%s: Expected the call to fail with error message `%s` but err=%v", test.Name, test.ExpectedFailure, err)
   185  			}
   186  		} else {
   187  			if err != nil {
   188  				t.Fatalf("%s: conversion failed with : %v", test.Name, err)
   189  			}
   190  			if !reflect.DeepEqual(test.ExpectedObject, actual) {
   191  				t.Fatalf("%s: Expected = %v, Actual = %v", test.Name, test.ExpectedObject, actual)
   192  			}
   193  		}
   194  	}
   195  }
   196  

View as plain text