Merge pull request #63364 from deads2k/api-16-scheme

Automatic merge from submit-queue (batch tested with PRs 63364, 63464). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

simplify api registration

The current registration and groupmeta is only use to determine a preferred ordering to versions.  The scheme already knows about all versions, so this simply makes that knowledge official.  After doing that, the announce, registered, and apimachinery/pkg/apimachinery all drop out.

With this change we'll be able to create `install` packages for each external apigroup that accept a scheme and have suggested orderings.  This will make it possible to close the consistency gap with kubectl, client, and apiserver.

@kubernetes/sig-api-machinery-pr-reviews
@lavalamp @smarterclayton @liggitt @sttts

```release-note
NONE
```

Kubernetes-commit: f929502282b370ceb3adae4816074142d6702c8b
This commit is contained in:
Kubernetes Publisher 2018-05-08 18:36:10 -07:00
commit 842a38c082
20 changed files with 338 additions and 453 deletions

470
Godeps/Godeps.json generated

File diff suppressed because it is too large Load Diff

View File

@ -19,25 +19,15 @@ limitations under the License.
package install package install
import ( import (
"k8s.io/apimachinery/pkg/apimachinery/announced"
"k8s.io/apimachinery/pkg/apimachinery/registered"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission" "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission"
"k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1" "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1"
) )
// Install registers the API group and adds types to a scheme // Install registers the API group and adds types to a scheme
func Install(registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { func Install(scheme *runtime.Scheme) {
if err := announced.NewGroupMetaFactory( utilruntime.Must(webhookadmission.AddToScheme(scheme))
&announced.GroupMetaFactoryArgs{ utilruntime.Must(v1alpha1.AddToScheme(scheme))
GroupName: webhookadmission.GroupName, utilruntime.Must(scheme.SetVersionPriority(v1alpha1.SchemeGroupVersion))
VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version},
AddInternalObjectsToScheme: webhookadmission.AddToScheme,
},
announced.VersionToSchemeFunc{
v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme,
},
).Register(registry, scheme); err != nil {
panic(err)
}
} }

View File

@ -17,25 +17,15 @@ limitations under the License.
package install package install
import ( import (
"k8s.io/apimachinery/pkg/apimachinery/announced"
"k8s.io/apimachinery/pkg/apimachinery/registered"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apiserver/pkg/apis/apiserver" "k8s.io/apiserver/pkg/apis/apiserver"
"k8s.io/apiserver/pkg/apis/apiserver/v1alpha1" "k8s.io/apiserver/pkg/apis/apiserver/v1alpha1"
) )
// Install registers the API group and adds types to a scheme // Install registers the API group and adds types to a scheme
func Install(registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { func Install(scheme *runtime.Scheme) {
if err := announced.NewGroupMetaFactory( utilruntime.Must(apiserver.AddToScheme(scheme))
&announced.GroupMetaFactoryArgs{ utilruntime.Must(v1alpha1.AddToScheme(scheme))
GroupName: apiserver.GroupName, utilruntime.Must(scheme.SetVersionPriority(v1alpha1.SchemeGroupVersion))
VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version},
AddInternalObjectsToScheme: apiserver.AddToScheme,
},
announced.VersionToSchemeFunc{
v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme,
},
).Register(registry, scheme); err != nil {
panic(err)
}
} }

View File

@ -19,27 +19,17 @@ limitations under the License.
package install package install
import ( import (
"k8s.io/apimachinery/pkg/apimachinery/announced"
"k8s.io/apimachinery/pkg/apimachinery/registered"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apiserver/pkg/apis/audit" "k8s.io/apiserver/pkg/apis/audit"
"k8s.io/apiserver/pkg/apis/audit/v1alpha1" "k8s.io/apiserver/pkg/apis/audit/v1alpha1"
"k8s.io/apiserver/pkg/apis/audit/v1beta1" "k8s.io/apiserver/pkg/apis/audit/v1beta1"
) )
// Install registers the API group and adds types to a scheme // Install registers the API group and adds types to a scheme
func Install(registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { func Install(scheme *runtime.Scheme) {
if err := announced.NewGroupMetaFactory( utilruntime.Must(audit.AddToScheme(scheme))
&announced.GroupMetaFactoryArgs{ utilruntime.Must(v1beta1.AddToScheme(scheme))
GroupName: audit.GroupName, utilruntime.Must(v1alpha1.AddToScheme(scheme))
VersionPreferenceOrder: []string{v1beta1.SchemeGroupVersion.Version, v1alpha1.SchemeGroupVersion.Version}, utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion, v1alpha1.SchemeGroupVersion))
AddInternalObjectsToScheme: audit.AddToScheme,
},
announced.VersionToSchemeFunc{
v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme,
v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme,
},
).Register(registry, scheme); err != nil {
panic(err)
}
} }

View File

@ -19,25 +19,15 @@ limitations under the License.
package install package install
import ( import (
"k8s.io/apimachinery/pkg/apimachinery/announced"
"k8s.io/apimachinery/pkg/apimachinery/registered"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apiserver/pkg/apis/example" "k8s.io/apiserver/pkg/apis/example"
examplev1 "k8s.io/apiserver/pkg/apis/example/v1" examplev1 "k8s.io/apiserver/pkg/apis/example/v1"
) )
// Install registers the API group and adds types to a scheme // Install registers the API group and adds types to a scheme
func Install(registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { func Install(scheme *runtime.Scheme) {
if err := announced.NewGroupMetaFactory( utilruntime.Must(example.AddToScheme(scheme))
&announced.GroupMetaFactoryArgs{ utilruntime.Must(examplev1.AddToScheme(scheme))
GroupName: example.GroupName, utilruntime.Must(scheme.SetVersionPriority(examplev1.SchemeGroupVersion))
VersionPreferenceOrder: []string{examplev1.SchemeGroupVersion.Version},
AddInternalObjectsToScheme: example.AddToScheme,
},
announced.VersionToSchemeFunc{
examplev1.SchemeGroupVersion.Version: examplev1.AddToScheme,
},
).Register(registry, scheme); err != nil {
panic(err)
}
} }

View File

@ -19,26 +19,15 @@ limitations under the License.
package install package install
import ( import (
"k8s.io/apimachinery/pkg/apimachinery/announced"
"k8s.io/apimachinery/pkg/apimachinery/registered"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apiserver/pkg/apis/example" "k8s.io/apiserver/pkg/apis/example"
"k8s.io/apiserver/pkg/apis/example2"
example2v1 "k8s.io/apiserver/pkg/apis/example2/v1" example2v1 "k8s.io/apiserver/pkg/apis/example2/v1"
) )
// Install registers the API group and adds types to a scheme // Install registers the API group and adds types to a scheme
func Install(registry *registered.APIRegistrationManager, scheme *runtime.Scheme) { func Install(scheme *runtime.Scheme) {
if err := announced.NewGroupMetaFactory( utilruntime.Must(example.AddToScheme(scheme))
&announced.GroupMetaFactoryArgs{ utilruntime.Must(example2v1.AddToScheme(scheme))
GroupName: example2.GroupName, utilruntime.Must(scheme.SetVersionPriority(example2v1.SchemeGroupVersion))
VersionPreferenceOrder: []string{example2v1.SchemeGroupVersion.Version},
AddInternalObjectsToScheme: example.AddToScheme,
},
announced.VersionToSchemeFunc{
example2v1.SchemeGroupVersion.Version: example2v1.AddToScheme,
},
).Register(registry, scheme); err != nil {
panic(err)
}
} }

View File

@ -26,7 +26,6 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/apimachinery/registered"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
@ -37,9 +36,8 @@ import (
) )
var ( var (
registry = registered.NewAPIRegistrationManager() scheme = runtime.NewScheme()
scheme = runtime.NewScheme() codecs = serializer.NewCodecFactory(scheme)
codecs = serializer.NewCodecFactory(scheme)
) )
func init() { func init() {

View File

@ -28,8 +28,6 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/apimachinery"
"k8s.io/apimachinery/pkg/apimachinery/registered"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
@ -49,7 +47,7 @@ import (
// Info about an API group. // Info about an API group.
type APIGroupInfo struct { type APIGroupInfo struct {
GroupMeta apimachinery.GroupMeta PrioritizedVersions []schema.GroupVersion
// Info about the resources in this group. Its a map from version to resource to the storage. // Info about the resources in this group. Its a map from version to resource to the storage.
VersionedResourcesStorageMap map[string]map[string]rest.Storage VersionedResourcesStorageMap map[string]map[string]rest.Storage
// OptionsExternalVersion controls the APIVersion used for common objects in the // OptionsExternalVersion controls the APIVersion used for common objects in the
@ -316,7 +314,7 @@ func (s preparedGenericAPIServer) NonBlockingRun(stopCh <-chan struct{}) error {
// installAPIResources is a private method for installing the REST storage backing each api groupversionresource // installAPIResources is a private method for installing the REST storage backing each api groupversionresource
func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *APIGroupInfo) error { func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *APIGroupInfo) error {
for _, groupVersion := range apiGroupInfo.GroupMeta.GroupVersions { for _, groupVersion := range apiGroupInfo.PrioritizedVersions {
if len(apiGroupInfo.VersionedResourcesStorageMap[groupVersion.Version]) == 0 { if len(apiGroupInfo.VersionedResourcesStorageMap[groupVersion.Version]) == 0 {
glog.Warningf("Skipping API %v because it has no resources.", groupVersion) glog.Warningf("Skipping API %v because it has no resources.", groupVersion)
continue continue
@ -345,7 +343,7 @@ func (s *GenericAPIServer) InstallLegacyAPIGroup(apiPrefix string, apiGroupInfo
// setup discovery // setup discovery
apiVersions := []string{} apiVersions := []string{}
for _, groupVersion := range apiGroupInfo.GroupMeta.GroupVersions { for _, groupVersion := range apiGroupInfo.PrioritizedVersions {
apiVersions = append(apiVersions, groupVersion.Version) apiVersions = append(apiVersions, groupVersion.Version)
} }
// Install the version handler. // Install the version handler.
@ -359,10 +357,10 @@ func (s *GenericAPIServer) InstallLegacyAPIGroup(apiPrefix string, apiGroupInfo
func (s *GenericAPIServer) InstallAPIGroup(apiGroupInfo *APIGroupInfo) error { func (s *GenericAPIServer) InstallAPIGroup(apiGroupInfo *APIGroupInfo) error {
// Do not register empty group or empty version. Doing so claims /apis/ for the wrong entity to be returned. // Do not register empty group or empty version. Doing so claims /apis/ for the wrong entity to be returned.
// Catching these here places the error much closer to its origin // Catching these here places the error much closer to its origin
if len(apiGroupInfo.GroupMeta.GroupVersions[0].Group) == 0 { if len(apiGroupInfo.PrioritizedVersions[0].Group) == 0 {
return fmt.Errorf("cannot register handler with an empty group for %#v", *apiGroupInfo) return fmt.Errorf("cannot register handler with an empty group for %#v", *apiGroupInfo)
} }
if len(apiGroupInfo.GroupMeta.GroupVersions[0].Version) == 0 { if len(apiGroupInfo.PrioritizedVersions[0].Version) == 0 {
return fmt.Errorf("cannot register handler with an empty version for %#v", *apiGroupInfo) return fmt.Errorf("cannot register handler with an empty version for %#v", *apiGroupInfo)
} }
@ -374,7 +372,7 @@ func (s *GenericAPIServer) InstallAPIGroup(apiGroupInfo *APIGroupInfo) error {
// Install the version handler. // Install the version handler.
// Add a handler at /apis/<groupName> to enumerate all versions supported by this group. // Add a handler at /apis/<groupName> to enumerate all versions supported by this group.
apiVersionsForDiscovery := []metav1.GroupVersionForDiscovery{} apiVersionsForDiscovery := []metav1.GroupVersionForDiscovery{}
for _, groupVersion := range apiGroupInfo.GroupMeta.GroupVersions { for _, groupVersion := range apiGroupInfo.PrioritizedVersions {
// Check the config to make sure that we elide versions that don't have any resources // Check the config to make sure that we elide versions that don't have any resources
if len(apiGroupInfo.VersionedResourcesStorageMap[groupVersion.Version]) == 0 { if len(apiGroupInfo.VersionedResourcesStorageMap[groupVersion.Version]) == 0 {
continue continue
@ -385,11 +383,11 @@ func (s *GenericAPIServer) InstallAPIGroup(apiGroupInfo *APIGroupInfo) error {
}) })
} }
preferredVersionForDiscovery := metav1.GroupVersionForDiscovery{ preferredVersionForDiscovery := metav1.GroupVersionForDiscovery{
GroupVersion: apiGroupInfo.GroupMeta.GroupVersions[0].String(), GroupVersion: apiGroupInfo.PrioritizedVersions[0].String(),
Version: apiGroupInfo.GroupMeta.GroupVersions[0].Version, Version: apiGroupInfo.PrioritizedVersions[0].Version,
} }
apiGroup := metav1.APIGroup{ apiGroup := metav1.APIGroup{
Name: apiGroupInfo.GroupMeta.GroupVersions[0].Group, Name: apiGroupInfo.PrioritizedVersions[0].Group,
Versions: apiVersionsForDiscovery, Versions: apiVersionsForDiscovery,
PreferredVersion: preferredVersionForDiscovery, PreferredVersion: preferredVersionForDiscovery,
} }
@ -433,11 +431,9 @@ func (s *GenericAPIServer) newAPIGroupVersion(apiGroupInfo *APIGroupInfo, groupV
// NewDefaultAPIGroupInfo returns an APIGroupInfo stubbed with "normal" values // NewDefaultAPIGroupInfo returns an APIGroupInfo stubbed with "normal" values
// exposed for easier composition from other packages // exposed for easier composition from other packages
func NewDefaultAPIGroupInfo(group string, registry *registered.APIRegistrationManager, scheme *runtime.Scheme, parameterCodec runtime.ParameterCodec, codecs serializer.CodecFactory) APIGroupInfo { func NewDefaultAPIGroupInfo(group string, scheme *runtime.Scheme, parameterCodec runtime.ParameterCodec, codecs serializer.CodecFactory) APIGroupInfo {
groupMeta := registry.GroupOrDie(group)
return APIGroupInfo{ return APIGroupInfo{
GroupMeta: *groupMeta, PrioritizedVersions: scheme.PrioritizedVersionsForGroup(group),
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{}, VersionedResourcesStorageMap: map[string]map[string]rest.Storage{},
// TODO unhardcode this. It was hardcoded before, but we need to re-evaluate // TODO unhardcode this. It was hardcoded before, but we need to re-evaluate
OptionsExternalVersion: &schema.GroupVersion{Version: "v1"}, OptionsExternalVersion: &schema.GroupVersion{Version: "v1"},

View File

@ -34,7 +34,6 @@ import (
// "github.com/go-openapi/spec" // "github.com/go-openapi/spec"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/apimachinery"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
@ -151,12 +150,8 @@ func TestInstallAPIGroups(t *testing.T) {
scheme.AddKnownTypes(v1GroupVersion, &metav1.Status{}) scheme.AddKnownTypes(v1GroupVersion, &metav1.Status{})
metav1.AddToGroupVersion(scheme, v1GroupVersion) metav1.AddToGroupVersion(scheme, v1GroupVersion)
groupMeta := apimachinery.GroupMeta{
GroupVersions: []schema.GroupVersion{gv},
}
return APIGroupInfo{ return APIGroupInfo{
GroupMeta: groupMeta, PrioritizedVersions: []schema.GroupVersion{gv},
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{ VersionedResourcesStorageMap: map[string]map[string]rest.Storage{
gv.Version: { gv.Version: {
"getter": &testGetterStorage{Version: gv.Version}, "getter": &testGetterStorage{Version: gv.Version},
@ -184,7 +179,7 @@ func TestInstallAPIGroups(t *testing.T) {
for _, api := range apis[1:] { for _, api := range apis[1:] {
err = s.InstallAPIGroup(&api) err = s.InstallAPIGroup(&api)
assert.NoError(err) assert.NoError(err)
groupPaths = append(groupPaths, APIGroupPrefix+"/"+api.GroupMeta.GroupVersions[0].Group) // /apis/<group> groupPaths = append(groupPaths, APIGroupPrefix+"/"+api.PrioritizedVersions[0].Group) // /apis/<group>
} }
server := httptest.NewServer(s.Handler) server := httptest.NewServer(s.Handler)
@ -225,19 +220,19 @@ func TestInstallAPIGroups(t *testing.T) {
continue continue
} }
if got, expected := group.Name, info.GroupMeta.GroupVersions[0].Group; got != expected { if got, expected := group.Name, info.PrioritizedVersions[0].Group; got != expected {
t.Errorf("[%d] unexpected group name at path %q: got=%q expected=%q", i, path, got, expected) t.Errorf("[%d] unexpected group name at path %q: got=%q expected=%q", i, path, got, expected)
continue continue
} }
if got, expected := group.PreferredVersion.Version, info.GroupMeta.GroupVersions[0].Version; got != expected { if got, expected := group.PreferredVersion.Version, info.PrioritizedVersions[0].Version; got != expected {
t.Errorf("[%d] unexpected group version at path %q: got=%q expected=%q", i, path, got, expected) t.Errorf("[%d] unexpected group version at path %q: got=%q expected=%q", i, path, got, expected)
continue continue
} }
} }
// should serve APIResourceList at group path + /<group-version> // should serve APIResourceList at group path + /<group-version>
path = path + "/" + info.GroupMeta.GroupVersions[0].Version path = path + "/" + info.PrioritizedVersions[0].Version
resp, err = http.Get(server.URL + path) resp, err = http.Get(server.URL + path)
if err != nil { if err != nil {
t.Errorf("[%d] unexpected error getting path %q path: %v", i, path, err) t.Errorf("[%d] unexpected error getting path %q path: %v", i, path, err)
@ -259,7 +254,7 @@ func TestInstallAPIGroups(t *testing.T) {
continue continue
} }
if got, expected := resources.GroupVersion, info.GroupMeta.GroupVersions[0].String(); got != expected { if got, expected := resources.GroupVersion, info.PrioritizedVersions[0].String(); got != expected {
t.Errorf("[%d] unexpected groupVersion at path %q: got=%q expected=%q", i, path, got, expected) t.Errorf("[%d] unexpected groupVersion at path %q: got=%q expected=%q", i, path, got, expected)
continue continue
} }

View File

@ -97,7 +97,7 @@ func (s *APIEnablementOptions) ApplyTo(c *server.Config, defaultResourceConfig *
func unknownGroups(groups []string, registry GroupRegisty) []string { func unknownGroups(groups []string, registry GroupRegisty) []string {
unknownGroups := []string{} unknownGroups := []string{}
for _, group := range groups { for _, group := range groups {
if !registry.IsRegistered(group) { if !registry.IsGroupRegistered(group) {
unknownGroups = append(unknownGroups, group) unknownGroups = append(unknownGroups, group)
} }
} }
@ -107,5 +107,5 @@ func unknownGroups(groups []string, registry GroupRegisty) []string {
// GroupRegisty provides a method to check whether given group is registered. // GroupRegisty provides a method to check whether given group is registered.
type GroupRegisty interface { type GroupRegisty interface {
// IsRegistered returns true if given group is registered. // IsRegistered returns true if given group is registered.
IsRegistered(group string) bool IsGroupRegistered(group string) bool
} }

View File

@ -29,12 +29,12 @@ import (
// GroupVersionRegistry provides access to registered group versions. // GroupVersionRegistry provides access to registered group versions.
type GroupVersionRegistry interface { type GroupVersionRegistry interface {
// IsRegistered returns true if given group is registered. // IsGroupRegistered returns true if given group is registered.
IsRegistered(group string) bool IsGroupRegistered(group string) bool
// IsRegisteredVersion returns true if given version is registered. // IsVersionRegistered returns true if given version is registered.
IsRegisteredVersion(v schema.GroupVersion) bool IsVersionRegistered(v schema.GroupVersion) bool
// RegisteredGroupVersions returns all registered group versions. // PrioritizedVersionsAllGroups returns all registered group versions.
RegisteredGroupVersions() []schema.GroupVersion PrioritizedVersionsAllGroups() []schema.GroupVersion
} }
// MergeResourceEncodingConfigs merges the given defaultResourceConfig with specific GroupVersionResource overrides. // MergeResourceEncodingConfigs merges the given defaultResourceConfig with specific GroupVersionResource overrides.
@ -104,12 +104,12 @@ func MergeAPIResourceConfigs(
} }
// Exclude group not registered into the registry. // Exclude group not registered into the registry.
if !registry.IsRegistered(groupVersion.Group) { if !registry.IsGroupRegistered(groupVersion.Group) {
continue continue
} }
// Verify that the groupVersion is registered into registry. // Verify that the groupVersion is registered into registry.
if !registry.IsRegisteredVersion(groupVersion) { if !registry.IsVersionRegistered(groupVersion) {
return nil, fmt.Errorf("group version %s that has not been registered", groupVersion.String()) return nil, fmt.Errorf("group version %s that has not been registered", groupVersion.String())
} }
enabled, err := getRuntimeConfigValue(overrides, key, false) enabled, err := getRuntimeConfigValue(overrides, key, false)

View File

@ -22,14 +22,12 @@ import (
apiv1 "k8s.io/api/core/v1" apiv1 "k8s.io/api/core/v1"
extensionsapiv1beta1 "k8s.io/api/extensions/v1beta1" extensionsapiv1beta1 "k8s.io/api/extensions/v1beta1"
"k8s.io/apimachinery/pkg/apimachinery" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/apimachinery/registered"
"k8s.io/apimachinery/pkg/runtime/schema"
serverstore "k8s.io/apiserver/pkg/server/storage" serverstore "k8s.io/apiserver/pkg/server/storage"
) )
func TestParseRuntimeConfig(t *testing.T) { func TestParseRuntimeConfig(t *testing.T) {
registry := newFakeRegistry() scheme := newFakeScheme()
apiv1GroupVersion := apiv1.SchemeGroupVersion apiv1GroupVersion := apiv1.SchemeGroupVersion
testCases := []struct { testCases := []struct {
runtimeConfig map[string]string runtimeConfig map[string]string
@ -116,7 +114,7 @@ func TestParseRuntimeConfig(t *testing.T) {
}, },
expectedAPIConfig: func() *serverstore.ResourceConfig { expectedAPIConfig: func() *serverstore.ResourceConfig {
config := newFakeAPIResourceConfigSource() config := newFakeAPIResourceConfigSource()
config.EnableVersions(registry.RegisteredGroupVersions()...) config.EnableVersions(scheme.PrioritizedVersionsAllGroups()...)
return config return config
}, },
err: false, err: false,
@ -139,8 +137,8 @@ func TestParseRuntimeConfig(t *testing.T) {
}, },
} }
for index, test := range testCases { for index, test := range testCases {
t.Log(registry.RegisteredGroupVersions()) t.Log(scheme.PrioritizedVersionsAllGroups())
actualDisablers, err := MergeAPIResourceConfigs(test.defaultResourceConfig(), test.runtimeConfig, registry) actualDisablers, err := MergeAPIResourceConfigs(test.defaultResourceConfig(), test.runtimeConfig, scheme)
if err == nil && test.err { if err == nil && test.err {
t.Fatalf("expected error for test case: %v", index) t.Fatalf("expected error for test case: %v", index)
} else if err != nil && !test.err { } else if err != nil && !test.err {
@ -165,15 +163,13 @@ func newFakeAPIResourceConfigSource() *serverstore.ResourceConfig {
return ret return ret
} }
func newFakeRegistry() *registered.APIRegistrationManager { func newFakeScheme() *runtime.Scheme {
registry := registered.NewAPIRegistrationManager() ret := runtime.NewScheme()
apiv1.AddToScheme(ret)
extensionsapiv1beta1.AddToScheme(ret)
registry.RegisterGroup(apimachinery.GroupMeta{ ret.SetVersionPriority(apiv1.SchemeGroupVersion)
GroupVersions: []schema.GroupVersion{apiv1.SchemeGroupVersion}, ret.SetVersionPriority(extensionsapiv1beta1.SchemeGroupVersion)
})
registry.RegisterGroup(apimachinery.GroupMeta{ return ret
GroupVersions: []schema.GroupVersion{extensionsapiv1beta1.SchemeGroupVersion},
})
registry.RegisterVersions([]schema.GroupVersion{apiv1.SchemeGroupVersion, extensionsapiv1beta1.SchemeGroupVersion})
return registry
} }

View File

@ -17,7 +17,8 @@ limitations under the License.
package storage package storage
import ( import (
"k8s.io/apimachinery/pkg/apimachinery/registered" "fmt"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
) )
@ -33,8 +34,8 @@ type ResourceEncodingConfig interface {
} }
type DefaultResourceEncodingConfig struct { type DefaultResourceEncodingConfig struct {
groups map[string]*GroupResourceEncodingConfig groups map[string]*GroupResourceEncodingConfig
registry *registered.APIRegistrationManager scheme *runtime.Scheme
} }
type GroupResourceEncodingConfig struct { type GroupResourceEncodingConfig struct {
@ -47,8 +48,8 @@ type GroupResourceEncodingConfig struct {
var _ ResourceEncodingConfig = &DefaultResourceEncodingConfig{} var _ ResourceEncodingConfig = &DefaultResourceEncodingConfig{}
func NewDefaultResourceEncodingConfig(registry *registered.APIRegistrationManager) *DefaultResourceEncodingConfig { func NewDefaultResourceEncodingConfig(scheme *runtime.Scheme) *DefaultResourceEncodingConfig {
return &DefaultResourceEncodingConfig{groups: map[string]*GroupResourceEncodingConfig{}, registry: registry} return &DefaultResourceEncodingConfig{groups: map[string]*GroupResourceEncodingConfig{}, scheme: scheme}
} }
func newGroupResourceEncodingConfig(defaultEncoding, defaultInternalVersion schema.GroupVersion) *GroupResourceEncodingConfig { func newGroupResourceEncodingConfig(defaultEncoding, defaultInternalVersion schema.GroupVersion) *GroupResourceEncodingConfig {
@ -80,16 +81,15 @@ func (o *DefaultResourceEncodingConfig) SetResourceEncoding(resourceBeingStored
} }
func (o *DefaultResourceEncodingConfig) StorageEncodingFor(resource schema.GroupResource) (schema.GroupVersion, error) { func (o *DefaultResourceEncodingConfig) StorageEncodingFor(resource schema.GroupResource) (schema.GroupVersion, error) {
groupMeta, err := o.registry.Group(resource.Group) if !o.scheme.IsGroupRegistered(resource.Group) {
if err != nil { return schema.GroupVersion{}, fmt.Errorf("group %q is not registered in scheme", resource.Group)
return schema.GroupVersion{}, err
} }
groupEncoding, groupExists := o.groups[resource.Group] groupEncoding, groupExists := o.groups[resource.Group]
if !groupExists { if !groupExists {
// return the most preferred external version for the group // return the most preferred external version for the group
return groupMeta.GroupVersions[0], nil return o.scheme.PrioritizedVersionsForGroup(resource.Group)[0], nil
} }
resourceOverride, resourceExists := groupEncoding.ExternalResourceEncodings[resource.Resource] resourceOverride, resourceExists := groupEncoding.ExternalResourceEncodings[resource.Resource]
@ -101,8 +101,8 @@ func (o *DefaultResourceEncodingConfig) StorageEncodingFor(resource schema.Group
} }
func (o *DefaultResourceEncodingConfig) InMemoryEncodingFor(resource schema.GroupResource) (schema.GroupVersion, error) { func (o *DefaultResourceEncodingConfig) InMemoryEncodingFor(resource schema.GroupResource) (schema.GroupVersion, error) {
if _, err := o.registry.Group(resource.Group); err != nil { if !o.scheme.IsGroupRegistered(resource.Group) {
return schema.GroupVersion{}, err return schema.GroupVersion{}, fmt.Errorf("group %q is not registered in scheme", resource.Group)
} }
groupEncoding, groupExists := o.groups[resource.Group] groupEncoding, groupExists := o.groups[resource.Group]

View File

@ -20,7 +20,6 @@ import (
"reflect" "reflect"
"testing" "testing"
"k8s.io/apimachinery/pkg/apimachinery/registered"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
@ -34,7 +33,6 @@ import (
var ( var (
v1GroupVersion = schema.GroupVersion{Group: "", Version: "v1"} v1GroupVersion = schema.GroupVersion{Group: "", Version: "v1"}
registry = registered.NewAPIRegistrationManager()
scheme = runtime.NewScheme() scheme = runtime.NewScheme()
codecs = serializer.NewCodecFactory(scheme) codecs = serializer.NewCodecFactory(scheme)
parameterCodec = runtime.NewParameterCodec(scheme) parameterCodec = runtime.NewParameterCodec(scheme)
@ -50,7 +48,7 @@ func init() {
&metav1.APIResourceList{}, &metav1.APIResourceList{},
) )
exampleinstall.Install(registry, scheme) exampleinstall.Install(scheme)
} }
type fakeNegotiater struct { type fakeNegotiater struct {
@ -91,7 +89,7 @@ func (n *fakeNegotiater) DecoderToVersion(serializer runtime.Decoder, gv runtime
func TestConfigurableStorageFactory(t *testing.T) { func TestConfigurableStorageFactory(t *testing.T) {
ns := &fakeNegotiater{types: []string{"test/test"}} ns := &fakeNegotiater{types: []string{"test/test"}}
f := NewDefaultStorageFactory(storagebackend.Config{}, "test/test", ns, NewDefaultResourceEncodingConfig(registry), NewResourceConfig(), nil) f := NewDefaultStorageFactory(storagebackend.Config{}, "test/test", ns, NewDefaultResourceEncodingConfig(scheme), NewResourceConfig(), nil)
f.AddCohabitatingResources(example.Resource("test"), schema.GroupResource{Resource: "test2", Group: "2"}) f.AddCohabitatingResources(example.Resource("test"), schema.GroupResource{Resource: "test2", Group: "2"})
called := false called := false
testEncoderChain := func(e runtime.Encoder) runtime.Encoder { testEncoderChain := func(e runtime.Encoder) runtime.Encoder {
@ -115,8 +113,7 @@ func TestConfigurableStorageFactory(t *testing.T) {
} }
func TestUpdateEtcdOverrides(t *testing.T) { func TestUpdateEtcdOverrides(t *testing.T) {
registry := registered.NewAPIRegistrationManager() exampleinstall.Install(scheme)
exampleinstall.Install(registry, scheme)
testCases := []struct { testCases := []struct {
resource schema.GroupResource resource schema.GroupResource
@ -142,7 +139,7 @@ func TestUpdateEtcdOverrides(t *testing.T) {
Prefix: "/registry", Prefix: "/registry",
ServerList: defaultEtcdLocation, ServerList: defaultEtcdLocation,
} }
storageFactory := NewDefaultStorageFactory(defaultConfig, "", codecs, NewDefaultResourceEncodingConfig(registry), NewResourceConfig(), nil) storageFactory := NewDefaultStorageFactory(defaultConfig, "", codecs, NewDefaultResourceEncodingConfig(scheme), NewResourceConfig(), nil)
storageFactory.SetEtcdLocation(test.resource, test.servers) storageFactory.SetEtcdLocation(test.resource, test.servers)
var err error var err error

View File

@ -22,7 +22,6 @@ import (
"time" "time"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/apimachinery/registered"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/runtime/serializer"
@ -42,13 +41,13 @@ type GenericWebhook struct {
} }
// NewGenericWebhook creates a new GenericWebhook from the provided kubeconfig file. // NewGenericWebhook creates a new GenericWebhook from the provided kubeconfig file.
func NewGenericWebhook(registry *registered.APIRegistrationManager, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff time.Duration) (*GenericWebhook, error) { func NewGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff time.Duration) (*GenericWebhook, error) {
return newGenericWebhook(registry, codecFactory, kubeConfigFile, groupVersions, initialBackoff, defaultRequestTimeout) return newGenericWebhook(scheme, codecFactory, kubeConfigFile, groupVersions, initialBackoff, defaultRequestTimeout)
} }
func newGenericWebhook(registry *registered.APIRegistrationManager, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff, requestTimeout time.Duration) (*GenericWebhook, error) { func newGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff, requestTimeout time.Duration) (*GenericWebhook, error) {
for _, groupVersion := range groupVersions { for _, groupVersion := range groupVersions {
if !registry.IsRegisteredVersion(groupVersion) { if !scheme.IsVersionRegistered(groupVersion) {
return nil, fmt.Errorf("webhook plugin requires enabling extension resource: %s", groupVersion) return nil, fmt.Errorf("webhook plugin requires enabling extension resource: %s", groupVersion)
} }
} }

View File

@ -32,7 +32,7 @@ import (
"time" "time"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
@ -258,7 +258,7 @@ func TestKubeConfigFile(t *testing.T) {
if err == nil { if err == nil {
defer os.Remove(kubeConfigFile) defer os.Remove(kubeConfigFile)
_, err = NewGenericWebhook(registered.NewAPIRegistrationManager(), scheme.Codecs, kubeConfigFile, groupVersions, retryBackoff) _, err = NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, kubeConfigFile, groupVersions, retryBackoff)
} }
return err return err
@ -281,7 +281,7 @@ func TestKubeConfigFile(t *testing.T) {
// TestMissingKubeConfigFile ensures that a kube config path to a missing file is handled properly // TestMissingKubeConfigFile ensures that a kube config path to a missing file is handled properly
func TestMissingKubeConfigFile(t *testing.T) { func TestMissingKubeConfigFile(t *testing.T) {
kubeConfigPath := "/some/missing/path" kubeConfigPath := "/some/missing/path"
_, err := NewGenericWebhook(registered.NewAPIRegistrationManager(), scheme.Codecs, kubeConfigPath, groupVersions, retryBackoff) _, err := NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, kubeConfigPath, groupVersions, retryBackoff)
if err == nil { if err == nil {
t.Errorf("creating the webhook should had failed") t.Errorf("creating the webhook should had failed")
@ -393,7 +393,7 @@ func TestTLSConfig(t *testing.T) {
defer os.Remove(configFile) defer os.Remove(configFile)
wh, err := NewGenericWebhook(registered.NewAPIRegistrationManager(), scheme.Codecs, configFile, groupVersions, retryBackoff) wh, err := NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, configFile, groupVersions, retryBackoff)
if err == nil { if err == nil {
err = wh.RestClient.Get().Do().Error() err = wh.RestClient.Get().Do().Error()
@ -458,7 +458,7 @@ func TestRequestTimeout(t *testing.T) {
var requestTimeout = 10 * time.Millisecond var requestTimeout = 10 * time.Millisecond
wh, err := newGenericWebhook(registered.NewAPIRegistrationManager(), scheme.Codecs, configFile, groupVersions, retryBackoff, requestTimeout) wh, err := newGenericWebhook(runtime.NewScheme(), scheme.Codecs, configFile, groupVersions, retryBackoff, requestTimeout)
if err != nil { if err != nil {
t.Fatalf("failed to create the webhook: %v", err) t.Fatalf("failed to create the webhook: %v", err)
} }
@ -544,7 +544,7 @@ func TestWithExponentialBackoff(t *testing.T) {
defer os.Remove(configFile) defer os.Remove(configFile)
wh, err := NewGenericWebhook(registered.NewAPIRegistrationManager(), scheme.Codecs, configFile, groupVersions, retryBackoff) wh, err := NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, configFile, groupVersions, retryBackoff)
if err != nil { if err != nil {
t.Fatalf("failed to create the webhook: %v", err) t.Fatalf("failed to create the webhook: %v", err)

View File

@ -25,10 +25,8 @@ import (
"github.com/pborman/uuid" "github.com/pborman/uuid"
"k8s.io/apimachinery/pkg/apimachinery/registered"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
auditinternal "k8s.io/apiserver/pkg/apis/audit" auditinternal "k8s.io/apiserver/pkg/apis/audit"
"k8s.io/apiserver/pkg/apis/audit/install" "k8s.io/apiserver/pkg/apis/audit/install"
@ -36,15 +34,8 @@ import (
"k8s.io/apiserver/pkg/audit" "k8s.io/apiserver/pkg/audit"
) )
// NOTE: Copied from webhook backend to register auditv1beta1 to scheme
var (
registry = registered.NewAPIRegistrationManager()
)
func init() { func init() {
allGVs := []schema.GroupVersion{auditv1beta1.SchemeGroupVersion} install.Install(audit.Scheme)
registry.RegisterVersions(allGVs)
install.Install(registry, audit.Scheme)
} }
func TestLogEventsLegacy(t *testing.T) { func TestLogEventsLegacy(t *testing.T) {

View File

@ -20,12 +20,9 @@ package webhook
import ( import (
"time" "time"
"k8s.io/apimachinery/pkg/apimachinery/registered"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
auditinternal "k8s.io/apiserver/pkg/apis/audit" auditinternal "k8s.io/apiserver/pkg/apis/audit"
"k8s.io/apiserver/pkg/apis/audit/install" "k8s.io/apiserver/pkg/apis/audit/install"
auditv1alpha1 "k8s.io/apiserver/pkg/apis/audit/v1alpha1"
auditv1beta1 "k8s.io/apiserver/pkg/apis/audit/v1beta1"
"k8s.io/apiserver/pkg/audit" "k8s.io/apiserver/pkg/audit"
"k8s.io/apiserver/pkg/util/webhook" "k8s.io/apiserver/pkg/util/webhook"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
@ -40,22 +37,12 @@ const (
DefaultInitialBackoff = 10 * time.Second DefaultInitialBackoff = 10 * time.Second
) )
var (
// NOTE: Copied from other webhook implementations
//
// Can we make these passable to NewGenericWebhook?
// TODO(audit): figure out a general way to let the client choose their preferred version
registry = registered.NewAPIRegistrationManager()
)
func init() { func init() {
allGVs := []schema.GroupVersion{auditv1alpha1.SchemeGroupVersion, auditv1beta1.SchemeGroupVersion} install.Install(audit.Scheme)
registry.RegisterVersions(allGVs)
install.Install(registry, audit.Scheme)
} }
func loadWebhook(configFile string, groupVersion schema.GroupVersion, initialBackoff time.Duration) (*webhook.GenericWebhook, error) { func loadWebhook(configFile string, groupVersion schema.GroupVersion, initialBackoff time.Duration) (*webhook.GenericWebhook, error) {
return webhook.NewGenericWebhook(registry, audit.Codecs, configFile, return webhook.NewGenericWebhook(audit.Scheme, audit.Codecs, configFile,
[]schema.GroupVersion{groupVersion}, initialBackoff) []schema.GroupVersion{groupVersion}, initialBackoff)
} }

View File

@ -23,9 +23,10 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
authentication "k8s.io/api/authentication/v1beta1" authentication "k8s.io/api/authentication/v1beta1"
"k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/cache" "k8s.io/apimachinery/pkg/util/cache"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/util/webhook" "k8s.io/apiserver/pkg/util/webhook"
@ -112,21 +113,15 @@ func (w *WebhookTokenAuthenticator) AuthenticateToken(token string) (user.Info,
}, true, nil }, true, nil
} }
// NOTE: client-go doesn't provide a registry. client-go does registers the
// authentication/v1beta1. We construct a registry that acknowledges
// authentication/v1beta1 as an enabled version to pass a check enforced in
// NewGenericWebhook.
var registry = registered.NewAPIRegistrationManager()
func init() {
registry.RegisterVersions(groupVersions)
}
// tokenReviewInterfaceFromKubeconfig builds a client from the specified kubeconfig file, // tokenReviewInterfaceFromKubeconfig builds a client from the specified kubeconfig file,
// and returns a TokenReviewInterface that uses that client. Note that the client submits TokenReview // and returns a TokenReviewInterface that uses that client. Note that the client submits TokenReview
// requests to the exact path specified in the kubeconfig file, so arbitrary non-API servers can be targeted. // requests to the exact path specified in the kubeconfig file, so arbitrary non-API servers can be targeted.
func tokenReviewInterfaceFromKubeconfig(kubeConfigFile string) (authenticationclient.TokenReviewInterface, error) { func tokenReviewInterfaceFromKubeconfig(kubeConfigFile string) (authenticationclient.TokenReviewInterface, error) {
gw, err := webhook.NewGenericWebhook(registry, scheme.Codecs, kubeConfigFile, groupVersions, 0) localScheme := runtime.NewScheme()
scheme.AddToScheme(localScheme)
utilruntime.Must(localScheme.SetVersionPriority(groupVersions...))
gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, kubeConfigFile, groupVersions, 0)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -25,7 +25,7 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
authorization "k8s.io/api/authorization/v1beta1" authorization "k8s.io/api/authorization/v1beta1"
"k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/cache" "k8s.io/apimachinery/pkg/util/cache"
"k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authentication/user"
@ -234,21 +234,15 @@ func convertToSARExtra(extra map[string][]string) map[string]authorization.Extra
return ret return ret
} }
// NOTE: client-go doesn't provide a registry. client-go does registers the
// authorization/v1beta1. We construct a registry that acknowledges
// authorization/v1beta1 as an enabled version to pass a check enforced in
// NewGenericWebhook.
var registry = registered.NewAPIRegistrationManager()
func init() {
registry.RegisterVersions(groupVersions)
}
// subjectAccessReviewInterfaceFromKubeconfig builds a client from the specified kubeconfig file, // subjectAccessReviewInterfaceFromKubeconfig builds a client from the specified kubeconfig file,
// and returns a SubjectAccessReviewInterface that uses that client. Note that the client submits SubjectAccessReview // and returns a SubjectAccessReviewInterface that uses that client. Note that the client submits SubjectAccessReview
// requests to the exact path specified in the kubeconfig file, so arbitrary non-API servers can be targeted. // requests to the exact path specified in the kubeconfig file, so arbitrary non-API servers can be targeted.
func subjectAccessReviewInterfaceFromKubeconfig(kubeConfigFile string) (authorizationclient.SubjectAccessReviewInterface, error) { func subjectAccessReviewInterfaceFromKubeconfig(kubeConfigFile string) (authorizationclient.SubjectAccessReviewInterface, error) {
gw, err := webhook.NewGenericWebhook(registry, scheme.Codecs, kubeConfigFile, groupVersions, 0) localScheme := runtime.NewScheme()
scheme.AddToScheme(localScheme)
localScheme.SetVersionPriority(groupVersions...)
gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, kubeConfigFile, groupVersions, 0)
if err != nil { if err != nil {
return nil, err return nil, err
} }