1/*
2Copyright 2016 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package kubeapiserver
18
19import (
20	"strings"
21
22	"k8s.io/apimachinery/pkg/runtime"
23	"k8s.io/apimachinery/pkg/runtime/schema"
24	serveroptions "k8s.io/apiserver/pkg/server/options"
25	"k8s.io/apiserver/pkg/server/options/encryptionconfig"
26	"k8s.io/apiserver/pkg/server/resourceconfig"
27	serverstorage "k8s.io/apiserver/pkg/server/storage"
28	"k8s.io/apiserver/pkg/storage/storagebackend"
29	"k8s.io/kubernetes/pkg/api/legacyscheme"
30	"k8s.io/kubernetes/pkg/apis/apps"
31	api "k8s.io/kubernetes/pkg/apis/core"
32	"k8s.io/kubernetes/pkg/apis/events"
33	"k8s.io/kubernetes/pkg/apis/extensions"
34	"k8s.io/kubernetes/pkg/apis/networking"
35	"k8s.io/kubernetes/pkg/apis/policy"
36	apisstorage "k8s.io/kubernetes/pkg/apis/storage"
37)
38
39// SpecialDefaultResourcePrefixes are prefixes compiled into Kubernetes.
40var SpecialDefaultResourcePrefixes = map[schema.GroupResource]string{
41	{Group: "", Resource: "replicationcontrollers"}:        "controllers",
42	{Group: "", Resource: "endpoints"}:                     "services/endpoints",
43	{Group: "", Resource: "nodes"}:                         "minions",
44	{Group: "", Resource: "services"}:                      "services/specs",
45	{Group: "extensions", Resource: "ingresses"}:           "ingress",
46	{Group: "networking.k8s.io", Resource: "ingresses"}:    "ingress",
47	{Group: "extensions", Resource: "podsecuritypolicies"}: "podsecuritypolicy",
48	{Group: "policy", Resource: "podsecuritypolicies"}:     "podsecuritypolicy",
49}
50
51// DefaultWatchCacheSizes defines default resources for which watchcache
52// should be disabled.
53func DefaultWatchCacheSizes() map[schema.GroupResource]int {
54	return map[schema.GroupResource]int{
55		{Resource: "events"}:                         0,
56		{Group: "events.k8s.io", Resource: "events"}: 0,
57	}
58}
59
60// NewStorageFactoryConfig returns a new StorageFactoryConfig set up with necessary resource overrides.
61func NewStorageFactoryConfig() *StorageFactoryConfig {
62
63	resources := []schema.GroupVersionResource{
64		apisstorage.Resource("csistoragecapacities").WithVersion("v1beta1"),
65	}
66
67	return &StorageFactoryConfig{
68		Serializer:                legacyscheme.Codecs,
69		DefaultResourceEncoding:   serverstorage.NewDefaultResourceEncodingConfig(legacyscheme.Scheme),
70		ResourceEncodingOverrides: resources,
71	}
72}
73
74// StorageFactoryConfig is a configuration for creating storage factory.
75type StorageFactoryConfig struct {
76	StorageConfig                    storagebackend.Config
77	APIResourceConfig                *serverstorage.ResourceConfig
78	DefaultResourceEncoding          *serverstorage.DefaultResourceEncodingConfig
79	DefaultStorageMediaType          string
80	Serializer                       runtime.StorageSerializer
81	ResourceEncodingOverrides        []schema.GroupVersionResource
82	EtcdServersOverrides             []string
83	EncryptionProviderConfigFilepath string
84}
85
86// Complete completes the StorageFactoryConfig with provided etcdOptions returning completedStorageFactoryConfig.
87func (c *StorageFactoryConfig) Complete(etcdOptions *serveroptions.EtcdOptions) (*completedStorageFactoryConfig, error) {
88	c.StorageConfig = etcdOptions.StorageConfig
89	c.DefaultStorageMediaType = etcdOptions.DefaultStorageMediaType
90	c.EtcdServersOverrides = etcdOptions.EtcdServersOverrides
91	c.EncryptionProviderConfigFilepath = etcdOptions.EncryptionProviderConfigFilepath
92	return &completedStorageFactoryConfig{c}, nil
93}
94
95// completedStorageFactoryConfig is a wrapper around StorageFactoryConfig completed with etcd options.
96//
97// Note: this struct is intentionally unexported so that it can only be constructed via a StorageFactoryConfig.Complete
98// call. The implied consequence is that this does not comply with golint.
99type completedStorageFactoryConfig struct {
100	*StorageFactoryConfig
101}
102
103// New returns a new storage factory created from the completed storage factory configuration.
104func (c *completedStorageFactoryConfig) New() (*serverstorage.DefaultStorageFactory, error) {
105	resourceEncodingConfig := resourceconfig.MergeResourceEncodingConfigs(c.DefaultResourceEncoding, c.ResourceEncodingOverrides)
106	storageFactory := serverstorage.NewDefaultStorageFactory(
107		c.StorageConfig,
108		c.DefaultStorageMediaType,
109		c.Serializer,
110		resourceEncodingConfig,
111		c.APIResourceConfig,
112		SpecialDefaultResourcePrefixes)
113
114	storageFactory.AddCohabitatingResources(networking.Resource("networkpolicies"), extensions.Resource("networkpolicies"))
115	storageFactory.AddCohabitatingResources(apps.Resource("deployments"), extensions.Resource("deployments"))
116	storageFactory.AddCohabitatingResources(apps.Resource("daemonsets"), extensions.Resource("daemonsets"))
117	storageFactory.AddCohabitatingResources(apps.Resource("replicasets"), extensions.Resource("replicasets"))
118	storageFactory.AddCohabitatingResources(api.Resource("events"), events.Resource("events"))
119	storageFactory.AddCohabitatingResources(api.Resource("replicationcontrollers"), extensions.Resource("replicationcontrollers")) // to make scale subresources equivalent
120	storageFactory.AddCohabitatingResources(policy.Resource("podsecuritypolicies"), extensions.Resource("podsecuritypolicies"))
121	storageFactory.AddCohabitatingResources(networking.Resource("ingresses"), extensions.Resource("ingresses"))
122
123	for _, override := range c.EtcdServersOverrides {
124		tokens := strings.Split(override, "#")
125		apiresource := strings.Split(tokens[0], "/")
126
127		group := apiresource[0]
128		resource := apiresource[1]
129		groupResource := schema.GroupResource{Group: group, Resource: resource}
130
131		servers := strings.Split(tokens[1], ";")
132		storageFactory.SetEtcdLocation(groupResource, servers)
133	}
134	if len(c.EncryptionProviderConfigFilepath) != 0 {
135		transformerOverrides, err := encryptionconfig.GetTransformerOverrides(c.EncryptionProviderConfigFilepath)
136		if err != nil {
137			return nil, err
138		}
139		for groupResource, transformer := range transformerOverrides {
140			storageFactory.SetTransformer(groupResource, transformer)
141		}
142	}
143	return storageFactory, nil
144}
145