Skip to content

Commit bbdbfc8

Browse files
author
k8s-merge-robot
committed
Merge pull request kubernetes#24787 from nikhiljindal/storageVersion
Automatic merge from submit-queue Moving StorageFactory building logic to genericapiserver Adding a DefaultStorageFactoryBuilder which builds the required StorageFactory. This allows us to remove the duplicated code between `cmd/kube-apiserver` and `federation/cmd/federated-apiserver` cc @deads2k @lavalamp @jianhuiz
2 parents 5ca769e + 2ffa3b4 commit bbdbfc8

File tree

13 files changed

+573
-550
lines changed

13 files changed

+573
-550
lines changed

cmd/kube-apiserver/app/options/options.go

Lines changed: 2 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,7 @@ import (
2323

2424
"k8s.io/kubernetes/pkg/admission"
2525
"k8s.io/kubernetes/pkg/api"
26-
"k8s.io/kubernetes/pkg/api/unversioned"
27-
apiutil "k8s.io/kubernetes/pkg/api/util"
2826
"k8s.io/kubernetes/pkg/api/validation"
29-
"k8s.io/kubernetes/pkg/apimachinery/registered"
3027
"k8s.io/kubernetes/pkg/apiserver"
3128
"k8s.io/kubernetes/pkg/genericapiserver"
3229
kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
@@ -46,7 +43,6 @@ type APIServer struct {
4643
BasicAuthFile string
4744
DefaultStorageMediaType string
4845
DeleteCollectionWorkers int
49-
DeprecatedStorageVersion string
5046
EtcdServersOverrides []string
5147
EventTTL time.Duration
5248
KeystoneURL string
@@ -62,13 +58,8 @@ type APIServer struct {
6258
SSHUser string
6359
ServiceAccountKeyFile string
6460
ServiceAccountLookup bool
65-
StorageVersions string
66-
// The default values for StorageVersions. StorageVersions overrides
67-
// these; you can change this if you want to change the defaults (e.g.,
68-
// for testing). This is not actually exposed as a flag.
69-
DefaultStorageVersions string
70-
TokenAuthFile string
71-
WatchCacheSizes []string
61+
TokenAuthFile string
62+
WatchCacheSizes []string
7263
}
7364

7465
// NewAPIServer creates a new APIServer object with default parameters
@@ -81,8 +72,6 @@ func NewAPIServer() *APIServer {
8172
DeleteCollectionWorkers: 1,
8273
EventTTL: 1 * time.Hour,
8374
MasterServiceNamespace: api.NamespaceDefault,
84-
StorageVersions: registered.AllPreferredGroupVersions(),
85-
DefaultStorageVersions: registered.AllPreferredGroupVersions(),
8675
KubeletConfig: kubeletclient.KubeletClientConfig{
8776
Port: ports.KubeletPort,
8877
EnableHttps: true,
@@ -92,69 +81,12 @@ func NewAPIServer() *APIServer {
9281
return &s
9382
}
9483

95-
// dest must be a map of group to groupVersion.
96-
func mergeGroupVersionIntoMap(gvList string, dest map[string]unversioned.GroupVersion) error {
97-
for _, gvString := range strings.Split(gvList, ",") {
98-
if gvString == "" {
99-
continue
100-
}
101-
// We accept two formats. "group/version" OR
102-
// "group=group/version". The latter is used when types
103-
// move between groups.
104-
if !strings.Contains(gvString, "=") {
105-
gv, err := unversioned.ParseGroupVersion(gvString)
106-
if err != nil {
107-
return err
108-
}
109-
dest[gv.Group] = gv
110-
111-
} else {
112-
parts := strings.SplitN(gvString, "=", 2)
113-
gv, err := unversioned.ParseGroupVersion(parts[1])
114-
if err != nil {
115-
return err
116-
}
117-
dest[parts[0]] = gv
118-
}
119-
}
120-
121-
return nil
122-
}
123-
124-
// StorageGroupsToEncodingVersion returns a map from group name to group version,
125-
// computed from the s.DeprecatedStorageVersion and s.StorageVersions flags.
126-
// TODO: can we move the whole storage version concept to the generic apiserver?
127-
func (s *APIServer) StorageGroupsToEncodingVersion() (map[string]unversioned.GroupVersion, error) {
128-
storageVersionMap := map[string]unversioned.GroupVersion{}
129-
if s.DeprecatedStorageVersion != "" {
130-
storageVersionMap[""] = unversioned.GroupVersion{Group: apiutil.GetGroup(s.DeprecatedStorageVersion), Version: apiutil.GetVersion(s.DeprecatedStorageVersion)}
131-
}
132-
133-
// First, get the defaults.
134-
if err := mergeGroupVersionIntoMap(s.DefaultStorageVersions, storageVersionMap); err != nil {
135-
return nil, err
136-
}
137-
// Override any defaults with the user settings.
138-
if err := mergeGroupVersionIntoMap(s.StorageVersions, storageVersionMap); err != nil {
139-
return nil, err
140-
}
141-
142-
return storageVersionMap, nil
143-
}
144-
14584
// AddFlags adds flags for a specific APIServer to the specified FlagSet
14685
func (s *APIServer) AddFlags(fs *pflag.FlagSet) {
14786
// Add the generic flags.
14887
s.ServerRunOptions.AddFlags(fs)
14988
// Note: the weird ""+ in below lines seems to be the only way to get gofmt to
15089
// arrange these text blocks sensibly. Grrr.
151-
fs.StringVar(&s.DeprecatedStorageVersion, "storage-version", s.DeprecatedStorageVersion, "The version to store the legacy v1 resources with. Defaults to server preferred")
152-
fs.MarkDeprecated("storage-version", "--storage-version is deprecated and will be removed when the v1 API is retired. See --storage-versions instead.")
153-
fs.StringVar(&s.StorageVersions, "storage-versions", s.StorageVersions, "The per-group version to store resources in. "+
154-
"Specified in the format \"group1/version1,group2/version2,...\". "+
155-
"In the case where objects are moved from one group to the other, you may specify the format \"group1=group2/v1beta1,group3/v1beta1,...\". "+
156-
"You only need to pass the groups you wish to change from the defaults. "+
157-
"It defaults to a list of preferred versions of all registered groups, which is derived from the KUBE_API_VERSIONS environment variable.")
15890
fs.StringVar(&s.DefaultStorageMediaType, "storage-media-type", s.DefaultStorageMediaType, "The media type to use to store objects in storage. Defaults to application/json. Some resources may only support a specific media type and will ignore this setting.")
15991
fs.DurationVar(&s.EventTTL, "event-ttl", s.EventTTL, "Amount of time to retain events. Default 1 hour.")
16092
fs.StringVar(&s.BasicAuthFile, "basic-auth-file", s.BasicAuthFile, "If set, the file that will be used to admit requests to the secure port of the API server via http basic authentication.")

cmd/kube-apiserver/app/options/options_test.go

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -17,72 +17,11 @@ limitations under the License.
1717
package options
1818

1919
import (
20-
"reflect"
2120
"testing"
2221

2322
"github.com/spf13/pflag"
24-
25-
"k8s.io/kubernetes/pkg/api"
26-
"k8s.io/kubernetes/pkg/api/unversioned"
27-
"k8s.io/kubernetes/pkg/apis/autoscaling"
28-
"k8s.io/kubernetes/pkg/apis/extensions"
2923
)
3024

31-
func TestGenerateStorageVersionMap(t *testing.T) {
32-
testCases := []struct {
33-
legacyVersion string
34-
storageVersions string
35-
defaultVersions string
36-
expectedMap map[string]unversioned.GroupVersion
37-
}{
38-
{
39-
legacyVersion: "v1",
40-
storageVersions: "v1,extensions/v1beta1",
41-
expectedMap: map[string]unversioned.GroupVersion{
42-
api.GroupName: {Version: "v1"},
43-
extensions.GroupName: {Group: "extensions", Version: "v1beta1"},
44-
},
45-
},
46-
{
47-
legacyVersion: "",
48-
storageVersions: "extensions/v1beta1,v1",
49-
expectedMap: map[string]unversioned.GroupVersion{
50-
api.GroupName: {Version: "v1"},
51-
extensions.GroupName: {Group: "extensions", Version: "v1beta1"},
52-
},
53-
},
54-
{
55-
legacyVersion: "",
56-
storageVersions: "autoscaling=extensions/v1beta1,v1",
57-
defaultVersions: "extensions/v1beta1,v1,autoscaling/v1",
58-
expectedMap: map[string]unversioned.GroupVersion{
59-
api.GroupName: {Version: "v1"},
60-
autoscaling.GroupName: {Group: "extensions", Version: "v1beta1"},
61-
extensions.GroupName: {Group: "extensions", Version: "v1beta1"},
62-
},
63-
},
64-
{
65-
legacyVersion: "",
66-
storageVersions: "",
67-
expectedMap: map[string]unversioned.GroupVersion{},
68-
},
69-
}
70-
for i, test := range testCases {
71-
s := APIServer{
72-
DeprecatedStorageVersion: test.legacyVersion,
73-
StorageVersions: test.storageVersions,
74-
DefaultStorageVersions: test.defaultVersions,
75-
}
76-
output, err := s.StorageGroupsToEncodingVersion()
77-
if err != nil {
78-
t.Errorf("%v: unexpected error: %v", i, err)
79-
}
80-
if !reflect.DeepEqual(test.expectedMap, output) {
81-
t.Errorf("%v: unexpected error. expect: %v, got: %v", i, test.expectedMap, output)
82-
}
83-
}
84-
}
85-
8625
func TestAddFlagsFlag(t *testing.T) {
8726
// TODO: This only tests the enable-swagger-ui flag for now.
8827
// Expand the test to include other flags as well.

cmd/kube-apiserver/app/server.go

Lines changed: 12 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ package app
2121

2222
import (
2323
"crypto/tls"
24-
"fmt"
2524
"net"
2625
"net/url"
2726
"strconv"
@@ -35,26 +34,18 @@ import (
3534
"k8s.io/kubernetes/pkg/admission"
3635
"k8s.io/kubernetes/pkg/api"
3736
"k8s.io/kubernetes/pkg/api/unversioned"
38-
apiv1 "k8s.io/kubernetes/pkg/api/v1"
39-
appsapi "k8s.io/kubernetes/pkg/apis/apps/v1alpha1"
4037
"k8s.io/kubernetes/pkg/apis/autoscaling"
41-
autoscalingapiv1 "k8s.io/kubernetes/pkg/apis/autoscaling/v1"
4238
"k8s.io/kubernetes/pkg/apis/batch"
43-
batchapiv1 "k8s.io/kubernetes/pkg/apis/batch/v1"
4439
"k8s.io/kubernetes/pkg/apis/extensions"
45-
extensionsapiv1beta1 "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
4640
"k8s.io/kubernetes/pkg/apiserver"
4741
"k8s.io/kubernetes/pkg/apiserver/authenticator"
4842
"k8s.io/kubernetes/pkg/capabilities"
49-
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
50-
"k8s.io/kubernetes/pkg/client/restclient"
5143
"k8s.io/kubernetes/pkg/cloudprovider"
5244
serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount"
5345
"k8s.io/kubernetes/pkg/genericapiserver"
5446
kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
5547
"k8s.io/kubernetes/pkg/master"
5648
"k8s.io/kubernetes/pkg/registry/cachesize"
57-
"k8s.io/kubernetes/pkg/runtime"
5849
"k8s.io/kubernetes/pkg/serviceaccount"
5950
)
6051

@@ -132,44 +123,17 @@ func Run(s *options.APIServer) error {
132123
glog.Fatalf("Failure to start kubelet client: %v", err)
133124
}
134125

135-
apiResourceConfigSource, err := parseRuntimeConfig(s)
126+
storageGroupsToEncodingVersion, err := s.StorageGroupsToEncodingVersion()
136127
if err != nil {
137-
glog.Fatalf("error in parsing runtime-config: %s", err)
128+
glog.Fatalf("error generating storage version map: %s", err)
138129
}
139-
140-
clientConfig := &restclient.Config{
141-
Host: net.JoinHostPort(s.InsecureBindAddress.String(), strconv.Itoa(s.InsecurePort)),
142-
// Increase QPS limits. The client is currently passed to all admission plugins,
143-
// and those can be throttled in case of higher load on apiserver - see #22340 and #22422
144-
// for more details. Once #22422 is fixed, we may want to remove it.
145-
QPS: 50,
146-
Burst: 100,
147-
}
148-
if len(s.DeprecatedStorageVersion) != 0 {
149-
gv, err := unversioned.ParseGroupVersion(s.DeprecatedStorageVersion)
150-
if err != nil {
151-
glog.Fatalf("error in parsing group version: %s", err)
152-
}
153-
clientConfig.GroupVersion = &gv
154-
}
155-
156-
client, err := clientset.NewForConfig(clientConfig)
130+
storageFactory, err := genericapiserver.BuildDefaultStorageFactory(
131+
s.StorageConfig, s.DefaultStorageMediaType, api.Codecs,
132+
genericapiserver.NewDefaultResourceEncodingConfig(), storageGroupsToEncodingVersion,
133+
master.DefaultAPIResourceConfigSource(), s.RuntimeConfig)
157134
if err != nil {
158-
glog.Errorf("Failed to create clientset: %v", err)
159-
}
160-
161-
resourceEncoding := genericapiserver.NewDefaultResourceEncodingConfig()
162-
groupToEncoding, err := s.StorageGroupsToEncodingVersion()
163-
if err != nil {
164-
glog.Fatalf("error getting group encoding: %s", err)
165-
}
166-
for group, storageEncodingVersion := range groupToEncoding {
167-
resourceEncoding.SetVersionEncoding(group, storageEncodingVersion, unversioned.GroupVersion{Group: group, Version: runtime.APIVersionInternal})
135+
glog.Fatalf("error in initializing storage factory: %s", err)
168136
}
169-
170-
storageFactory := genericapiserver.NewDefaultStorageFactory(s.StorageConfig, s.DefaultStorageMediaType, api.Codecs, resourceEncoding, apiResourceConfigSource)
171-
// third party resources are always serialized to storage using JSON
172-
storageFactory.SetSerializer(extensions.Resource("thirdpartyresources"), "application/json", nil)
173137
storageFactory.AddCohabitatingResources(batch.Resource("jobs"), extensions.Resource("jobs"))
174138
storageFactory.AddCohabitatingResources(autoscaling.Resource("horizontalpodautoscalers"), extensions.Resource("horizontalpodautoscalers"))
175139
for _, override := range s.EtcdServersOverrides {
@@ -238,6 +202,10 @@ func Run(s *options.APIServer) error {
238202
}
239203

240204
admissionControlPluginNames := strings.Split(s.AdmissionControl, ",")
205+
client, err := s.NewSelfClient()
206+
if err != nil {
207+
glog.Errorf("Failed to create clientset: %v", err)
208+
}
241209
admissionController := admission.NewFromPlugins(client, admissionControlPluginNames, s.AdmissionControlConfigFile)
242210

243211
genericConfig := genericapiserver.NewConfig(s.ServerRunOptions)
@@ -247,7 +215,7 @@ func Run(s *options.APIServer) error {
247215
genericConfig.SupportsBasicAuth = len(s.BasicAuthFile) > 0
248216
genericConfig.Authorizer = authorizer
249217
genericConfig.AdmissionControl = admissionController
250-
genericConfig.APIResourceConfigSource = apiResourceConfigSource
218+
genericConfig.APIResourceConfigSource = storageFactory.APIResourceConfigSource
251219
genericConfig.MasterServiceNamespace = s.MasterServiceNamespace
252220
genericConfig.ProxyDialer = proxyDialerFn
253221
genericConfig.ProxyTLSClientConfig = proxyTLSClientConfig
@@ -275,85 +243,3 @@ func Run(s *options.APIServer) error {
275243
m.Run(s.ServerRunOptions)
276244
return nil
277245
}
278-
279-
func getRuntimeConfigValue(s *options.APIServer, apiKey string, defaultValue bool) bool {
280-
flagValue, ok := s.RuntimeConfig[apiKey]
281-
if ok {
282-
if flagValue == "" {
283-
return true
284-
}
285-
boolValue, err := strconv.ParseBool(flagValue)
286-
if err != nil {
287-
glog.Fatalf("Invalid value of %s: %s, err: %v", apiKey, flagValue, err)
288-
}
289-
return boolValue
290-
}
291-
return defaultValue
292-
}
293-
294-
// Parses the given runtime-config and formats it into genericapiserver.APIResourceConfigSource
295-
func parseRuntimeConfig(s *options.APIServer) (genericapiserver.APIResourceConfigSource, error) {
296-
v1GroupVersionString := "api/v1"
297-
extensionsGroupVersionString := extensionsapiv1beta1.SchemeGroupVersion.String()
298-
versionToResourceSpecifier := map[unversioned.GroupVersion]string{
299-
apiv1.SchemeGroupVersion: v1GroupVersionString,
300-
extensionsapiv1beta1.SchemeGroupVersion: extensionsGroupVersionString,
301-
batchapiv1.SchemeGroupVersion: batchapiv1.SchemeGroupVersion.String(),
302-
autoscalingapiv1.SchemeGroupVersion: autoscalingapiv1.SchemeGroupVersion.String(),
303-
appsapi.SchemeGroupVersion: appsapi.SchemeGroupVersion.String(),
304-
}
305-
306-
resourceConfig := master.DefaultAPIResourceConfigSource()
307-
308-
// "api/all=false" allows users to selectively enable specific api versions.
309-
enableAPIByDefault := true
310-
allAPIFlagValue, ok := s.RuntimeConfig["api/all"]
311-
if ok && allAPIFlagValue == "false" {
312-
enableAPIByDefault = false
313-
}
314-
315-
// "api/legacy=false" allows users to disable legacy api versions.
316-
disableLegacyAPIs := false
317-
legacyAPIFlagValue, ok := s.RuntimeConfig["api/legacy"]
318-
if ok && legacyAPIFlagValue == "false" {
319-
disableLegacyAPIs = true
320-
}
321-
_ = disableLegacyAPIs // hush the compiler while we don't have legacy APIs to disable.
322-
323-
// "<resourceSpecifier>={true|false} allows users to enable/disable API.
324-
// This takes preference over api/all and api/legacy, if specified.
325-
for version, resourceSpecifier := range versionToResourceSpecifier {
326-
enableVersion := getRuntimeConfigValue(s, resourceSpecifier, enableAPIByDefault)
327-
if enableVersion {
328-
resourceConfig.EnableVersions(version)
329-
} else {
330-
resourceConfig.DisableVersions(version)
331-
}
332-
}
333-
334-
for key := range s.RuntimeConfig {
335-
tokens := strings.Split(key, "/")
336-
if len(tokens) != 3 {
337-
continue
338-
}
339-
340-
switch {
341-
case strings.HasPrefix(key, extensionsGroupVersionString+"/"):
342-
if !resourceConfig.AnyResourcesForVersionEnabled(extensionsapiv1beta1.SchemeGroupVersion) {
343-
return nil, fmt.Errorf("%v is disabled, you cannot configure its resources individually", extensionsapiv1beta1.SchemeGroupVersion)
344-
}
345-
346-
resource := strings.TrimPrefix(key, extensionsGroupVersionString+"/")
347-
if getRuntimeConfigValue(s, key, false) {
348-
resourceConfig.EnableResources(extensionsapiv1beta1.SchemeGroupVersion.WithResource(resource))
349-
} else {
350-
resourceConfig.DisableResources(extensionsapiv1beta1.SchemeGroupVersion.WithResource(resource))
351-
}
352-
353-
default:
354-
// TODO enable individual resource capability for all GroupVersionResources
355-
return nil, fmt.Errorf("%v resources cannot be enabled/disabled individually", key)
356-
}
357-
}
358-
return resourceConfig, nil
359-
}

0 commit comments

Comments
 (0)