k8s.io/apiserver@v0.31.1/pkg/server/resourceconfig/helpers_test.go (about)

     1  /*
     2  Copyright 2017 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 resourceconfig
    18  
    19  import (
    20  	"reflect"
    21  	"testing"
    22  
    23  	"github.com/stretchr/testify/require"
    24  
    25  	appsv1 "k8s.io/api/apps/v1"
    26  	apiv1 "k8s.io/api/core/v1"
    27  	extensionsapiv1beta1 "k8s.io/api/extensions/v1beta1"
    28  	"k8s.io/apimachinery/pkg/runtime"
    29  	"k8s.io/apimachinery/pkg/runtime/schema"
    30  	serverstore "k8s.io/apiserver/pkg/server/storage"
    31  )
    32  
    33  func TestParseRuntimeConfig(t *testing.T) {
    34  	scheme := newFakeScheme(t)
    35  	apiv1GroupVersion := apiv1.SchemeGroupVersion
    36  	testCases := []struct {
    37  		name                  string
    38  		runtimeConfig         map[string]string
    39  		defaultResourceConfig func() *serverstore.ResourceConfig
    40  		expectedAPIConfig     func() *serverstore.ResourceConfig
    41  		expectedEnabledAPIs   map[schema.GroupVersionResource]bool
    42  		err                   bool
    43  	}{
    44  		{
    45  			name: "using-kind",
    46  			runtimeConfig: map[string]string{
    47  				"apps/v1/Deployment": "false",
    48  			},
    49  			defaultResourceConfig: func() *serverstore.ResourceConfig {
    50  				return newFakeAPIResourceConfigSource()
    51  			},
    52  			expectedAPIConfig: func() *serverstore.ResourceConfig {
    53  				return newFakeAPIResourceConfigSource()
    54  			},
    55  			expectedEnabledAPIs: defaultFakeEnabledResources(),
    56  			err:                 true,
    57  		},
    58  		{
    59  			name:          "everything-default-value",
    60  			runtimeConfig: map[string]string{},
    61  			defaultResourceConfig: func() *serverstore.ResourceConfig {
    62  				return newFakeAPIResourceConfigSource()
    63  			},
    64  			expectedAPIConfig: func() *serverstore.ResourceConfig {
    65  				return newFakeAPIResourceConfigSource()
    66  			},
    67  			expectedEnabledAPIs: defaultFakeEnabledResources(),
    68  			err:                 false,
    69  		},
    70  		{
    71  			name:          "no-runtimeConfig-override",
    72  			runtimeConfig: map[string]string{},
    73  			defaultResourceConfig: func() *serverstore.ResourceConfig {
    74  				config := newFakeAPIResourceConfigSource()
    75  				config.DisableVersions(extensionsapiv1beta1.SchemeGroupVersion)
    76  				return config
    77  			},
    78  			expectedAPIConfig: func() *serverstore.ResourceConfig {
    79  				config := newFakeAPIResourceConfigSource()
    80  				config.DisableVersions(extensionsapiv1beta1.SchemeGroupVersion)
    81  				return config
    82  			},
    83  			expectedEnabledAPIs: map[schema.GroupVersionResource]bool{
    84  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"):   false, // this becomes false because the DisableVersions set in the defaultConfig is now order dependent.
    85  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"): false,
    86  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"): false,
    87  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"):  false,
    88  				appsv1.SchemeGroupVersion.WithResource("deployments"):               true,
    89  				apiv1.SchemeGroupVersion.WithResource("pods"):                       true,
    90  			},
    91  			err: false,
    92  		},
    93  		{
    94  			name: "version-enabled-by-runtimeConfig-override",
    95  			runtimeConfig: map[string]string{
    96  				"apps/v1": "",
    97  			},
    98  			defaultResourceConfig: func() *serverstore.ResourceConfig {
    99  				config := newFakeAPIResourceConfigSource()
   100  				return config
   101  			},
   102  			expectedAPIConfig: func() *serverstore.ResourceConfig {
   103  				config := newFakeAPIResourceConfigSource()
   104  				return config
   105  			},
   106  			expectedEnabledAPIs: defaultFakeEnabledResources(),
   107  			err:                 false,
   108  		},
   109  		{
   110  			name: "disable-v1",
   111  			runtimeConfig: map[string]string{
   112  				"/v1": "false",
   113  			},
   114  			defaultResourceConfig: func() *serverstore.ResourceConfig {
   115  				return newFakeAPIResourceConfigSource()
   116  			},
   117  			expectedAPIConfig: func() *serverstore.ResourceConfig {
   118  				config := newFakeAPIResourceConfigSource()
   119  				config.DisableVersions(apiv1GroupVersion)
   120  				return config
   121  			},
   122  			expectedEnabledAPIs: map[schema.GroupVersionResource]bool{
   123  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"):   true,
   124  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"): false,
   125  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"): false,
   126  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"):  false,
   127  				appsv1.SchemeGroupVersion.WithResource("deployments"):               true,
   128  				apiv1.SchemeGroupVersion.WithResource("pods"):                       false,
   129  			},
   130  			err: false,
   131  		},
   132  		{
   133  			name: "invalid-runtime-config",
   134  			runtimeConfig: map[string]string{
   135  				"invalidgroup/version": "false",
   136  			},
   137  			defaultResourceConfig: func() *serverstore.ResourceConfig {
   138  				return newFakeAPIResourceConfigSource()
   139  			},
   140  			expectedAPIConfig: func() *serverstore.ResourceConfig {
   141  				return newFakeAPIResourceConfigSource()
   142  			},
   143  			expectedEnabledAPIs: defaultFakeEnabledResources(),
   144  			err:                 false,
   145  		},
   146  		{
   147  			name: "enable-all",
   148  			runtimeConfig: map[string]string{
   149  				"api/all": "true",
   150  			},
   151  			defaultResourceConfig: func() *serverstore.ResourceConfig {
   152  				return newFakeAPIResourceConfigSource()
   153  			},
   154  			expectedAPIConfig: func() *serverstore.ResourceConfig {
   155  				config := newFakeAPIResourceConfigSource()
   156  				config.EnableVersions(scheme.PrioritizedVersionsAllGroups()...)
   157  				return config
   158  			},
   159  			expectedEnabledAPIs: map[schema.GroupVersionResource]bool{
   160  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"):   true,
   161  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"): true,
   162  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"): true,
   163  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"):  true,
   164  				appsv1.SchemeGroupVersion.WithResource("deployments"):               true,
   165  				apiv1.SchemeGroupVersion.WithResource("pods"):                       true,
   166  			},
   167  			err: false,
   168  		},
   169  		{
   170  			name: "only-enable-v1",
   171  			runtimeConfig: map[string]string{
   172  				"api/all": "false",
   173  				"/v1":     "true",
   174  			},
   175  			defaultResourceConfig: func() *serverstore.ResourceConfig {
   176  				return newFakeAPIResourceConfigSource()
   177  			},
   178  			expectedAPIConfig: func() *serverstore.ResourceConfig {
   179  				config := newFakeAPIResourceConfigSource()
   180  				config.DisableVersions(appsv1.SchemeGroupVersion)
   181  				config.DisableVersions(extensionsapiv1beta1.SchemeGroupVersion)
   182  				return config
   183  			},
   184  			expectedEnabledAPIs: map[schema.GroupVersionResource]bool{
   185  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"):   false,
   186  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"): false,
   187  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"): false,
   188  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"):  false,
   189  				appsv1.SchemeGroupVersion.WithResource("deployments"):               false,
   190  				apiv1.SchemeGroupVersion.WithResource("pods"):                       true,
   191  			},
   192  			err: false,
   193  		},
   194  		{
   195  			name: "enable-specific-extensions-resources",
   196  			runtimeConfig: map[string]string{
   197  				"extensions/v1beta1/deployments": "true",
   198  			},
   199  			defaultResourceConfig: func() *serverstore.ResourceConfig {
   200  				return newFakeAPIResourceConfigSource()
   201  			},
   202  			expectedAPIConfig: func() *serverstore.ResourceConfig {
   203  				config := newFakeAPIResourceConfigSource()
   204  				config.EnableResources(extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"))
   205  				return config
   206  			},
   207  			expectedEnabledAPIs: map[schema.GroupVersionResource]bool{
   208  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"):   true,
   209  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"): true,
   210  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"): false,
   211  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"):  false,
   212  				appsv1.SchemeGroupVersion.WithResource("deployments"):               true,
   213  				apiv1.SchemeGroupVersion.WithResource("pods"):                       true,
   214  			}, err: false,
   215  		},
   216  		{
   217  			name: "disable-specific-extensions-resources",
   218  			runtimeConfig: map[string]string{
   219  				"extensions/v1beta1/ingresses": "false",
   220  			},
   221  			defaultResourceConfig: func() *serverstore.ResourceConfig {
   222  				return newFakeAPIResourceConfigSource()
   223  			},
   224  			expectedAPIConfig: func() *serverstore.ResourceConfig {
   225  				config := newFakeAPIResourceConfigSource()
   226  				config.DisableResources(extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"))
   227  				return config
   228  			},
   229  			expectedEnabledAPIs: map[schema.GroupVersionResource]bool{
   230  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"):   false,
   231  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"): false,
   232  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"): false,
   233  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"):  false,
   234  				appsv1.SchemeGroupVersion.WithResource("deployments"):               true,
   235  				apiv1.SchemeGroupVersion.WithResource("pods"):                       true,
   236  			}, err: false,
   237  		},
   238  		{
   239  			name: "disable-all-extensions-resources",
   240  			runtimeConfig: map[string]string{
   241  				"extensions/v1beta1": "false",
   242  			},
   243  			defaultResourceConfig: func() *serverstore.ResourceConfig {
   244  				return newFakeAPIResourceConfigSource()
   245  			},
   246  			expectedAPIConfig: func() *serverstore.ResourceConfig {
   247  				config := newFakeAPIResourceConfigSource()
   248  				config.DisableVersions(extensionsapiv1beta1.SchemeGroupVersion)
   249  				return config
   250  			},
   251  			expectedEnabledAPIs: map[schema.GroupVersionResource]bool{
   252  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"):   false,
   253  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"): false,
   254  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"): false,
   255  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"):  false,
   256  				appsv1.SchemeGroupVersion.WithResource("deployments"):               true,
   257  				apiv1.SchemeGroupVersion.WithResource("pods"):                       true,
   258  			}, err: false,
   259  		},
   260  		{
   261  			name: "disable-a-no-extensions-resources",
   262  			runtimeConfig: map[string]string{
   263  				"apps/v1/deployments": "false",
   264  			},
   265  			defaultResourceConfig: func() *serverstore.ResourceConfig {
   266  				return newFakeAPIResourceConfigSource()
   267  			},
   268  			expectedAPIConfig: func() *serverstore.ResourceConfig {
   269  				config := newFakeAPIResourceConfigSource()
   270  				config.DisableResources(appsv1.SchemeGroupVersion.WithResource("deployments"))
   271  				return config
   272  			},
   273  			expectedEnabledAPIs: map[schema.GroupVersionResource]bool{
   274  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"):   true,
   275  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"): false,
   276  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"): false,
   277  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"):  false,
   278  				appsv1.SchemeGroupVersion.WithResource("deployments"):               false,
   279  				apiv1.SchemeGroupVersion.WithResource("pods"):                       true,
   280  			},
   281  			err: false, // no error for backwards compatibility
   282  		},
   283  		{
   284  			name: "disable-all-beta-resources",
   285  			runtimeConfig: map[string]string{
   286  				"api/beta": "false",
   287  			},
   288  			defaultResourceConfig: func() *serverstore.ResourceConfig {
   289  				return newFakeAPIResourceConfigSource()
   290  			},
   291  			expectedAPIConfig: func() *serverstore.ResourceConfig {
   292  				config := newFakeAPIResourceConfigSource()
   293  				config.DisableVersions(extensionsapiv1beta1.SchemeGroupVersion)
   294  				return config
   295  			},
   296  			expectedEnabledAPIs: map[schema.GroupVersionResource]bool{
   297  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"):   false,
   298  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"): false,
   299  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"): false,
   300  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"):  false,
   301  				appsv1.SchemeGroupVersion.WithResource("deployments"):               true,
   302  				apiv1.SchemeGroupVersion.WithResource("pods"):                       true,
   303  			},
   304  			err: false, // no error for backwards compatibility
   305  		},
   306  		{
   307  			name: "user-explicit-disable-resource-over-user-version-enable",
   308  			runtimeConfig: map[string]string{
   309  				"apps/v1":             "true",
   310  				"apps/v1/deployments": "false",
   311  			},
   312  			defaultResourceConfig: func() *serverstore.ResourceConfig {
   313  				return newFakeAPIResourceConfigSource()
   314  			},
   315  			expectedAPIConfig: func() *serverstore.ResourceConfig {
   316  				config := newFakeAPIResourceConfigSource()
   317  				config.DisableResources(appsv1.SchemeGroupVersion.WithResource("deployments"))
   318  				return config
   319  			},
   320  			expectedEnabledAPIs: map[schema.GroupVersionResource]bool{
   321  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"):   true,
   322  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"): false,
   323  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"): false,
   324  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"):  false,
   325  				appsv1.SchemeGroupVersion.WithResource("deployments"):               false,
   326  				apiv1.SchemeGroupVersion.WithResource("pods"):                       true,
   327  			},
   328  			err: false, // no error for backwards compatibility
   329  		},
   330  		{
   331  			name: "user-explicit-enable-resource-over-user-version-disable",
   332  			runtimeConfig: map[string]string{
   333  				"apps/v1":             "false",
   334  				"apps/v1/deployments": "true",
   335  			},
   336  			defaultResourceConfig: func() *serverstore.ResourceConfig {
   337  				return newFakeAPIResourceConfigSource()
   338  			},
   339  			expectedAPIConfig: func() *serverstore.ResourceConfig {
   340  				config := newFakeAPIResourceConfigSource()
   341  				config.DisableVersions(appsv1.SchemeGroupVersion)
   342  				config.EnableResources(appsv1.SchemeGroupVersion.WithResource("deployments"))
   343  				return config
   344  			},
   345  			expectedEnabledAPIs: map[schema.GroupVersionResource]bool{
   346  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"):   true,
   347  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"): false,
   348  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"): false,
   349  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"):  false,
   350  				appsv1.SchemeGroupVersion.WithResource("deployments"):               true,
   351  				appsv1.SchemeGroupVersion.WithResource("other"):                     false,
   352  				apiv1.SchemeGroupVersion.WithResource("pods"):                       true,
   353  			},
   354  			err: false, // no error for backwards compatibility
   355  		},
   356  		{
   357  			name: "user-explicit-disable-resource-over-user-stability-enable",
   358  			runtimeConfig: map[string]string{
   359  				"api/ga":              "true",
   360  				"apps/v1/deployments": "false",
   361  			},
   362  			defaultResourceConfig: func() *serverstore.ResourceConfig {
   363  				return newFakeAPIResourceConfigSource()
   364  			},
   365  			expectedAPIConfig: func() *serverstore.ResourceConfig {
   366  				config := newFakeAPIResourceConfigSource()
   367  				config.DisableResources(appsv1.SchemeGroupVersion.WithResource("deployments"))
   368  				return config
   369  			},
   370  			expectedEnabledAPIs: map[schema.GroupVersionResource]bool{
   371  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"):   true,
   372  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"): false,
   373  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"): false,
   374  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"):  false,
   375  				appsv1.SchemeGroupVersion.WithResource("deployments"):               false,
   376  				apiv1.SchemeGroupVersion.WithResource("pods"):                       true,
   377  			},
   378  			err: false, // no error for backwards compatibility
   379  		},
   380  		{
   381  			name: "user-explicit-enable-resource-over-user-stability-disable",
   382  			runtimeConfig: map[string]string{
   383  				"api/ga":              "false",
   384  				"apps/v1/deployments": "true",
   385  			},
   386  			defaultResourceConfig: func() *serverstore.ResourceConfig {
   387  				return newFakeAPIResourceConfigSource()
   388  			},
   389  			expectedAPIConfig: func() *serverstore.ResourceConfig {
   390  				config := newFakeAPIResourceConfigSource()
   391  				config.DisableVersions(apiv1.SchemeGroupVersion)
   392  				config.DisableVersions(appsv1.SchemeGroupVersion)
   393  				config.EnableResources(appsv1.SchemeGroupVersion.WithResource("deployments"))
   394  				return config
   395  			},
   396  			expectedEnabledAPIs: map[schema.GroupVersionResource]bool{
   397  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"):   true,
   398  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"): false,
   399  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"): false,
   400  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"):  false,
   401  				appsv1.SchemeGroupVersion.WithResource("deployments"):               true,
   402  				apiv1.SchemeGroupVersion.WithResource("pods"):                       false,
   403  			},
   404  			err: false, // no error for backwards compatibility
   405  		},
   406  		{
   407  			name: "user-explicit-disable-resource-over-user-version-enable-over-user-stability-disable",
   408  			runtimeConfig: map[string]string{
   409  				"api/ga":              "false",
   410  				"apps/v1":             "true",
   411  				"apps/v1/deployments": "false",
   412  			},
   413  			defaultResourceConfig: func() *serverstore.ResourceConfig {
   414  				return newFakeAPIResourceConfigSource()
   415  			},
   416  			expectedAPIConfig: func() *serverstore.ResourceConfig {
   417  				config := newFakeAPIResourceConfigSource()
   418  				config.DisableVersions(apiv1.SchemeGroupVersion)
   419  				config.EnableVersions(appsv1.SchemeGroupVersion)
   420  				config.DisableResources(appsv1.SchemeGroupVersion.WithResource("deployments"))
   421  				return config
   422  			},
   423  			expectedEnabledAPIs: map[schema.GroupVersionResource]bool{
   424  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"):   true,
   425  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"): false,
   426  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"): false,
   427  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"):  false,
   428  				appsv1.SchemeGroupVersion.WithResource("deployments"):               false,
   429  				appsv1.SchemeGroupVersion.WithResource("other"):                     true,
   430  				apiv1.SchemeGroupVersion.WithResource("pods"):                       false,
   431  			},
   432  			err: false, // no error for backwards compatibility
   433  		},
   434  		{
   435  			name: "user-explicit-enable-resource-over-user-version-disable-over-user-stability-disable",
   436  			runtimeConfig: map[string]string{
   437  				"api/ga":              "false",
   438  				"apps/v1":             "false",
   439  				"apps/v1/deployments": "true",
   440  			},
   441  			defaultResourceConfig: func() *serverstore.ResourceConfig {
   442  				return newFakeAPIResourceConfigSource()
   443  			},
   444  			expectedAPIConfig: func() *serverstore.ResourceConfig {
   445  				config := newFakeAPIResourceConfigSource()
   446  				config.DisableVersions(apiv1.SchemeGroupVersion)
   447  				config.DisableVersions(appsv1.SchemeGroupVersion)
   448  				config.EnableResources(appsv1.SchemeGroupVersion.WithResource("deployments"))
   449  				return config
   450  			},
   451  			expectedEnabledAPIs: map[schema.GroupVersionResource]bool{
   452  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"):   true,
   453  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"): false,
   454  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"): false,
   455  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"):  false,
   456  				appsv1.SchemeGroupVersion.WithResource("deployments"):               true,
   457  				apiv1.SchemeGroupVersion.WithResource("pods"):                       false,
   458  			},
   459  			err: false, // no error for backwards compatibility
   460  		},
   461  		{
   462  			name: "user-explicit-disable-resource-over-user-version-enable-over-user-stability-enable",
   463  			runtimeConfig: map[string]string{
   464  				"api/ga":              "true",
   465  				"apps/v1":             "true",
   466  				"apps/v1/deployments": "false",
   467  			},
   468  			defaultResourceConfig: func() *serverstore.ResourceConfig {
   469  				return newFakeAPIResourceConfigSource()
   470  			},
   471  			expectedAPIConfig: func() *serverstore.ResourceConfig {
   472  				config := newFakeAPIResourceConfigSource()
   473  				config.EnableVersions(appsv1.SchemeGroupVersion)
   474  				config.DisableResources(appsv1.SchemeGroupVersion.WithResource("deployments"))
   475  				return config
   476  			},
   477  			expectedEnabledAPIs: map[schema.GroupVersionResource]bool{
   478  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"):   true,
   479  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"): false,
   480  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"): false,
   481  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"):  false,
   482  				appsv1.SchemeGroupVersion.WithResource("deployments"):               false,
   483  				apiv1.SchemeGroupVersion.WithResource("pods"):                       true,
   484  			},
   485  			err: false, // no error for backwards compatibility
   486  		},
   487  		{
   488  			name: "user-explicit-enable-resource-over-user-version-disable-over-user-stability-enable",
   489  			runtimeConfig: map[string]string{
   490  				"api/ga":              "true",
   491  				"apps/v1":             "false",
   492  				"apps/v1/deployments": "true",
   493  			},
   494  			defaultResourceConfig: func() *serverstore.ResourceConfig {
   495  				return newFakeAPIResourceConfigSource()
   496  			},
   497  			expectedAPIConfig: func() *serverstore.ResourceConfig {
   498  				config := newFakeAPIResourceConfigSource()
   499  				config.DisableVersions(appsv1.SchemeGroupVersion)
   500  				config.EnableResources(appsv1.SchemeGroupVersion.WithResource("deployments"))
   501  				return config
   502  			},
   503  			expectedEnabledAPIs: map[schema.GroupVersionResource]bool{
   504  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"):   true,
   505  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"): false,
   506  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"): false,
   507  				extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"):  false,
   508  				appsv1.SchemeGroupVersion.WithResource("deployments"):               true,
   509  				appsv1.SchemeGroupVersion.WithResource("other"):                     false,
   510  				apiv1.SchemeGroupVersion.WithResource("pods"):                       true,
   511  			},
   512  			err: false, // no error for backwards compatibility
   513  		},
   514  	}
   515  	for _, test := range testCases {
   516  		t.Run(test.name, func(t *testing.T) {
   517  			t.Log(scheme.PrioritizedVersionsAllGroups())
   518  			actualDisablers, err := MergeAPIResourceConfigs(test.defaultResourceConfig(), test.runtimeConfig, scheme)
   519  			if err == nil && test.err {
   520  				t.Fatalf("expected error")
   521  			} else if err != nil && !test.err {
   522  				t.Fatalf("unexpected error: %s, for test: %v", err, test)
   523  			}
   524  			if err != nil {
   525  				return
   526  			}
   527  
   528  			expectedConfig := test.expectedAPIConfig()
   529  			if !reflect.DeepEqual(actualDisablers, expectedConfig) {
   530  				t.Fatalf("%v: unexpected apiResourceDisablers. Actual: %v\n expected: %v", test.runtimeConfig, actualDisablers, expectedConfig)
   531  			}
   532  
   533  			for _, resourceToCheck := range apiResourcesToCheck() {
   534  				actual := actualDisablers.ResourceEnabled(resourceToCheck)
   535  				expected := test.expectedEnabledAPIs[resourceToCheck]
   536  				if actual != expected {
   537  					t.Errorf("for %v, actual=%v, expected=%v", resourceToCheck, actual, expected)
   538  				}
   539  			}
   540  			for resourceToCheck, expected := range test.expectedEnabledAPIs {
   541  				actual := actualDisablers.ResourceEnabled(resourceToCheck)
   542  				if actual != expected {
   543  					t.Errorf("for %v, actual=%v, expected=%v", resourceToCheck, actual, expected)
   544  				}
   545  			}
   546  		})
   547  	}
   548  }
   549  
   550  func newFakeAPIResourceConfigSource() *serverstore.ResourceConfig {
   551  	ret := serverstore.NewResourceConfig()
   552  	// NOTE: GroupVersions listed here will be enabled by default. Don't put alpha versions in the list.
   553  	ret.EnableVersions(
   554  		apiv1.SchemeGroupVersion,
   555  		appsv1.SchemeGroupVersion,
   556  		extensionsapiv1beta1.SchemeGroupVersion,
   557  	)
   558  	ret.EnableResources(
   559  		extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"),
   560  	)
   561  	ret.DisableResources(
   562  		extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"),
   563  		extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"),
   564  		extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"),
   565  	)
   566  
   567  	return ret
   568  }
   569  
   570  // apiResourcesToCheck are the apis we use in this set of unit tests.  They will be check for enable/disable status
   571  func apiResourcesToCheck() []schema.GroupVersionResource {
   572  	return []schema.GroupVersionResource{
   573  		extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"),
   574  		extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"),
   575  		extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"),
   576  		extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"),
   577  		appsv1.SchemeGroupVersion.WithResource("deployments"),
   578  		apiv1.SchemeGroupVersion.WithResource("pods"),
   579  	}
   580  }
   581  
   582  func defaultFakeEnabledResources() map[schema.GroupVersionResource]bool {
   583  	return map[schema.GroupVersionResource]bool{
   584  		extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"):   true,
   585  		extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"): false,
   586  		extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"): false,
   587  		extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"):  false,
   588  		appsv1.SchemeGroupVersion.WithResource("deployments"):               true,
   589  		apiv1.SchemeGroupVersion.WithResource("pods"):                       true,
   590  	}
   591  }
   592  
   593  func newFakeScheme(t *testing.T) *runtime.Scheme {
   594  	ret := runtime.NewScheme()
   595  	require.NoError(t, apiv1.AddToScheme(ret))
   596  	require.NoError(t, appsv1.AddToScheme(ret))
   597  	require.NoError(t, extensionsapiv1beta1.AddToScheme(ret))
   598  
   599  	require.NoError(t, ret.SetVersionPriority(apiv1.SchemeGroupVersion))
   600  	require.NoError(t, ret.SetVersionPriority(extensionsapiv1beta1.SchemeGroupVersion))
   601  
   602  	return ret
   603  }