18
vendor/k8s.io/apiserver/pkg/server/storage/doc.go
generated
vendored
Normal file
18
vendor/k8s.io/apiserver/pkg/server/storage/doc.go
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package storage contains the plumbing to setup the etcd storage of the apiserver.
|
||||
package storage
|
||||
83
vendor/k8s.io/apiserver/pkg/server/storage/resource_config.go
generated
vendored
Normal file
83
vendor/k8s.io/apiserver/pkg/server/storage/resource_config.go
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package storage
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// APIResourceConfigSource is the interface to determine which groups and versions are enabled
|
||||
type APIResourceConfigSource interface {
|
||||
VersionEnabled(version schema.GroupVersion) bool
|
||||
AnyVersionForGroupEnabled(group string) bool
|
||||
}
|
||||
|
||||
var _ APIResourceConfigSource = &ResourceConfig{}
|
||||
|
||||
type ResourceConfig struct {
|
||||
GroupVersionConfigs map[schema.GroupVersion]bool
|
||||
}
|
||||
|
||||
func NewResourceConfig() *ResourceConfig {
|
||||
return &ResourceConfig{GroupVersionConfigs: map[schema.GroupVersion]bool{}}
|
||||
}
|
||||
|
||||
func (o *ResourceConfig) DisableAll() {
|
||||
for k := range o.GroupVersionConfigs {
|
||||
o.GroupVersionConfigs[k] = false
|
||||
}
|
||||
}
|
||||
|
||||
func (o *ResourceConfig) EnableAll() {
|
||||
for k := range o.GroupVersionConfigs {
|
||||
o.GroupVersionConfigs[k] = true
|
||||
}
|
||||
}
|
||||
|
||||
// DisableVersions disables the versions entirely.
|
||||
func (o *ResourceConfig) DisableVersions(versions ...schema.GroupVersion) {
|
||||
for _, version := range versions {
|
||||
o.GroupVersionConfigs[version] = false
|
||||
}
|
||||
}
|
||||
|
||||
func (o *ResourceConfig) EnableVersions(versions ...schema.GroupVersion) {
|
||||
for _, version := range versions {
|
||||
o.GroupVersionConfigs[version] = true
|
||||
}
|
||||
}
|
||||
|
||||
func (o *ResourceConfig) VersionEnabled(version schema.GroupVersion) bool {
|
||||
enabled, _ := o.GroupVersionConfigs[version]
|
||||
if enabled {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *ResourceConfig) AnyVersionForGroupEnabled(group string) bool {
|
||||
for version := range o.GroupVersionConfigs {
|
||||
if version.Group == group {
|
||||
if o.VersionEnabled(version) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
119
vendor/k8s.io/apiserver/pkg/server/storage/resource_encoding_config.go
generated
vendored
Normal file
119
vendor/k8s.io/apiserver/pkg/server/storage/resource_encoding_config.go
generated
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package storage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
type ResourceEncodingConfig interface {
|
||||
// StorageEncoding returns the serialization format for the resource.
|
||||
// TODO this should actually return a GroupVersionKind since you can logically have multiple "matching" Kinds
|
||||
// For now, it returns just the GroupVersion for consistency with old behavior
|
||||
StorageEncodingFor(schema.GroupResource) (schema.GroupVersion, error)
|
||||
|
||||
// InMemoryEncodingFor returns the groupVersion for the in memory representation the storage should convert to.
|
||||
InMemoryEncodingFor(schema.GroupResource) (schema.GroupVersion, error)
|
||||
}
|
||||
|
||||
type DefaultResourceEncodingConfig struct {
|
||||
groups map[string]*GroupResourceEncodingConfig
|
||||
scheme *runtime.Scheme
|
||||
}
|
||||
|
||||
type GroupResourceEncodingConfig struct {
|
||||
DefaultExternalEncoding schema.GroupVersion
|
||||
ExternalResourceEncodings map[string]schema.GroupVersion
|
||||
|
||||
DefaultInternalEncoding schema.GroupVersion
|
||||
InternalResourceEncodings map[string]schema.GroupVersion
|
||||
}
|
||||
|
||||
var _ ResourceEncodingConfig = &DefaultResourceEncodingConfig{}
|
||||
|
||||
func NewDefaultResourceEncodingConfig(scheme *runtime.Scheme) *DefaultResourceEncodingConfig {
|
||||
return &DefaultResourceEncodingConfig{groups: map[string]*GroupResourceEncodingConfig{}, scheme: scheme}
|
||||
}
|
||||
|
||||
func newGroupResourceEncodingConfig(defaultEncoding, defaultInternalVersion schema.GroupVersion) *GroupResourceEncodingConfig {
|
||||
return &GroupResourceEncodingConfig{
|
||||
DefaultExternalEncoding: defaultEncoding, ExternalResourceEncodings: map[string]schema.GroupVersion{},
|
||||
DefaultInternalEncoding: defaultInternalVersion, InternalResourceEncodings: map[string]schema.GroupVersion{},
|
||||
}
|
||||
}
|
||||
|
||||
func (o *DefaultResourceEncodingConfig) SetVersionEncoding(group string, externalEncodingVersion, internalVersion schema.GroupVersion) {
|
||||
_, groupExists := o.groups[group]
|
||||
if !groupExists {
|
||||
o.groups[group] = newGroupResourceEncodingConfig(externalEncodingVersion, internalVersion)
|
||||
}
|
||||
|
||||
o.groups[group].DefaultExternalEncoding = externalEncodingVersion
|
||||
o.groups[group].DefaultInternalEncoding = internalVersion
|
||||
}
|
||||
|
||||
func (o *DefaultResourceEncodingConfig) SetResourceEncoding(resourceBeingStored schema.GroupResource, externalEncodingVersion, internalVersion schema.GroupVersion) {
|
||||
group := resourceBeingStored.Group
|
||||
_, groupExists := o.groups[group]
|
||||
if !groupExists {
|
||||
o.groups[group] = newGroupResourceEncodingConfig(externalEncodingVersion, internalVersion)
|
||||
}
|
||||
|
||||
o.groups[group].ExternalResourceEncodings[resourceBeingStored.Resource] = externalEncodingVersion
|
||||
o.groups[group].InternalResourceEncodings[resourceBeingStored.Resource] = internalVersion
|
||||
}
|
||||
|
||||
func (o *DefaultResourceEncodingConfig) StorageEncodingFor(resource schema.GroupResource) (schema.GroupVersion, error) {
|
||||
if !o.scheme.IsGroupRegistered(resource.Group) {
|
||||
return schema.GroupVersion{}, fmt.Errorf("group %q is not registered in scheme", resource.Group)
|
||||
}
|
||||
|
||||
groupEncoding, groupExists := o.groups[resource.Group]
|
||||
|
||||
if !groupExists {
|
||||
// return the most preferred external version for the group
|
||||
return o.scheme.PrioritizedVersionsForGroup(resource.Group)[0], nil
|
||||
}
|
||||
|
||||
resourceOverride, resourceExists := groupEncoding.ExternalResourceEncodings[resource.Resource]
|
||||
if !resourceExists {
|
||||
return groupEncoding.DefaultExternalEncoding, nil
|
||||
}
|
||||
|
||||
return resourceOverride, nil
|
||||
}
|
||||
|
||||
func (o *DefaultResourceEncodingConfig) InMemoryEncodingFor(resource schema.GroupResource) (schema.GroupVersion, error) {
|
||||
if !o.scheme.IsGroupRegistered(resource.Group) {
|
||||
return schema.GroupVersion{}, fmt.Errorf("group %q is not registered in scheme", resource.Group)
|
||||
}
|
||||
|
||||
groupEncoding, groupExists := o.groups[resource.Group]
|
||||
if !groupExists {
|
||||
return schema.GroupVersion{Group: resource.Group, Version: runtime.APIVersionInternal}, nil
|
||||
}
|
||||
|
||||
resourceOverride, resourceExists := groupEncoding.InternalResourceEncodings[resource.Resource]
|
||||
if !resourceExists {
|
||||
return groupEncoding.DefaultInternalEncoding, nil
|
||||
}
|
||||
|
||||
return resourceOverride, nil
|
||||
}
|
||||
96
vendor/k8s.io/apiserver/pkg/server/storage/storage_codec.go
generated
vendored
Normal file
96
vendor/k8s.io/apiserver/pkg/server/storage/storage_codec.go
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package storage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mime"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer/recognizer"
|
||||
"k8s.io/apiserver/pkg/storage/storagebackend"
|
||||
)
|
||||
|
||||
// StorageCodecConfig are the arguments passed to newStorageCodecFn
|
||||
type StorageCodecConfig struct {
|
||||
StorageMediaType string
|
||||
StorageSerializer runtime.StorageSerializer
|
||||
StorageVersion schema.GroupVersion
|
||||
MemoryVersion schema.GroupVersion
|
||||
Config storagebackend.Config
|
||||
|
||||
EncoderDecoratorFn func(runtime.Encoder) runtime.Encoder
|
||||
DecoderDecoratorFn func([]runtime.Decoder) []runtime.Decoder
|
||||
}
|
||||
|
||||
// NewStorageCodec assembles a storage codec for the provided storage media type, the provided serializer, and the requested
|
||||
// storage and memory versions.
|
||||
func NewStorageCodec(opts StorageCodecConfig) (runtime.Codec, error) {
|
||||
mediaType, _, err := mime.ParseMediaType(opts.StorageMediaType)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%q is not a valid mime-type", opts.StorageMediaType)
|
||||
}
|
||||
|
||||
serializer, ok := runtime.SerializerInfoForMediaType(opts.StorageSerializer.SupportedMediaTypes(), mediaType)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unable to find serializer for %q", mediaType)
|
||||
}
|
||||
|
||||
s := serializer.Serializer
|
||||
|
||||
// Give callers the opportunity to wrap encoders and decoders. For decoders, each returned decoder will
|
||||
// be passed to the recognizer so that multiple decoders are available.
|
||||
var encoder runtime.Encoder = s
|
||||
if opts.EncoderDecoratorFn != nil {
|
||||
encoder = opts.EncoderDecoratorFn(encoder)
|
||||
}
|
||||
decoders := []runtime.Decoder{
|
||||
// selected decoder as the primary
|
||||
s,
|
||||
// universal deserializer as a fallback
|
||||
opts.StorageSerializer.UniversalDeserializer(),
|
||||
// base64-wrapped universal deserializer as a last resort.
|
||||
// this allows reading base64-encoded protobuf, which should only exist if etcd2+protobuf was used at some point.
|
||||
// data written that way could exist in etcd2, or could have been migrated to etcd3.
|
||||
// TODO: flag this type of data if we encounter it, require migration (read to decode, write to persist using a supported encoder), and remove in 1.8
|
||||
runtime.NewBase64Serializer(nil, opts.StorageSerializer.UniversalDeserializer()),
|
||||
}
|
||||
if opts.DecoderDecoratorFn != nil {
|
||||
decoders = opts.DecoderDecoratorFn(decoders)
|
||||
}
|
||||
|
||||
// Ensure the storage receives the correct version.
|
||||
encoder = opts.StorageSerializer.EncoderForVersion(
|
||||
encoder,
|
||||
runtime.NewMultiGroupVersioner(
|
||||
opts.StorageVersion,
|
||||
schema.GroupKind{Group: opts.StorageVersion.Group},
|
||||
schema.GroupKind{Group: opts.MemoryVersion.Group},
|
||||
),
|
||||
)
|
||||
decoder := opts.StorageSerializer.DecoderToVersion(
|
||||
recognizer.NewDecoder(decoders...),
|
||||
runtime.NewCoercingMultiGroupVersioner(
|
||||
opts.MemoryVersion,
|
||||
schema.GroupKind{Group: opts.MemoryVersion.Group},
|
||||
schema.GroupKind{Group: opts.StorageVersion.Group},
|
||||
),
|
||||
)
|
||||
|
||||
return runtime.NewCodec(encoder, decoder), nil
|
||||
}
|
||||
350
vendor/k8s.io/apiserver/pkg/server/storage/storage_factory.go
generated
vendored
Normal file
350
vendor/k8s.io/apiserver/pkg/server/storage/storage_factory.go
generated
vendored
Normal file
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package storage
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"k8s.io/klog"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apiserver/pkg/features"
|
||||
"k8s.io/apiserver/pkg/storage/storagebackend"
|
||||
"k8s.io/apiserver/pkg/storage/value"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
)
|
||||
|
||||
// Backend describes the storage servers, the information here should be enough
|
||||
// for health validations.
|
||||
type Backend struct {
|
||||
// the url of storage backend like: https://etcd.domain:2379
|
||||
Server string
|
||||
// the required tls config
|
||||
TLSConfig *tls.Config
|
||||
}
|
||||
|
||||
// StorageFactory is the interface to locate the storage for a given GroupResource
|
||||
type StorageFactory interface {
|
||||
// New finds the storage destination for the given group and resource. It will
|
||||
// return an error if the group has no storage destination configured.
|
||||
NewConfig(groupResource schema.GroupResource) (*storagebackend.Config, error)
|
||||
|
||||
// ResourcePrefix returns the overridden resource prefix for the GroupResource
|
||||
// This allows for cohabitation of resources with different native types and provides
|
||||
// centralized control over the shape of etcd directories
|
||||
ResourcePrefix(groupResource schema.GroupResource) string
|
||||
|
||||
// Backends gets all backends for all registered storage destinations.
|
||||
// Used for getting all instances for health validations.
|
||||
Backends() []Backend
|
||||
}
|
||||
|
||||
// DefaultStorageFactory takes a GroupResource and returns back its storage interface. This result includes:
|
||||
// 1. Merged etcd config, including: auth, server locations, prefixes
|
||||
// 2. Resource encodings for storage: group,version,kind to store as
|
||||
// 3. Cohabitating default: some resources like hpa are exposed through multiple APIs. They must agree on 1 and 2
|
||||
type DefaultStorageFactory struct {
|
||||
// StorageConfig describes how to create a storage backend in general.
|
||||
// Its authentication information will be used for every storage.Interface returned.
|
||||
StorageConfig storagebackend.Config
|
||||
|
||||
Overrides map[schema.GroupResource]groupResourceOverrides
|
||||
|
||||
DefaultResourcePrefixes map[schema.GroupResource]string
|
||||
|
||||
// DefaultMediaType is the media type used to store resources. If it is not set, "application/json" is used.
|
||||
DefaultMediaType string
|
||||
|
||||
// DefaultSerializer is used to create encoders and decoders for the storage.Interface.
|
||||
DefaultSerializer runtime.StorageSerializer
|
||||
|
||||
// ResourceEncodingConfig describes how to encode a particular GroupVersionResource
|
||||
ResourceEncodingConfig ResourceEncodingConfig
|
||||
|
||||
// APIResourceConfigSource indicates whether the *storage* is enabled, NOT the API
|
||||
// This is discrete from resource enablement because those are separate concerns. How this source is configured
|
||||
// is left to the caller.
|
||||
APIResourceConfigSource APIResourceConfigSource
|
||||
|
||||
// newStorageCodecFn exists to be overwritten for unit testing.
|
||||
newStorageCodecFn func(opts StorageCodecConfig) (codec runtime.Codec, err error)
|
||||
}
|
||||
|
||||
type groupResourceOverrides struct {
|
||||
// etcdLocation contains the list of "special" locations that are used for particular GroupResources
|
||||
// These are merged on top of the StorageConfig when requesting the storage.Interface for a given GroupResource
|
||||
etcdLocation []string
|
||||
// etcdPrefix is the base location for a GroupResource.
|
||||
etcdPrefix string
|
||||
// etcdResourcePrefix is the location to use to store a particular type under the `etcdPrefix` location
|
||||
// If empty, the default mapping is used. If the default mapping doesn't contain an entry, it will use
|
||||
// the ToLowered name of the resource, not including the group.
|
||||
etcdResourcePrefix string
|
||||
// mediaType is the desired serializer to choose. If empty, the default is chosen.
|
||||
mediaType string
|
||||
// serializer contains the list of "special" serializers for a GroupResource. Resource=* means for the entire group
|
||||
serializer runtime.StorageSerializer
|
||||
// cohabitatingResources keeps track of which resources must be stored together. This happens when we have multiple ways
|
||||
// of exposing one set of concepts. autoscaling.HPA and extensions.HPA as a for instance
|
||||
// The order of the slice matters! It is the priority order of lookup for finding a storage location
|
||||
cohabitatingResources []schema.GroupResource
|
||||
// encoderDecoratorFn is optional and may wrap the provided encoder prior to being serialized.
|
||||
encoderDecoratorFn func(runtime.Encoder) runtime.Encoder
|
||||
// decoderDecoratorFn is optional and may wrap the provided decoders (can add new decoders). The order of
|
||||
// returned decoders will be priority for attempt to decode.
|
||||
decoderDecoratorFn func([]runtime.Decoder) []runtime.Decoder
|
||||
// transformer is optional and shall encrypt that resource at rest.
|
||||
transformer value.Transformer
|
||||
// disablePaging will prevent paging on the provided resource.
|
||||
disablePaging bool
|
||||
}
|
||||
|
||||
// Apply overrides the provided config and options if the override has a value in that position
|
||||
func (o groupResourceOverrides) Apply(config *storagebackend.Config, options *StorageCodecConfig) {
|
||||
if len(o.etcdLocation) > 0 {
|
||||
config.ServerList = o.etcdLocation
|
||||
}
|
||||
if len(o.etcdPrefix) > 0 {
|
||||
config.Prefix = o.etcdPrefix
|
||||
}
|
||||
|
||||
if len(o.mediaType) > 0 {
|
||||
options.StorageMediaType = o.mediaType
|
||||
}
|
||||
if o.serializer != nil {
|
||||
options.StorageSerializer = o.serializer
|
||||
}
|
||||
if o.encoderDecoratorFn != nil {
|
||||
options.EncoderDecoratorFn = o.encoderDecoratorFn
|
||||
}
|
||||
if o.decoderDecoratorFn != nil {
|
||||
options.DecoderDecoratorFn = o.decoderDecoratorFn
|
||||
}
|
||||
if o.transformer != nil {
|
||||
config.Transformer = o.transformer
|
||||
}
|
||||
if o.disablePaging {
|
||||
config.Paging = false
|
||||
}
|
||||
}
|
||||
|
||||
var _ StorageFactory = &DefaultStorageFactory{}
|
||||
|
||||
const AllResources = "*"
|
||||
|
||||
func NewDefaultStorageFactory(
|
||||
config storagebackend.Config,
|
||||
defaultMediaType string,
|
||||
defaultSerializer runtime.StorageSerializer,
|
||||
resourceEncodingConfig ResourceEncodingConfig,
|
||||
resourceConfig APIResourceConfigSource,
|
||||
specialDefaultResourcePrefixes map[schema.GroupResource]string,
|
||||
) *DefaultStorageFactory {
|
||||
config.Paging = utilfeature.DefaultFeatureGate.Enabled(features.APIListChunking)
|
||||
if len(defaultMediaType) == 0 {
|
||||
defaultMediaType = runtime.ContentTypeJSON
|
||||
}
|
||||
return &DefaultStorageFactory{
|
||||
StorageConfig: config,
|
||||
Overrides: map[schema.GroupResource]groupResourceOverrides{},
|
||||
DefaultMediaType: defaultMediaType,
|
||||
DefaultSerializer: defaultSerializer,
|
||||
ResourceEncodingConfig: resourceEncodingConfig,
|
||||
APIResourceConfigSource: resourceConfig,
|
||||
DefaultResourcePrefixes: specialDefaultResourcePrefixes,
|
||||
|
||||
newStorageCodecFn: NewStorageCodec,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DefaultStorageFactory) SetEtcdLocation(groupResource schema.GroupResource, location []string) {
|
||||
overrides := s.Overrides[groupResource]
|
||||
overrides.etcdLocation = location
|
||||
s.Overrides[groupResource] = overrides
|
||||
}
|
||||
|
||||
func (s *DefaultStorageFactory) SetEtcdPrefix(groupResource schema.GroupResource, prefix string) {
|
||||
overrides := s.Overrides[groupResource]
|
||||
overrides.etcdPrefix = prefix
|
||||
s.Overrides[groupResource] = overrides
|
||||
}
|
||||
|
||||
// SetDisableAPIListChunking allows a specific resource to disable paging at the storage layer, to prevent
|
||||
// exposure of key names in continuations. This may be overridden by feature gates.
|
||||
func (s *DefaultStorageFactory) SetDisableAPIListChunking(groupResource schema.GroupResource) {
|
||||
overrides := s.Overrides[groupResource]
|
||||
overrides.disablePaging = true
|
||||
s.Overrides[groupResource] = overrides
|
||||
}
|
||||
|
||||
// SetResourceEtcdPrefix sets the prefix for a resource, but not the base-dir. You'll end up in `etcdPrefix/resourceEtcdPrefix`.
|
||||
func (s *DefaultStorageFactory) SetResourceEtcdPrefix(groupResource schema.GroupResource, prefix string) {
|
||||
overrides := s.Overrides[groupResource]
|
||||
overrides.etcdResourcePrefix = prefix
|
||||
s.Overrides[groupResource] = overrides
|
||||
}
|
||||
|
||||
func (s *DefaultStorageFactory) SetSerializer(groupResource schema.GroupResource, mediaType string, serializer runtime.StorageSerializer) {
|
||||
overrides := s.Overrides[groupResource]
|
||||
overrides.mediaType = mediaType
|
||||
overrides.serializer = serializer
|
||||
s.Overrides[groupResource] = overrides
|
||||
}
|
||||
|
||||
func (s *DefaultStorageFactory) SetTransformer(groupResource schema.GroupResource, transformer value.Transformer) {
|
||||
overrides := s.Overrides[groupResource]
|
||||
overrides.transformer = transformer
|
||||
s.Overrides[groupResource] = overrides
|
||||
}
|
||||
|
||||
// AddCohabitatingResources links resources together the order of the slice matters! its the priority order of lookup for finding a storage location
|
||||
func (s *DefaultStorageFactory) AddCohabitatingResources(groupResources ...schema.GroupResource) {
|
||||
for _, groupResource := range groupResources {
|
||||
overrides := s.Overrides[groupResource]
|
||||
overrides.cohabitatingResources = groupResources
|
||||
s.Overrides[groupResource] = overrides
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DefaultStorageFactory) AddSerializationChains(encoderDecoratorFn func(runtime.Encoder) runtime.Encoder, decoderDecoratorFn func([]runtime.Decoder) []runtime.Decoder, groupResources ...schema.GroupResource) {
|
||||
for _, groupResource := range groupResources {
|
||||
overrides := s.Overrides[groupResource]
|
||||
overrides.encoderDecoratorFn = encoderDecoratorFn
|
||||
overrides.decoderDecoratorFn = decoderDecoratorFn
|
||||
s.Overrides[groupResource] = overrides
|
||||
}
|
||||
}
|
||||
|
||||
func getAllResourcesAlias(resource schema.GroupResource) schema.GroupResource {
|
||||
return schema.GroupResource{Group: resource.Group, Resource: AllResources}
|
||||
}
|
||||
|
||||
func (s *DefaultStorageFactory) getStorageGroupResource(groupResource schema.GroupResource) schema.GroupResource {
|
||||
for _, potentialStorageResource := range s.Overrides[groupResource].cohabitatingResources {
|
||||
if s.APIResourceConfigSource.AnyVersionForGroupEnabled(potentialStorageResource.Group) {
|
||||
return potentialStorageResource
|
||||
}
|
||||
}
|
||||
|
||||
return groupResource
|
||||
}
|
||||
|
||||
// New finds the storage destination for the given group and resource. It will
|
||||
// return an error if the group has no storage destination configured.
|
||||
func (s *DefaultStorageFactory) NewConfig(groupResource schema.GroupResource) (*storagebackend.Config, error) {
|
||||
chosenStorageResource := s.getStorageGroupResource(groupResource)
|
||||
|
||||
// operate on copy
|
||||
storageConfig := s.StorageConfig
|
||||
codecConfig := StorageCodecConfig{
|
||||
StorageMediaType: s.DefaultMediaType,
|
||||
StorageSerializer: s.DefaultSerializer,
|
||||
}
|
||||
|
||||
if override, ok := s.Overrides[getAllResourcesAlias(chosenStorageResource)]; ok {
|
||||
override.Apply(&storageConfig, &codecConfig)
|
||||
}
|
||||
if override, ok := s.Overrides[chosenStorageResource]; ok {
|
||||
override.Apply(&storageConfig, &codecConfig)
|
||||
}
|
||||
|
||||
var err error
|
||||
codecConfig.StorageVersion, err = s.ResourceEncodingConfig.StorageEncodingFor(chosenStorageResource)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
codecConfig.MemoryVersion, err = s.ResourceEncodingConfig.InMemoryEncodingFor(groupResource)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
codecConfig.Config = storageConfig
|
||||
|
||||
storageConfig.Codec, err = s.newStorageCodecFn(codecConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
klog.V(3).Infof("storing %v in %v, reading as %v from %#v", groupResource, codecConfig.StorageVersion, codecConfig.MemoryVersion, codecConfig.Config)
|
||||
|
||||
return &storageConfig, nil
|
||||
}
|
||||
|
||||
// Backends returns all backends for all registered storage destinations.
|
||||
// Used for getting all instances for health validations.
|
||||
func (s *DefaultStorageFactory) Backends() []Backend {
|
||||
servers := sets.NewString(s.StorageConfig.ServerList...)
|
||||
|
||||
for _, overrides := range s.Overrides {
|
||||
servers.Insert(overrides.etcdLocation...)
|
||||
}
|
||||
|
||||
tlsConfig := &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
if len(s.StorageConfig.CertFile) > 0 && len(s.StorageConfig.KeyFile) > 0 {
|
||||
cert, err := tls.LoadX509KeyPair(s.StorageConfig.CertFile, s.StorageConfig.KeyFile)
|
||||
if err != nil {
|
||||
klog.Errorf("failed to load key pair while getting backends: %s", err)
|
||||
} else {
|
||||
tlsConfig.Certificates = []tls.Certificate{cert}
|
||||
}
|
||||
}
|
||||
if len(s.StorageConfig.CAFile) > 0 {
|
||||
if caCert, err := ioutil.ReadFile(s.StorageConfig.CAFile); err != nil {
|
||||
klog.Errorf("failed to read ca file while getting backends: %s", err)
|
||||
} else {
|
||||
caPool := x509.NewCertPool()
|
||||
caPool.AppendCertsFromPEM(caCert)
|
||||
tlsConfig.RootCAs = caPool
|
||||
tlsConfig.InsecureSkipVerify = false
|
||||
}
|
||||
}
|
||||
|
||||
backends := []Backend{}
|
||||
for server := range servers {
|
||||
backends = append(backends, Backend{
|
||||
Server: server,
|
||||
// We can't share TLSConfig across different backends to avoid races.
|
||||
// For more details see: http://pr.k8s.io/59338
|
||||
TLSConfig: tlsConfig.Clone(),
|
||||
})
|
||||
}
|
||||
return backends
|
||||
}
|
||||
|
||||
func (s *DefaultStorageFactory) ResourcePrefix(groupResource schema.GroupResource) string {
|
||||
chosenStorageResource := s.getStorageGroupResource(groupResource)
|
||||
groupOverride := s.Overrides[getAllResourcesAlias(chosenStorageResource)]
|
||||
exactResourceOverride := s.Overrides[chosenStorageResource]
|
||||
|
||||
etcdResourcePrefix := s.DefaultResourcePrefixes[chosenStorageResource]
|
||||
if len(groupOverride.etcdResourcePrefix) > 0 {
|
||||
etcdResourcePrefix = groupOverride.etcdResourcePrefix
|
||||
}
|
||||
if len(exactResourceOverride.etcdResourcePrefix) > 0 {
|
||||
etcdResourcePrefix = exactResourceOverride.etcdResourcePrefix
|
||||
}
|
||||
if len(etcdResourcePrefix) == 0 {
|
||||
etcdResourcePrefix = strings.ToLower(chosenStorageResource.Resource)
|
||||
}
|
||||
|
||||
return etcdResourcePrefix
|
||||
}
|
||||
Reference in New Issue
Block a user