Commit 75887829 authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #41136 from deads2k/apiserver-10-example

Automatic merge from submit-queue (batch tested with PRs 41121, 40048, 40502, 41136, 40759) add k8s.io/sample-apiserver to demonstrate how to build an aggregated API server builds on https://github.com/kubernetes/kubernetes/pull/41093 This creates a sample API server is a separate staging repo to guarantee no cheating with `k8s.io/kubernetes` dependencies. The sample is run during integration tests (simple tests on it so far) to ensure that it continues to run. @sttts @kubernetes/sig-api-machinery-misc ptal @pwittrock @pmorie @kris-nova an aggregated API server example that will stay up to date.
parents 2bd777e9 7cb5463b
...@@ -68,7 +68,6 @@ go_library( ...@@ -68,7 +68,6 @@ go_library(
"//vendor:k8s.io/apiserver/pkg/endpoints/filters", "//vendor:k8s.io/apiserver/pkg/endpoints/filters",
"//vendor:k8s.io/apiserver/pkg/endpoints/handlers/responsewriters", "//vendor:k8s.io/apiserver/pkg/endpoints/handlers/responsewriters",
"//vendor:k8s.io/apiserver/pkg/endpoints/request", "//vendor:k8s.io/apiserver/pkg/endpoints/request",
"//vendor:k8s.io/apiserver/pkg/registry/generic",
"//vendor:k8s.io/apiserver/pkg/registry/generic/rest", "//vendor:k8s.io/apiserver/pkg/registry/generic/rest",
"//vendor:k8s.io/apiserver/pkg/registry/rest", "//vendor:k8s.io/apiserver/pkg/registry/rest",
"//vendor:k8s.io/apiserver/pkg/server", "//vendor:k8s.io/apiserver/pkg/server",
......
...@@ -24,7 +24,6 @@ import ( ...@@ -24,7 +24,6 @@ import (
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
genericapifilters "k8s.io/apiserver/pkg/endpoints/filters" genericapifilters "k8s.io/apiserver/pkg/endpoints/filters"
genericapirequest "k8s.io/apiserver/pkg/endpoints/request" genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/registry/rest"
genericapiserver "k8s.io/apiserver/pkg/server" genericapiserver "k8s.io/apiserver/pkg/server"
genericfilters "k8s.io/apiserver/pkg/server/filters" genericfilters "k8s.io/apiserver/pkg/server/filters"
...@@ -54,9 +53,6 @@ type Config struct { ...@@ -54,9 +53,6 @@ type Config struct {
// this to confirm the proxy's identity // this to confirm the proxy's identity
ProxyClientCert []byte ProxyClientCert []byte
ProxyClientKey []byte ProxyClientKey []byte
// RESTOptionsGetter is used to construct storage for a particular resource
RESTOptionsGetter generic.RESTOptionsGetter
} }
// APIAggregator contains state for a Kubernetes cluster master/api server. // APIAggregator contains state for a Kubernetes cluster master/api server.
...@@ -144,7 +140,7 @@ func (c completedConfig) New() (*APIAggregator, error) { ...@@ -144,7 +140,7 @@ func (c completedConfig) New() (*APIAggregator, error) {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apiregistration.GroupName, api.Registry, api.Scheme, api.ParameterCodec, api.Codecs) apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apiregistration.GroupName, api.Registry, api.Scheme, api.ParameterCodec, api.Codecs)
apiGroupInfo.GroupMeta.GroupVersion = v1alpha1.SchemeGroupVersion apiGroupInfo.GroupMeta.GroupVersion = v1alpha1.SchemeGroupVersion
v1alpha1storage := map[string]rest.Storage{} v1alpha1storage := map[string]rest.Storage{}
v1alpha1storage["apiservices"] = apiservicestorage.NewREST(c.RESTOptionsGetter) v1alpha1storage["apiservices"] = apiservicestorage.NewREST(c.GenericConfig.RESTOptionsGetter)
apiGroupInfo.VersionedResourcesStorageMap["v1alpha1"] = v1alpha1storage apiGroupInfo.VersionedResourcesStorageMap["v1alpha1"] = v1alpha1storage
if err := s.GenericAPIServer.InstallAPIGroup(&apiGroupInfo); err != nil { if err := s.GenericAPIServer.InstallAPIGroup(&apiGroupInfo); err != nil {
......
...@@ -19,15 +19,11 @@ go_library( ...@@ -19,15 +19,11 @@ go_library(
"//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/cmd/util:go_default_library",
"//vendor:github.com/pborman/uuid", "//vendor:github.com/pborman/uuid",
"//vendor:github.com/spf13/cobra", "//vendor:github.com/spf13/cobra",
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
"//vendor:k8s.io/apimachinery/pkg/util/sets", "//vendor:k8s.io/apimachinery/pkg/util/sets",
"//vendor:k8s.io/apimachinery/pkg/util/wait", "//vendor:k8s.io/apimachinery/pkg/util/wait",
"//vendor:k8s.io/apiserver/pkg/registry/generic",
"//vendor:k8s.io/apiserver/pkg/registry/generic/registry",
"//vendor:k8s.io/apiserver/pkg/server", "//vendor:k8s.io/apiserver/pkg/server",
"//vendor:k8s.io/apiserver/pkg/server/filters", "//vendor:k8s.io/apiserver/pkg/server/filters",
"//vendor:k8s.io/apiserver/pkg/server/options", "//vendor:k8s.io/apiserver/pkg/server/options",
"//vendor:k8s.io/apiserver/pkg/storage/storagebackend",
"//vendor:k8s.io/client-go/rest", "//vendor:k8s.io/client-go/rest",
], ],
) )
......
...@@ -24,15 +24,11 @@ import ( ...@@ -24,15 +24,11 @@ import (
"github.com/pborman/uuid" "github.com/pborman/uuid"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/registry/generic/registry"
genericapiserver "k8s.io/apiserver/pkg/server" genericapiserver "k8s.io/apiserver/pkg/server"
"k8s.io/apiserver/pkg/server/filters" "k8s.io/apiserver/pkg/server/filters"
genericoptions "k8s.io/apiserver/pkg/server/options" genericoptions "k8s.io/apiserver/pkg/server/options"
"k8s.io/apiserver/pkg/storage/storagebackend"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/kubernetes/cmd/kube-aggregator/pkg/apiserver" "k8s.io/kubernetes/cmd/kube-aggregator/pkg/apiserver"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
...@@ -59,14 +55,11 @@ type AggregatorOptions struct { ...@@ -59,14 +55,11 @@ type AggregatorOptions struct {
// NewCommandStartMaster provides a CLI handler for 'start master' command // NewCommandStartMaster provides a CLI handler for 'start master' command
func NewCommandStartAggregator(out, err io.Writer) *cobra.Command { func NewCommandStartAggregator(out, err io.Writer) *cobra.Command {
o := &AggregatorOptions{ o := &AggregatorOptions{
RecommendedOptions: genericoptions.NewRecommendedOptions(api.Scheme), RecommendedOptions: genericoptions.NewRecommendedOptions(defaultEtcdPathPrefix, api.Scheme, api.Codecs.LegacyCodec(v1alpha1.SchemeGroupVersion)),
StdOut: out, StdOut: out,
StdErr: err, StdErr: err,
} }
o.RecommendedOptions.Etcd.StorageConfig.Type = storagebackend.StorageTypeETCD3
o.RecommendedOptions.Etcd.StorageConfig.Prefix = defaultEtcdPathPrefix
o.RecommendedOptions.Etcd.StorageConfig.Codec = api.Codecs.LegacyCodec(v1alpha1.SchemeGroupVersion)
o.RecommendedOptions.SecureServing.ServingOptions.BindPort = 443 o.RecommendedOptions.SecureServing.ServingOptions.BindPort = 443
cmd := &cobra.Command{ cmd := &cobra.Command{
...@@ -129,7 +122,6 @@ func (o AggregatorOptions) RunAggregator() error { ...@@ -129,7 +122,6 @@ func (o AggregatorOptions) RunAggregator() error {
config := apiserver.Config{ config := apiserver.Config{
GenericConfig: serverConfig, GenericConfig: serverConfig,
RESTOptionsGetter: &restOptionsFactory{storageConfig: &o.RecommendedOptions.Etcd.StorageConfig},
CoreAPIServerClient: coreAPIServerClient, CoreAPIServerClient: coreAPIServerClient,
} }
...@@ -150,17 +142,3 @@ func (o AggregatorOptions) RunAggregator() error { ...@@ -150,17 +142,3 @@ func (o AggregatorOptions) RunAggregator() error {
return nil return nil
} }
type restOptionsFactory struct {
storageConfig *storagebackend.Config
}
func (f *restOptionsFactory) GetRESTOptions(resource schema.GroupResource) (generic.RESTOptions, error) {
return generic.RESTOptions{
StorageConfig: f.storageConfig,
Decorator: registry.StorageWithCacher,
DeleteCollectionWorkers: 1,
EnableGarbageCollection: false,
ResourcePrefix: f.storageConfig.Prefix + "/" + resource.Group + "/" + resource.Resource,
}, nil
}
...@@ -68,7 +68,7 @@ type ServerRunOptions struct { ...@@ -68,7 +68,7 @@ type ServerRunOptions struct {
func NewServerRunOptions() *ServerRunOptions { func NewServerRunOptions() *ServerRunOptions {
s := ServerRunOptions{ s := ServerRunOptions{
GenericServerRunOptions: genericoptions.NewServerRunOptions(), GenericServerRunOptions: genericoptions.NewServerRunOptions(),
Etcd: genericoptions.NewEtcdOptions(api.Scheme), Etcd: genericoptions.NewEtcdOptions(kubeoptions.DefaultEtcdPathPrefix, api.Scheme, nil),
SecureServing: genericoptions.NewSecureServingOptions(), SecureServing: genericoptions.NewSecureServingOptions(),
InsecureServing: genericoptions.NewInsecureServingOptions(), InsecureServing: genericoptions.NewInsecureServingOptions(),
Audit: genericoptions.NewAuditLogOptions(), Audit: genericoptions.NewAuditLogOptions(),
......
...@@ -315,15 +315,19 @@ func Run(s *options.ServerRunOptions) error { ...@@ -315,15 +315,19 @@ func Run(s *options.ServerRunOptions) error {
sets.NewString("watch", "proxy"), sets.NewString("watch", "proxy"),
sets.NewString("attach", "exec", "proxy", "log", "portforward"), sets.NewString("attach", "exec", "proxy", "log", "portforward"),
) )
genericConfig.RESTOptionsGetter = &kubeapiserver.RESTOptionsFactory{
StorageFactory: storageFactory,
EnableWatchCache: s.Etcd.EnableWatchCache,
EnableGarbageCollection: s.Etcd.EnableGarbageCollection,
DeleteCollectionWorkers: s.Etcd.DeleteCollectionWorkers,
}
config := &master.Config{ config := &master.Config{
GenericConfig: genericConfig, GenericConfig: genericConfig,
APIResourceConfigSource: storageFactory.APIResourceConfigSource, APIResourceConfigSource: storageFactory.APIResourceConfigSource,
StorageFactory: storageFactory, StorageFactory: storageFactory,
EnableWatchCache: s.GenericServerRunOptions.EnableWatchCache,
EnableCoreControllers: true, EnableCoreControllers: true,
DeleteCollectionWorkers: s.GenericServerRunOptions.DeleteCollectionWorkers,
EventTTL: s.EventTTL, EventTTL: s.EventTTL,
KubeletClientConfig: s.KubeletConfig, KubeletClientConfig: s.KubeletConfig,
EnableUISupport: true, EnableUISupport: true,
...@@ -342,7 +346,7 @@ func Run(s *options.ServerRunOptions) error { ...@@ -342,7 +346,7 @@ func Run(s *options.ServerRunOptions) error {
MasterCount: s.MasterCount, MasterCount: s.MasterCount,
} }
if s.GenericServerRunOptions.EnableWatchCache { if s.Etcd.EnableWatchCache {
glog.V(2).Infof("Initializing cache sizes based on %dMB limit", s.GenericServerRunOptions.TargetRAMMB) glog.V(2).Infof("Initializing cache sizes based on %dMB limit", s.GenericServerRunOptions.TargetRAMMB)
cachesize.InitializeWatchCacheSizes(s.GenericServerRunOptions.TargetRAMMB) cachesize.InitializeWatchCacheSizes(s.GenericServerRunOptions.TargetRAMMB)
cachesize.SetWatchCacheSizes(s.GenericServerRunOptions.WatchCacheSizes) cachesize.SetWatchCacheSizes(s.GenericServerRunOptions.WatchCacheSizes)
......
...@@ -47,7 +47,7 @@ const ( ...@@ -47,7 +47,7 @@ const (
func newStorageFactory() genericapiserver.StorageFactory { func newStorageFactory() genericapiserver.StorageFactory {
config := storagebackend.Config{ config := storagebackend.Config{
Prefix: genericoptions.DefaultEtcdPathPrefix, Prefix: kubeoptions.DefaultEtcdPathPrefix,
ServerList: []string{"http://127.0.0.1:2379"}, ServerList: []string{"http://127.0.0.1:2379"},
Copier: api.Scheme, Copier: api.Scheme,
} }
...@@ -68,7 +68,7 @@ type ServerRunOptions struct { ...@@ -68,7 +68,7 @@ type ServerRunOptions struct {
func NewServerRunOptions() *ServerRunOptions { func NewServerRunOptions() *ServerRunOptions {
s := ServerRunOptions{ s := ServerRunOptions{
GenericServerRunOptions: genericoptions.NewServerRunOptions(), GenericServerRunOptions: genericoptions.NewServerRunOptions(),
Etcd: genericoptions.NewEtcdOptions(api.Scheme), Etcd: genericoptions.NewEtcdOptions(kubeoptions.DefaultEtcdPathPrefix, api.Scheme, nil),
SecureServing: genericoptions.NewSecureServingOptions(), SecureServing: genericoptions.NewSecureServingOptions(),
InsecureServing: genericoptions.NewInsecureServingOptions(), InsecureServing: genericoptions.NewInsecureServingOptions(),
Authentication: kubeoptions.NewBuiltInAuthenticationOptions().WithAll(), Authentication: kubeoptions.NewBuiltInAuthenticationOptions().WithAll(),
......
...@@ -71,7 +71,6 @@ go_library( ...@@ -71,7 +71,6 @@ go_library(
"//vendor:k8s.io/apimachinery/pkg/util/wait", "//vendor:k8s.io/apimachinery/pkg/util/wait",
"//vendor:k8s.io/apiserver/pkg/admission", "//vendor:k8s.io/apiserver/pkg/admission",
"//vendor:k8s.io/apiserver/pkg/registry/generic", "//vendor:k8s.io/apiserver/pkg/registry/generic",
"//vendor:k8s.io/apiserver/pkg/registry/generic/registry",
"//vendor:k8s.io/apiserver/pkg/registry/rest", "//vendor:k8s.io/apiserver/pkg/registry/rest",
"//vendor:k8s.io/apiserver/pkg/server", "//vendor:k8s.io/apiserver/pkg/server",
"//vendor:k8s.io/apiserver/pkg/server/filters", "//vendor:k8s.io/apiserver/pkg/server/filters",
......
...@@ -51,7 +51,7 @@ type ServerRunOptions struct { ...@@ -51,7 +51,7 @@ type ServerRunOptions struct {
func NewServerRunOptions() *ServerRunOptions { func NewServerRunOptions() *ServerRunOptions {
s := ServerRunOptions{ s := ServerRunOptions{
GenericServerRunOptions: genericoptions.NewServerRunOptions(), GenericServerRunOptions: genericoptions.NewServerRunOptions(),
Etcd: genericoptions.NewEtcdOptions(api.Scheme), Etcd: genericoptions.NewEtcdOptions(kubeoptions.DefaultEtcdPathPrefix, api.Scheme, nil),
SecureServing: genericoptions.NewSecureServingOptions(), SecureServing: genericoptions.NewSecureServingOptions(),
InsecureServing: genericoptions.NewInsecureServingOptions(), InsecureServing: genericoptions.NewInsecureServingOptions(),
Audit: genericoptions.NewAuditLogOptions(), Audit: genericoptions.NewAuditLogOptions(),
......
...@@ -36,8 +36,6 @@ import ( ...@@ -36,8 +36,6 @@ import (
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/registry/generic"
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
genericapiserver "k8s.io/apiserver/pkg/server" genericapiserver "k8s.io/apiserver/pkg/server"
"k8s.io/apiserver/pkg/server/filters" "k8s.io/apiserver/pkg/server/filters"
"k8s.io/kubernetes/federation/cmd/federation-apiserver/app/options" "k8s.io/kubernetes/federation/cmd/federation-apiserver/app/options"
...@@ -196,9 +194,15 @@ func Run(s *options.ServerRunOptions) error { ...@@ -196,9 +194,15 @@ func Run(s *options.ServerRunOptions) error {
sets.NewString("watch", "proxy"), sets.NewString("watch", "proxy"),
sets.NewString("attach", "exec", "proxy", "log", "portforward"), sets.NewString("attach", "exec", "proxy", "log", "portforward"),
) )
genericConfig.RESTOptionsGetter = &kubeapiserver.RESTOptionsFactory{
StorageFactory: storageFactory,
EnableWatchCache: s.Etcd.EnableWatchCache,
EnableGarbageCollection: s.Etcd.EnableGarbageCollection,
DeleteCollectionWorkers: s.Etcd.DeleteCollectionWorkers,
}
// TODO: Move this to generic api server (Need to move the command line flag). // TODO: Move this to generic api server (Need to move the command line flag).
if s.GenericServerRunOptions.EnableWatchCache { if s.Etcd.EnableWatchCache {
cachesize.InitializeWatchCacheSizes(s.GenericServerRunOptions.TargetRAMMB) cachesize.InitializeWatchCacheSizes(s.GenericServerRunOptions.TargetRAMMB)
cachesize.SetWatchCacheSizes(s.GenericServerRunOptions.WatchCacheSizes) cachesize.SetWatchCacheSizes(s.GenericServerRunOptions.WatchCacheSizes)
} }
...@@ -211,50 +215,17 @@ func Run(s *options.ServerRunOptions) error { ...@@ -211,50 +215,17 @@ func Run(s *options.ServerRunOptions) error {
routes.UIRedirect{}.Install(m.HandlerContainer) routes.UIRedirect{}.Install(m.HandlerContainer)
routes.Logs{}.Install(m.HandlerContainer) routes.Logs{}.Install(m.HandlerContainer)
// TODO: Refactor this code to share it with kube-apiserver rather than duplicating it here. installFederationAPIs(m, genericConfig.RESTOptionsGetter)
restOptionsFactory := &restOptionsFactory{ installCoreAPIs(s, m, genericConfig.RESTOptionsGetter)
storageFactory: storageFactory, installExtensionsAPIs(m, genericConfig.RESTOptionsGetter)
enableGarbageCollection: s.Features.EnableGarbageCollection, installBatchAPIs(m, genericConfig.RESTOptionsGetter)
deleteCollectionWorkers: s.GenericServerRunOptions.DeleteCollectionWorkers, installAutoscalingAPIs(m, genericConfig.RESTOptionsGetter)
}
if s.GenericServerRunOptions.EnableWatchCache {
restOptionsFactory.storageDecorator = genericregistry.StorageWithCacher
} else {
restOptionsFactory.storageDecorator = generic.UndecoratedStorage
}
installFederationAPIs(m, restOptionsFactory)
installCoreAPIs(s, m, restOptionsFactory)
installExtensionsAPIs(m, restOptionsFactory)
installBatchAPIs(m, restOptionsFactory)
installAutoscalingAPIs(m, restOptionsFactory)
sharedInformers.Start(wait.NeverStop) sharedInformers.Start(wait.NeverStop)
m.PrepareRun().Run(wait.NeverStop) m.PrepareRun().Run(wait.NeverStop)
return nil return nil
} }
type restOptionsFactory struct {
storageFactory genericapiserver.StorageFactory
storageDecorator generic.StorageDecorator
deleteCollectionWorkers int
enableGarbageCollection bool
}
func (f *restOptionsFactory) GetRESTOptions(resource schema.GroupResource) (generic.RESTOptions, error) {
config, err := f.storageFactory.NewConfig(resource)
if err != nil {
return generic.RESTOptions{}, fmt.Errorf("Unable to find storage config for %v, due to %v", resource, err.Error())
}
return generic.RESTOptions{
StorageConfig: config,
Decorator: f.storageDecorator,
DeleteCollectionWorkers: f.deleteCollectionWorkers,
EnableGarbageCollection: f.enableGarbageCollection,
ResourcePrefix: f.storageFactory.ResourcePrefix(resource),
}, nil
}
// PostProcessSpec adds removed definitions for backward compatibility // PostProcessSpec adds removed definitions for backward compatibility
func postProcessOpenAPISpecForBackwardCompatibility(s *spec.Swagger) (*spec.Swagger, error) { func postProcessOpenAPISpecForBackwardCompatibility(s *spec.Swagger) (*spec.Swagger, error) {
compatibilityMap := map[string]string{ compatibilityMap := map[string]string{
......
...@@ -305,6 +305,8 @@ staging/src/k8s.io/client-go/tools/metrics ...@@ -305,6 +305,8 @@ staging/src/k8s.io/client-go/tools/metrics
staging/src/k8s.io/client-go/util/cert staging/src/k8s.io/client-go/util/cert
staging/src/k8s.io/client-go/util/homedir staging/src/k8s.io/client-go/util/homedir
staging/src/k8s.io/client-go/util/workqueue staging/src/k8s.io/client-go/util/workqueue
staging/src/k8s.io/sample-apiserver
staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install
test/e2e/perftype test/e2e/perftype
test/e2e_node/runner/local test/e2e_node/runner/local
test/images/clusterapi-tester test/images/clusterapi-tester
......
...@@ -47,6 +47,9 @@ pushd "${KUBE_ROOT}" > /dev/null ...@@ -47,6 +47,9 @@ pushd "${KUBE_ROOT}" > /dev/null
if [ ! -e "vendor/k8s.io/apimachinery" ]; then if [ ! -e "vendor/k8s.io/apimachinery" ]; then
ln -s ../../staging/src/k8s.io/apimachinery vendor/k8s.io/apimachinery ln -s ../../staging/src/k8s.io/apimachinery vendor/k8s.io/apimachinery
fi fi
if [ ! -e "vendor/k8s.io/sample-apiserver" ]; then
ln -s ../../staging/src/k8s.io/sample-apiserver vendor/k8s.io/sample-apiserver
fi
popd > /dev/null popd > /dev/null
echo "Don't forget to run hack/update-godep-licenses.sh if you added or removed a dependency!" echo "Don't forget to run hack/update-godep-licenses.sh if you added or removed a dependency!"
...@@ -53,6 +53,7 @@ RC=0 ...@@ -53,6 +53,7 @@ RC=0
print_forbidden_imports apimachinery k8s.io/ || RC=1 print_forbidden_imports apimachinery k8s.io/ || RC=1
print_forbidden_imports apiserver k8s.io/kubernetes || RC=1 print_forbidden_imports apiserver k8s.io/kubernetes || RC=1
print_forbidden_imports client-go k8s.io/kubernetes k8s.io/apiserver || RC=1 print_forbidden_imports client-go k8s.io/kubernetes k8s.io/apiserver || RC=1
print_forbidden_imports sample-apiserver k8s.io/kubernetes || RC=1
if [ ${RC} != 0 ]; then if [ ${RC} != 0 ]; then
exit ${RC} exit ${RC}
fi fi
......
...@@ -13,12 +13,15 @@ go_library( ...@@ -13,12 +13,15 @@ go_library(
srcs = [ srcs = [
"default_storage_factory_builder.go", "default_storage_factory_builder.go",
"doc.go", "doc.go",
"rest.go",
], ],
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//vendor:k8s.io/apimachinery/pkg/runtime", "//vendor:k8s.io/apimachinery/pkg/runtime",
"//vendor:k8s.io/apimachinery/pkg/runtime/schema", "//vendor:k8s.io/apimachinery/pkg/runtime/schema",
"//vendor:k8s.io/apiserver/pkg/registry/generic",
"//vendor:k8s.io/apiserver/pkg/registry/generic/registry",
"//vendor:k8s.io/apiserver/pkg/server", "//vendor:k8s.io/apiserver/pkg/server",
"//vendor:k8s.io/apiserver/pkg/storage/storagebackend", "//vendor:k8s.io/apiserver/pkg/storage/storagebackend",
"//vendor:k8s.io/apiserver/pkg/util/flag", "//vendor:k8s.io/apiserver/pkg/util/flag",
......
...@@ -25,6 +25,10 @@ import ( ...@@ -25,6 +25,10 @@ import (
"github.com/spf13/pflag" "github.com/spf13/pflag"
) )
const (
DefaultEtcdPathPrefix = "/registry"
)
// StorageSerializationOptions contains the options for encoding resources. // StorageSerializationOptions contains the options for encoding resources.
type StorageSerializationOptions struct { type StorageSerializationOptions struct {
StorageVersions string StorageVersions string
......
/*
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 kubeapiserver
import (
"fmt"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/registry/generic"
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
genericapiserver "k8s.io/apiserver/pkg/server"
)
// RESTOptionsFactory is a RESTOptionsGetter for kube apiservers since they do complicated stuff
type RESTOptionsFactory struct {
DeleteCollectionWorkers int
EnableGarbageCollection bool
EnableWatchCache bool
StorageFactory genericapiserver.StorageFactory
}
func (f *RESTOptionsFactory) GetRESTOptions(resource schema.GroupResource) (generic.RESTOptions, error) {
storageConfig, err := f.StorageFactory.NewConfig(resource)
if err != nil {
return generic.RESTOptions{}, fmt.Errorf("Unable to find storage destination for %v, due to %v", resource, err.Error())
}
ret := generic.RESTOptions{
StorageConfig: storageConfig,
Decorator: generic.UndecoratedStorage,
DeleteCollectionWorkers: f.DeleteCollectionWorkers,
EnableGarbageCollection: f.EnableGarbageCollection,
ResourcePrefix: f.StorageFactory.ResourcePrefix(resource),
}
if f.EnableWatchCache {
ret.Decorator = genericregistry.StorageWithCacher
}
return ret, nil
}
...@@ -75,13 +75,11 @@ go_library( ...@@ -75,13 +75,11 @@ go_library(
"//vendor:github.com/prometheus/client_golang/prometheus", "//vendor:github.com/prometheus/client_golang/prometheus",
"//vendor:k8s.io/apimachinery/pkg/api/errors", "//vendor:k8s.io/apimachinery/pkg/api/errors",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
"//vendor:k8s.io/apimachinery/pkg/util/intstr", "//vendor:k8s.io/apimachinery/pkg/util/intstr",
"//vendor:k8s.io/apimachinery/pkg/util/net", "//vendor:k8s.io/apimachinery/pkg/util/net",
"//vendor:k8s.io/apimachinery/pkg/util/runtime", "//vendor:k8s.io/apimachinery/pkg/util/runtime",
"//vendor:k8s.io/apimachinery/pkg/util/wait", "//vendor:k8s.io/apimachinery/pkg/util/wait",
"//vendor:k8s.io/apiserver/pkg/registry/generic", "//vendor:k8s.io/apiserver/pkg/registry/generic",
"//vendor:k8s.io/apiserver/pkg/registry/generic/registry",
"//vendor:k8s.io/apiserver/pkg/server", "//vendor:k8s.io/apiserver/pkg/server",
"//vendor:k8s.io/apiserver/pkg/server/healthz", "//vendor:k8s.io/apiserver/pkg/server/healthz",
], ],
...@@ -115,6 +113,7 @@ go_test( ...@@ -115,6 +113,7 @@ go_test(
"//pkg/client/clientset_generated/clientset/fake:go_default_library", "//pkg/client/clientset_generated/clientset/fake:go_default_library",
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library", "//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
"//pkg/generated/openapi:go_default_library", "//pkg/generated/openapi:go_default_library",
"//pkg/kubeapiserver:go_default_library",
"//pkg/kubelet/client:go_default_library", "//pkg/kubelet/client:go_default_library",
"//pkg/version:go_default_library", "//pkg/version:go_default_library",
"//vendor:github.com/go-openapi/loads", "//vendor:github.com/go-openapi/loads",
......
...@@ -25,10 +25,8 @@ import ( ...@@ -25,10 +25,8 @@ import (
"time" "time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
utilnet "k8s.io/apimachinery/pkg/util/net" utilnet "k8s.io/apimachinery/pkg/util/net"
"k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/generic"
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
genericapiserver "k8s.io/apiserver/pkg/server" genericapiserver "k8s.io/apiserver/pkg/server"
"k8s.io/apiserver/pkg/server/healthz" "k8s.io/apiserver/pkg/server/healthz"
"k8s.io/kubernetes/cmd/kube-apiserver/app/options" "k8s.io/kubernetes/cmd/kube-apiserver/app/options"
...@@ -82,10 +80,8 @@ type Config struct { ...@@ -82,10 +80,8 @@ type Config struct {
APIResourceConfigSource genericapiserver.APIResourceConfigSource APIResourceConfigSource genericapiserver.APIResourceConfigSource
StorageFactory genericapiserver.StorageFactory StorageFactory genericapiserver.StorageFactory
EnableWatchCache bool
EnableCoreControllers bool EnableCoreControllers bool
EndpointReconcilerConfig EndpointReconcilerConfig EndpointReconcilerConfig EndpointReconcilerConfig
DeleteCollectionWorkers int
EventTTL time.Duration EventTTL time.Duration
KubeletClientConfig kubeletclient.KubeletClientConfig KubeletClientConfig kubeletclient.KubeletClientConfig
...@@ -221,18 +217,6 @@ func (c completedConfig) New() (*Master, error) { ...@@ -221,18 +217,6 @@ func (c completedConfig) New() (*Master, error) {
GenericAPIServer: s, GenericAPIServer: s,
} }
restOptionsFactory := &restOptionsFactory{
deleteCollectionWorkers: c.DeleteCollectionWorkers,
enableGarbageCollection: c.GenericConfig.EnableGarbageCollection,
storageFactory: c.StorageFactory,
}
if c.EnableWatchCache {
restOptionsFactory.storageDecorator = genericregistry.StorageWithCacher
} else {
restOptionsFactory.storageDecorator = generic.UndecoratedStorage
}
// install legacy rest storage // install legacy rest storage
if c.APIResourceConfigSource.AnyResourcesForVersionEnabled(apiv1.SchemeGroupVersion) { if c.APIResourceConfigSource.AnyResourcesForVersionEnabled(apiv1.SchemeGroupVersion) {
legacyRESTStorageProvider := corerest.LegacyRESTStorageProvider{ legacyRESTStorageProvider := corerest.LegacyRESTStorageProvider{
...@@ -244,7 +228,7 @@ func (c completedConfig) New() (*Master, error) { ...@@ -244,7 +228,7 @@ func (c completedConfig) New() (*Master, error) {
ServiceNodePortRange: c.ServiceNodePortRange, ServiceNodePortRange: c.ServiceNodePortRange,
LoopbackClientConfig: c.GenericConfig.LoopbackClientConfig, LoopbackClientConfig: c.GenericConfig.LoopbackClientConfig,
} }
m.InstallLegacyAPI(c.Config, restOptionsFactory, legacyRESTStorageProvider) m.InstallLegacyAPI(c.Config, c.Config.GenericConfig.RESTOptionsGetter, legacyRESTStorageProvider)
} }
restStorageProviders := []RESTStorageProvider{ restStorageProviders := []RESTStorageProvider{
...@@ -259,7 +243,7 @@ func (c completedConfig) New() (*Master, error) { ...@@ -259,7 +243,7 @@ func (c completedConfig) New() (*Master, error) {
rbacrest.RESTStorageProvider{Authorizer: c.GenericConfig.Authorizer}, rbacrest.RESTStorageProvider{Authorizer: c.GenericConfig.Authorizer},
storagerest.RESTStorageProvider{}, storagerest.RESTStorageProvider{},
} }
m.InstallAPIs(c.Config.APIResourceConfigSource, restOptionsFactory, restStorageProviders...) m.InstallAPIs(c.Config.APIResourceConfigSource, c.Config.GenericConfig.RESTOptionsGetter, restStorageProviders...)
if c.Tunneler != nil { if c.Tunneler != nil {
m.installTunneler(c.Tunneler, corev1client.NewForConfigOrDie(c.GenericConfig.LoopbackClientConfig).Nodes()) m.installTunneler(c.Tunneler, corev1client.NewForConfigOrDie(c.GenericConfig.LoopbackClientConfig).Nodes())
...@@ -339,28 +323,6 @@ func (m *Master) InstallAPIs(apiResourceConfigSource genericapiserver.APIResourc ...@@ -339,28 +323,6 @@ func (m *Master) InstallAPIs(apiResourceConfigSource genericapiserver.APIResourc
} }
} }
type restOptionsFactory struct {
deleteCollectionWorkers int
enableGarbageCollection bool
storageFactory genericapiserver.StorageFactory
storageDecorator generic.StorageDecorator
}
func (f *restOptionsFactory) GetRESTOptions(resource schema.GroupResource) (generic.RESTOptions, error) {
storageConfig, err := f.storageFactory.NewConfig(resource)
if err != nil {
return generic.RESTOptions{}, fmt.Errorf("Unable to find storage destination for %v, due to %v", resource, err.Error())
}
return generic.RESTOptions{
StorageConfig: storageConfig,
Decorator: f.storageDecorator,
DeleteCollectionWorkers: f.deleteCollectionWorkers,
EnableGarbageCollection: f.enableGarbageCollection,
ResourcePrefix: f.storageFactory.ResourcePrefix(resource),
}, nil
}
type nodeAddressProvider struct { type nodeAddressProvider struct {
nodeClient corev1client.NodeInterface nodeClient corev1client.NodeInterface
} }
......
...@@ -51,6 +51,7 @@ import ( ...@@ -51,6 +51,7 @@ import (
extensionsapiv1beta1 "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" extensionsapiv1beta1 "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
"k8s.io/kubernetes/pkg/apis/rbac" "k8s.io/kubernetes/pkg/apis/rbac"
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset/fake" "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/fake"
"k8s.io/kubernetes/pkg/kubeapiserver"
kubeletclient "k8s.io/kubernetes/pkg/kubelet/client" kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
kubeversion "k8s.io/kubernetes/pkg/version" kubeversion "k8s.io/kubernetes/pkg/version"
...@@ -87,6 +88,12 @@ func setUp(t *testing.T) (*Master, *etcdtesting.EtcdTestServer, Config, *assert. ...@@ -87,6 +88,12 @@ func setUp(t *testing.T) (*Master, *etcdtesting.EtcdTestServer, Config, *assert.
config.GenericConfig.RequestContextMapper = genericapirequest.NewRequestContextMapper() config.GenericConfig.RequestContextMapper = genericapirequest.NewRequestContextMapper()
config.GenericConfig.LoopbackClientConfig = &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: api.Codecs}} config.GenericConfig.LoopbackClientConfig = &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: api.Codecs}}
config.GenericConfig.EnableMetrics = true config.GenericConfig.EnableMetrics = true
config.GenericConfig.RESTOptionsGetter = &kubeapiserver.RESTOptionsFactory{
StorageFactory: storageFactory,
EnableWatchCache: true,
EnableGarbageCollection: true,
DeleteCollectionWorkers: 1,
}
config.EnableCoreControllers = false config.EnableCoreControllers = false
config.KubeletClientConfig = kubeletclient.KubeletClientConfig{Port: 10250} config.KubeletClientConfig = kubeletclient.KubeletClientConfig{Port: 10250}
config.ProxyTransport = utilnet.SetTransportDefaults(&http.Transport{ config.ProxyTransport = utilnet.SetTransportDefaults(&http.Transport{
......
...@@ -50,6 +50,7 @@ import ( ...@@ -50,6 +50,7 @@ import (
genericapifilters "k8s.io/apiserver/pkg/endpoints/filters" genericapifilters "k8s.io/apiserver/pkg/endpoints/filters"
apiopenapi "k8s.io/apiserver/pkg/endpoints/openapi" apiopenapi "k8s.io/apiserver/pkg/endpoints/openapi"
apirequest "k8s.io/apiserver/pkg/endpoints/request" apirequest "k8s.io/apiserver/pkg/endpoints/request"
genericregistry "k8s.io/apiserver/pkg/registry/generic"
genericfilters "k8s.io/apiserver/pkg/server/filters" genericfilters "k8s.io/apiserver/pkg/server/filters"
"k8s.io/apiserver/pkg/server/healthz" "k8s.io/apiserver/pkg/server/healthz"
"k8s.io/apiserver/pkg/server/mux" "k8s.io/apiserver/pkg/server/mux"
...@@ -92,7 +93,6 @@ type Config struct { ...@@ -92,7 +93,6 @@ type Config struct {
EnableProfiling bool EnableProfiling bool
// Requires generic profiling enabled // Requires generic profiling enabled
EnableContentionProfiling bool EnableContentionProfiling bool
EnableGarbageCollection bool
EnableMetrics bool EnableMetrics bool
// Version will enable the /version endpoint if non-nil // Version will enable the /version endpoint if non-nil
...@@ -131,6 +131,8 @@ type Config struct { ...@@ -131,6 +131,8 @@ type Config struct {
OpenAPIConfig *openapicommon.Config OpenAPIConfig *openapicommon.Config
// SwaggerConfig will be used in generating Swagger spec. This is nil by default. Use DefaultSwaggerConfig for "working" defaults. // SwaggerConfig will be used in generating Swagger spec. This is nil by default. Use DefaultSwaggerConfig for "working" defaults.
SwaggerConfig *swagger.Config SwaggerConfig *swagger.Config
// RESTOptionsGetter is used to construct "normal" RESTStorage types
RESTOptionsGetter genericregistry.RESTOptionsGetter
// If specified, requests will be allocated a random timeout between this value, and twice this value. // If specified, requests will be allocated a random timeout between this value, and twice this value.
// Note that it is up to the request handlers to ignore or honor this timeout. In seconds. // Note that it is up to the request handlers to ignore or honor this timeout. In seconds.
...@@ -196,7 +198,6 @@ func NewConfig() *Config { ...@@ -196,7 +198,6 @@ func NewConfig() *Config {
LegacyAPIGroupPrefixes: sets.NewString(DefaultLegacyAPIPrefix), LegacyAPIGroupPrefixes: sets.NewString(DefaultLegacyAPIPrefix),
HealthzChecks: []healthz.HealthzChecker{healthz.PingHealthz}, HealthzChecks: []healthz.HealthzChecker{healthz.PingHealthz},
EnableIndex: true, EnableIndex: true,
EnableGarbageCollection: true,
EnableProfiling: true, EnableProfiling: true,
MaxRequestsInFlight: 400, MaxRequestsInFlight: 400,
MaxMutatingRequestsInFlight: 200, MaxMutatingRequestsInFlight: 200,
......
...@@ -388,9 +388,10 @@ func NewDefaultAPIGroupInfo(group string, registry *registered.APIRegistrationMa ...@@ -388,9 +388,10 @@ func NewDefaultAPIGroupInfo(group string, registry *registered.APIRegistrationMa
return APIGroupInfo{ return APIGroupInfo{
GroupMeta: *groupMeta, GroupMeta: *groupMeta,
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{}, VersionedResourcesStorageMap: map[string]map[string]rest.Storage{},
OptionsExternalVersion: &registry.GroupOrDie("").GroupVersion, // TODO unhardcode this. It was hardcoded before, but we need to re-evaluate
Scheme: scheme, OptionsExternalVersion: &schema.GroupVersion{Version: "v1"},
ParameterCodec: parameterCodec, Scheme: scheme,
NegotiatedSerializer: codecs, ParameterCodec: parameterCodec,
NegotiatedSerializer: codecs,
} }
} }
...@@ -60,7 +60,7 @@ func (s *RequestHeaderAuthenticationOptions) AddFlags(fs *pflag.FlagSet) { ...@@ -60,7 +60,7 @@ func (s *RequestHeaderAuthenticationOptions) AddFlags(fs *pflag.FlagSet) {
// ToAuthenticationRequestHeaderConfig returns a RequestHeaderConfig config object for these options // ToAuthenticationRequestHeaderConfig returns a RequestHeaderConfig config object for these options
// if necessary, nil otherwise. // if necessary, nil otherwise.
func (s *RequestHeaderAuthenticationOptions) ToAuthenticationRequestHeaderConfig() *authenticatorfactory.RequestHeaderConfig { func (s *RequestHeaderAuthenticationOptions) ToAuthenticationRequestHeaderConfig() *authenticatorfactory.RequestHeaderConfig {
if len(s.UsernameHeaders) == 0 { if len(s.UsernameHeaders) == 0 || (len(s.UsernameHeaders) == 1 && len(s.UsernameHeaders[0]) == 0) {
return nil return nil
} }
......
...@@ -22,13 +22,13 @@ import ( ...@@ -22,13 +22,13 @@ import (
"github.com/spf13/pflag" "github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/registry/generic/registry"
"k8s.io/apiserver/pkg/server"
"k8s.io/apiserver/pkg/storage/storagebackend" "k8s.io/apiserver/pkg/storage/storagebackend"
) )
const (
DefaultEtcdPathPrefix = "/registry"
)
type EtcdOptions struct { type EtcdOptions struct {
StorageConfig storagebackend.Config StorageConfig storagebackend.Config
...@@ -37,18 +37,25 @@ type EtcdOptions struct { ...@@ -37,18 +37,25 @@ type EtcdOptions struct {
// To enable protobuf as storage format, it is enough // To enable protobuf as storage format, it is enough
// to set it to "application/vnd.kubernetes.protobuf". // to set it to "application/vnd.kubernetes.protobuf".
DefaultStorageMediaType string DefaultStorageMediaType string
DeleteCollectionWorkers int
EnableGarbageCollection bool
EnableWatchCache bool
} }
func NewEtcdOptions(scheme *runtime.Scheme) *EtcdOptions { func NewEtcdOptions(prefix string, copier runtime.ObjectCopier, codec runtime.Codec) *EtcdOptions {
return &EtcdOptions{ return &EtcdOptions{
StorageConfig: storagebackend.Config{ StorageConfig: storagebackend.Config{
Prefix: DefaultEtcdPathPrefix, Prefix: prefix,
// Default cache size to 0 - if unset, its size will be set based on target // Default cache size to 0 - if unset, its size will be set based on target
// memory usage. // memory usage.
DeserializationCacheSize: 0, DeserializationCacheSize: 0,
Copier: scheme, Copier: copier,
Codec: codec,
}, },
DefaultStorageMediaType: "application/json", DefaultStorageMediaType: "application/json",
DeleteCollectionWorkers: 1,
EnableGarbageCollection: true,
EnableWatchCache: true,
} }
} }
...@@ -70,6 +77,16 @@ func (s *EtcdOptions) AddFlags(fs *pflag.FlagSet) { ...@@ -70,6 +77,16 @@ func (s *EtcdOptions) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&s.DefaultStorageMediaType, "storage-media-type", s.DefaultStorageMediaType, ""+ fs.StringVar(&s.DefaultStorageMediaType, "storage-media-type", s.DefaultStorageMediaType, ""+
"The media type to use to store objects in storage. Defaults to application/json. "+ "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.") "Some resources may only support a specific media type and will ignore this setting.")
fs.IntVar(&s.DeleteCollectionWorkers, "delete-collection-workers", s.DeleteCollectionWorkers,
"Number of workers spawned for DeleteCollection call. These are used to speed up namespace cleanup.")
fs.BoolVar(&s.EnableGarbageCollection, "enable-garbage-collector", s.EnableGarbageCollection, ""+
"Enables the generic garbage collector. MUST be synced with the corresponding flag "+
"of the kube-controller-manager.")
// TODO: enable cache in integration tests.
fs.BoolVar(&s.EnableWatchCache, "watch-cache", s.EnableWatchCache,
"Enable watch caching in the apiserver")
fs.StringVar(&s.StorageConfig.Type, "storage-backend", s.StorageConfig.Type, fs.StringVar(&s.StorageConfig.Type, "storage-backend", s.StorageConfig.Type,
"The storage backend for persistence. Options: 'etcd3' (default), 'etcd2'.") "The storage backend for persistence. Options: 'etcd3' (default), 'etcd2'.")
...@@ -95,3 +112,31 @@ func (s *EtcdOptions) AddFlags(fs *pflag.FlagSet) { ...@@ -95,3 +112,31 @@ func (s *EtcdOptions) AddFlags(fs *pflag.FlagSet) {
fs.BoolVar(&s.StorageConfig.Quorum, "etcd-quorum-read", s.StorageConfig.Quorum, fs.BoolVar(&s.StorageConfig.Quorum, "etcd-quorum-read", s.StorageConfig.Quorum,
"If true, enable quorum read.") "If true, enable quorum read.")
} }
func (s *EtcdOptions) ApplyTo(c *server.Config) error {
c.RESTOptionsGetter = &restOptionsFactory{options: s}
return nil
}
// restOptionsFactory is a default implementation of a RESTOptionsGetter
// This will work well for most aggregated API servers. The legacy kube server needs more customization
type restOptionsFactory struct {
options *EtcdOptions
}
func (f *restOptionsFactory) GetRESTOptions(resource schema.GroupResource) (generic.RESTOptions, error) {
ret := generic.RESTOptions{
StorageConfig: &f.options.StorageConfig,
Decorator: registry.StorageWithCacher,
DeleteCollectionWorkers: f.options.DeleteCollectionWorkers,
EnableGarbageCollection: f.options.EnableGarbageCollection,
ResourcePrefix: f.options.StorageConfig.Prefix + "/" + resource.Group + "/" + resource.Resource,
}
if !f.options.EnableWatchCache {
ret.Decorator = generic.UndecoratedStorage
}
return ret, nil
}
...@@ -23,7 +23,6 @@ import ( ...@@ -23,7 +23,6 @@ import (
) )
type FeatureOptions struct { type FeatureOptions struct {
EnableGarbageCollection bool
EnableProfiling bool EnableProfiling bool
EnableContentionProfiling bool EnableContentionProfiling bool
EnableSwaggerUI bool EnableSwaggerUI bool
...@@ -33,7 +32,6 @@ func NewFeatureOptions() *FeatureOptions { ...@@ -33,7 +32,6 @@ func NewFeatureOptions() *FeatureOptions {
defaults := server.NewConfig() defaults := server.NewConfig()
return &FeatureOptions{ return &FeatureOptions{
EnableGarbageCollection: defaults.EnableGarbageCollection,
EnableProfiling: defaults.EnableProfiling, EnableProfiling: defaults.EnableProfiling,
EnableContentionProfiling: defaults.EnableContentionProfiling, EnableContentionProfiling: defaults.EnableContentionProfiling,
EnableSwaggerUI: defaults.EnableSwaggerUI, EnableSwaggerUI: defaults.EnableSwaggerUI,
...@@ -41,9 +39,6 @@ func NewFeatureOptions() *FeatureOptions { ...@@ -41,9 +39,6 @@ func NewFeatureOptions() *FeatureOptions {
} }
func (o *FeatureOptions) AddFlags(fs *pflag.FlagSet) { func (o *FeatureOptions) AddFlags(fs *pflag.FlagSet) {
fs.BoolVar(&o.EnableGarbageCollection, "enable-garbage-collector", o.EnableGarbageCollection, ""+
"Enables the generic garbage collector. MUST be synced with the corresponding flag "+
"of the kube-controller-manager.")
fs.BoolVar(&o.EnableProfiling, "profiling", o.EnableProfiling, fs.BoolVar(&o.EnableProfiling, "profiling", o.EnableProfiling,
"Enable profiling via web interface host:port/debug/pprof/") "Enable profiling via web interface host:port/debug/pprof/")
fs.BoolVar(&o.EnableContentionProfiling, "contention-profiling", o.EnableContentionProfiling, fs.BoolVar(&o.EnableContentionProfiling, "contention-profiling", o.EnableContentionProfiling,
...@@ -53,7 +48,6 @@ func (o *FeatureOptions) AddFlags(fs *pflag.FlagSet) { ...@@ -53,7 +48,6 @@ func (o *FeatureOptions) AddFlags(fs *pflag.FlagSet) {
} }
func (o *FeatureOptions) ApplyTo(c *server.Config) error { func (o *FeatureOptions) ApplyTo(c *server.Config) error {
c.EnableGarbageCollection = o.EnableGarbageCollection
c.EnableProfiling = o.EnableProfiling c.EnableProfiling = o.EnableProfiling
c.EnableContentionProfiling = o.EnableContentionProfiling c.EnableContentionProfiling = o.EnableContentionProfiling
c.EnableSwaggerUI = o.EnableSwaggerUI c.EnableSwaggerUI = o.EnableSwaggerUI
......
...@@ -34,9 +34,9 @@ type RecommendedOptions struct { ...@@ -34,9 +34,9 @@ type RecommendedOptions struct {
Features *FeatureOptions Features *FeatureOptions
} }
func NewRecommendedOptions(scheme *runtime.Scheme) *RecommendedOptions { func NewRecommendedOptions(prefix string, copier runtime.ObjectCopier, codec runtime.Codec) *RecommendedOptions {
return &RecommendedOptions{ return &RecommendedOptions{
Etcd: NewEtcdOptions(scheme), Etcd: NewEtcdOptions(prefix, copier, codec),
SecureServing: NewSecureServingOptions(), SecureServing: NewSecureServingOptions(),
Authentication: NewDelegatingAuthenticationOptions(), Authentication: NewDelegatingAuthenticationOptions(),
Authorization: NewDelegatingAuthorizationOptions(), Authorization: NewDelegatingAuthorizationOptions(),
...@@ -55,6 +55,9 @@ func (o *RecommendedOptions) AddFlags(fs *pflag.FlagSet) { ...@@ -55,6 +55,9 @@ func (o *RecommendedOptions) AddFlags(fs *pflag.FlagSet) {
} }
func (o *RecommendedOptions) ApplyTo(config *server.Config) error { func (o *RecommendedOptions) ApplyTo(config *server.Config) error {
if err := o.Etcd.ApplyTo(config); err != nil {
return err
}
if err := o.SecureServing.ApplyTo(config); err != nil { if err := o.SecureServing.ApplyTo(config); err != nil {
return err return err
} }
......
...@@ -39,8 +39,6 @@ type ServerRunOptions struct { ...@@ -39,8 +39,6 @@ type ServerRunOptions struct {
AdvertiseAddress net.IP AdvertiseAddress net.IP
CorsAllowedOriginList []string CorsAllowedOriginList []string
DeleteCollectionWorkers int
EnableWatchCache bool
ExternalHost string ExternalHost string
MaxRequestsInFlight int MaxRequestsInFlight int
MaxMutatingRequestsInFlight int MaxMutatingRequestsInFlight int
...@@ -54,8 +52,6 @@ func NewServerRunOptions() *ServerRunOptions { ...@@ -54,8 +52,6 @@ func NewServerRunOptions() *ServerRunOptions {
return &ServerRunOptions{ return &ServerRunOptions{
AdmissionControl: "AlwaysAdmit", AdmissionControl: "AlwaysAdmit",
DeleteCollectionWorkers: 1,
EnableWatchCache: true,
MaxRequestsInFlight: defaults.MaxRequestsInFlight, MaxRequestsInFlight: defaults.MaxRequestsInFlight,
MaxMutatingRequestsInFlight: defaults.MaxMutatingRequestsInFlight, MaxMutatingRequestsInFlight: defaults.MaxMutatingRequestsInFlight,
MinRequestTimeout: defaults.MinRequestTimeout, MinRequestTimeout: defaults.MinRequestTimeout,
...@@ -124,13 +120,6 @@ func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) { ...@@ -124,13 +120,6 @@ func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) {
"List of allowed origins for CORS, comma separated. An allowed origin can be a regular "+ "List of allowed origins for CORS, comma separated. An allowed origin can be a regular "+
"expression to support subdomain matching. If this list is empty CORS will not be enabled.") "expression to support subdomain matching. If this list is empty CORS will not be enabled.")
fs.IntVar(&s.DeleteCollectionWorkers, "delete-collection-workers", s.DeleteCollectionWorkers,
"Number of workers spawned for DeleteCollection call. These are used to speed up namespace cleanup.")
// TODO: enable cache in integration tests.
fs.BoolVar(&s.EnableWatchCache, "watch-cache", s.EnableWatchCache,
"Enable watch caching in the apiserver")
fs.IntVar(&s.TargetRAMMB, "target-ram-mb", s.TargetRAMMB, fs.IntVar(&s.TargetRAMMB, "target-ram-mb", s.TargetRAMMB,
"Memory limit for apiserver in MB (used to configure sizes of caches, etc.)") "Memory limit for apiserver in MB (used to configure sizes of caches, etc.)")
......
apiVersion: serviceinjection.k8s.io/v1alpha1
kind: ServiceInjection
metadata:
name: injector
namespace: kube-system
labels:
sample-label: foo
# 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.
FROM fedora
ADD kube-service-injection /
ENTRYPOINT ["/kube-service-injection"]
apiVersion: v1
kind: Pod
metadata:
name: kube-service-injection
namespace: kube-system
spec:
hostNetwork: true
containers:
- name: kube-service-injection
image: kube-service-injection
imagePullPolicy: Never
args:
- "--secure-port=9443"
- "--authentication-kubeconfig=/all-certs/admin.kubeconfig"
- "--authorization-kubeconfig=/all-certs/admin.kubeconfig"
- "--tls-ca-file=/all-certs/apiserver.crt"
- "--client-ca-file=/all-certs/client-ca.crt"
- "--requestheader-username-headers=X-Remote-User"
- "--requestheader-group-headers=X-Remote-Group"
- "--requestheader-extra-headers-prefix=X-Remote-Extra-"
- "--requestheader-client-ca-file=/all-certs/request-header-ca.crt"
- "--etcd-servers=http://127.0.0.1:2379"
ports:
- containerPort: 9443
hostPort: 9443
volumeMounts:
- name: all-certs
mountPath: /all-certs
readOnly: true
volumes:
- name: all-certs
hostPath:
path: /var/run/kubernetes/
#!/bin/bash
# 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.
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../../..
source "${KUBE_ROOT}/hack/lib/util.sh"
# Register function to be called on EXIT to remove generated binary.
function cleanup {
rm "${KUBE_ROOT}/cmd/kube-sample-apiserver/artifacts/simple-image/kube-sample-apiserver"
}
trap cleanup EXIT
cp -v ${KUBE_ROOT}/_output/local/bin/linux/amd64/kube-sample-apiserver "${KUBE_ROOT}/cmd/kube-sample-apiserver/artifacts/simple-image/kube-sample-apiserver"
docker build -t kube-sample-apiserver:latest ${KUBE_ROOT}/cmd/kube-sample-apiserver/artifacts/simple-image
#!/bin/bash
# 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.
set -o errexit
set -o nounset
set -o pipefail
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../../..
APIFEDERATOR_ROOT=$(dirname "${BASH_SOURCE}")/..
source "${KUBE_ROOT}/hack/lib/init.sh"
# Register function to be called on EXIT to remove generated binary.
function cleanup {
rm -f "${CLIENTGEN:-}"
rm -f "${listergen:-}"
rm -f "${informergen:-}"
}
trap cleanup EXIT
echo "Building client-gen"
CLIENTGEN="${PWD}/client-gen-binary"
go build -o "${CLIENTGEN}" ./cmd/libs/go2idl/client-gen
PREFIX=k8s.io/sample-apiserver/pkg/apis
INPUT_BASE="--input-base ${PREFIX}"
INPUT_APIS=(
wardle/
wardle/v1alpha1
)
INPUT="--input ${INPUT_APIS[@]}"
CLIENTSET_PATH="--clientset-path k8s.io/sample-apiserver/pkg/client/clientset_generated"
${CLIENTGEN} ${INPUT_BASE} ${INPUT} ${CLIENTSET_PATH}
${CLIENTGEN} --clientset-name="clientset" ${INPUT_BASE} --input wardle/v1alpha1 ${CLIENTSET_PATH}
echo "Building lister-gen"
listergen="${PWD}/lister-gen"
go build -o "${listergen}" ./cmd/libs/go2idl/lister-gen
LISTER_INPUT="--input-dirs k8s.io/sample-apiserver/pkg/apis/wardle --input-dirs k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1"
LISTER_PATH="--output-package k8s.io/sample-apiserver/pkg/client/listers"
${listergen} ${LISTER_INPUT} ${LISTER_PATH}
echo "Building informer-gen"
informergen="${PWD}/informer-gen"
go build -o "${informergen}" ./cmd/libs/go2idl/informer-gen
${informergen} \
--input-dirs k8s.io/sample-apiserver/pkg/apis/wardle --input-dirs k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1 \
--versioned-clientset-package k8s.io/sample-apiserver/pkg/client/clientset_generated/clientset \
--internal-clientset-package k8s.io/sample-apiserver/pkg/client/clientset_generated/internalclientset \
--listers-package k8s.io/sample-apiserver/pkg/client/listers \
--output-package k8s.io/sample-apiserver/pkg/client/informers
"$@"
/*
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 main
import (
"flag"
"os"
"runtime"
"k8s.io/apimachinery/pkg/util/wait"
// "k8s.io/kubernetes/pkg/util/logs"
"k8s.io/sample-apiserver/pkg/cmd/server"
)
func main() {
// TODO move package and restore
// logs.InitLogs()
// defer logs.FlushLogs()
if len(os.Getenv("GOMAXPROCS")) == 0 {
runtime.GOMAXPROCS(runtime.NumCPU())
}
cmd := server.NewCommandStartWardleServer(os.Stdout, os.Stderr, wait.NeverStop)
cmd.Flags().AddGoFlagSet(flag.CommandLine)
if err := cmd.Execute(); err != nil {
panic(err)
}
}
/*
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.
*/
// +k8s:deepcopy-gen=package,register
// Package api is the internal version of the API.
// +groupName=wardle.k8s.io
package wardle
/*
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 install
import (
"k8s.io/apimachinery/pkg/apimachinery/announced"
"k8s.io/apimachinery/pkg/apimachinery/registered"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/sample-apiserver/pkg/apis/wardle"
"k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1"
)
// Install registers the API group and adds types to a scheme
func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) {
if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{
GroupName: wardle.GroupName,
RootScopedKinds: sets.NewString("APIService"),
VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version},
ImportPrefix: "k8s.io/sample-apiserver/pkg/apis/wardle",
AddInternalObjectsToScheme: wardle.AddToScheme,
},
announced.VersionToSchemeFunc{
v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme,
},
).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil {
panic(err)
}
}
/*
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 wardle
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
const GroupName = "wardle.k8s.io"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}
// Kind takes an unqualified kind and returns back a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind()
}
// Resource takes an unqualified resource and returns back a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
var (
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
AddToScheme = SchemeBuilder.AddToScheme
)
// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&Flunder{},
&FlunderList{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}
/*
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 wardle
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
// FlunderList is a list of Flunder objects.
type FlunderList struct {
metav1.TypeMeta
metav1.ListMeta
Items []Flunder
}
type FlunderSpec struct {
}
type FlunderStatus struct {
}
// +genclient=true
type Flunder struct {
metav1.TypeMeta
metav1.ObjectMeta
Spec FlunderSpec
Status FlunderStatus
}
/*
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.
*/
// +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=k8s.io/sample-apiserver/pkg/apis/wardle
// Package v1alpha1 is the v1alpha1 version of the API.
// +groupName=wardle.k8s.io
package v1alpha1
/*
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 v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
const GroupName = "wardle.k8s.io"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"}
var (
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
AddToScheme = SchemeBuilder.AddToScheme
)
// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&Flunder{},
&FlunderList{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}
/*
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 v1alpha1
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
// FlunderList is a list of Flunder objects.
type FlunderList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
Items []Flunder `json:"items" protobuf:"bytes,2,rep,name=items"`
}
type FlunderSpec struct {
}
type FlunderStatus struct {
}
// +genclient=true
type Flunder struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
Spec FlunderSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
Status FlunderStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
// +build !ignore_autogenerated
/*
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.
*/
// This file was autogenerated by conversion-gen. Do not edit it manually!
package v1alpha1
import (
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
wardle "k8s.io/sample-apiserver/pkg/apis/wardle"
unsafe "unsafe"
)
func init() {
SchemeBuilder.Register(RegisterConversions)
}
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(scheme *runtime.Scheme) error {
return scheme.AddGeneratedConversionFuncs(
Convert_v1alpha1_Flunder_To_wardle_Flunder,
Convert_wardle_Flunder_To_v1alpha1_Flunder,
Convert_v1alpha1_FlunderList_To_wardle_FlunderList,
Convert_wardle_FlunderList_To_v1alpha1_FlunderList,
Convert_v1alpha1_FlunderSpec_To_wardle_FlunderSpec,
Convert_wardle_FlunderSpec_To_v1alpha1_FlunderSpec,
Convert_v1alpha1_FlunderStatus_To_wardle_FlunderStatus,
Convert_wardle_FlunderStatus_To_v1alpha1_FlunderStatus,
)
}
func autoConvert_v1alpha1_Flunder_To_wardle_Flunder(in *Flunder, out *wardle.Flunder, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := Convert_v1alpha1_FlunderSpec_To_wardle_FlunderSpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
if err := Convert_v1alpha1_FlunderStatus_To_wardle_FlunderStatus(&in.Status, &out.Status, s); err != nil {
return err
}
return nil
}
func Convert_v1alpha1_Flunder_To_wardle_Flunder(in *Flunder, out *wardle.Flunder, s conversion.Scope) error {
return autoConvert_v1alpha1_Flunder_To_wardle_Flunder(in, out, s)
}
func autoConvert_wardle_Flunder_To_v1alpha1_Flunder(in *wardle.Flunder, out *Flunder, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := Convert_wardle_FlunderSpec_To_v1alpha1_FlunderSpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
if err := Convert_wardle_FlunderStatus_To_v1alpha1_FlunderStatus(&in.Status, &out.Status, s); err != nil {
return err
}
return nil
}
func Convert_wardle_Flunder_To_v1alpha1_Flunder(in *wardle.Flunder, out *Flunder, s conversion.Scope) error {
return autoConvert_wardle_Flunder_To_v1alpha1_Flunder(in, out, s)
}
func autoConvert_v1alpha1_FlunderList_To_wardle_FlunderList(in *FlunderList, out *wardle.FlunderList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
out.Items = *(*[]wardle.Flunder)(unsafe.Pointer(&in.Items))
return nil
}
func Convert_v1alpha1_FlunderList_To_wardle_FlunderList(in *FlunderList, out *wardle.FlunderList, s conversion.Scope) error {
return autoConvert_v1alpha1_FlunderList_To_wardle_FlunderList(in, out, s)
}
func autoConvert_wardle_FlunderList_To_v1alpha1_FlunderList(in *wardle.FlunderList, out *FlunderList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
out.Items = *(*[]Flunder)(unsafe.Pointer(&in.Items))
return nil
}
func Convert_wardle_FlunderList_To_v1alpha1_FlunderList(in *wardle.FlunderList, out *FlunderList, s conversion.Scope) error {
return autoConvert_wardle_FlunderList_To_v1alpha1_FlunderList(in, out, s)
}
func autoConvert_v1alpha1_FlunderSpec_To_wardle_FlunderSpec(in *FlunderSpec, out *wardle.FlunderSpec, s conversion.Scope) error {
return nil
}
func Convert_v1alpha1_FlunderSpec_To_wardle_FlunderSpec(in *FlunderSpec, out *wardle.FlunderSpec, s conversion.Scope) error {
return autoConvert_v1alpha1_FlunderSpec_To_wardle_FlunderSpec(in, out, s)
}
func autoConvert_wardle_FlunderSpec_To_v1alpha1_FlunderSpec(in *wardle.FlunderSpec, out *FlunderSpec, s conversion.Scope) error {
return nil
}
func Convert_wardle_FlunderSpec_To_v1alpha1_FlunderSpec(in *wardle.FlunderSpec, out *FlunderSpec, s conversion.Scope) error {
return autoConvert_wardle_FlunderSpec_To_v1alpha1_FlunderSpec(in, out, s)
}
func autoConvert_v1alpha1_FlunderStatus_To_wardle_FlunderStatus(in *FlunderStatus, out *wardle.FlunderStatus, s conversion.Scope) error {
return nil
}
func Convert_v1alpha1_FlunderStatus_To_wardle_FlunderStatus(in *FlunderStatus, out *wardle.FlunderStatus, s conversion.Scope) error {
return autoConvert_v1alpha1_FlunderStatus_To_wardle_FlunderStatus(in, out, s)
}
func autoConvert_wardle_FlunderStatus_To_v1alpha1_FlunderStatus(in *wardle.FlunderStatus, out *FlunderStatus, s conversion.Scope) error {
return nil
}
func Convert_wardle_FlunderStatus_To_v1alpha1_FlunderStatus(in *wardle.FlunderStatus, out *FlunderStatus, s conversion.Scope) error {
return autoConvert_wardle_FlunderStatus_To_v1alpha1_FlunderStatus(in, out, s)
}
// +build !ignore_autogenerated
/*
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.
*/
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
package v1alpha1
import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
reflect "reflect"
)
func init() {
SchemeBuilder.Register(RegisterDeepCopies)
}
// RegisterDeepCopies adds deep-copy functions to the given scheme. Public
// to allow building arbitrary schemes.
func RegisterDeepCopies(scheme *runtime.Scheme) error {
return scheme.AddGeneratedDeepCopyFuncs(
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_Flunder, InType: reflect.TypeOf(&Flunder{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_FlunderList, InType: reflect.TypeOf(&FlunderList{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_FlunderSpec, InType: reflect.TypeOf(&FlunderSpec{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_FlunderStatus, InType: reflect.TypeOf(&FlunderStatus{})},
)
}
func DeepCopy_v1alpha1_Flunder(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*Flunder)
out := out.(*Flunder)
*out = *in
if newVal, err := c.DeepCopy(&in.ObjectMeta); err != nil {
return err
} else {
out.ObjectMeta = *newVal.(*v1.ObjectMeta)
}
return nil
}
}
func DeepCopy_v1alpha1_FlunderList(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*FlunderList)
out := out.(*FlunderList)
*out = *in
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Flunder, len(*in))
for i := range *in {
if err := DeepCopy_v1alpha1_Flunder(&(*in)[i], &(*out)[i], c); err != nil {
return err
}
}
}
return nil
}
}
func DeepCopy_v1alpha1_FlunderSpec(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*FlunderSpec)
out := out.(*FlunderSpec)
*out = *in
return nil
}
}
func DeepCopy_v1alpha1_FlunderStatus(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*FlunderStatus)
out := out.(*FlunderStatus)
*out = *in
return nil
}
}
// +build !ignore_autogenerated
/*
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.
*/
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
package wardle
import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
reflect "reflect"
)
func init() {
SchemeBuilder.Register(RegisterDeepCopies)
}
// RegisterDeepCopies adds deep-copy functions to the given scheme. Public
// to allow building arbitrary schemes.
func RegisterDeepCopies(scheme *runtime.Scheme) error {
return scheme.AddGeneratedDeepCopyFuncs(
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_wardle_Flunder, InType: reflect.TypeOf(&Flunder{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_wardle_FlunderList, InType: reflect.TypeOf(&FlunderList{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_wardle_FlunderSpec, InType: reflect.TypeOf(&FlunderSpec{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_wardle_FlunderStatus, InType: reflect.TypeOf(&FlunderStatus{})},
)
}
func DeepCopy_wardle_Flunder(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*Flunder)
out := out.(*Flunder)
*out = *in
if newVal, err := c.DeepCopy(&in.ObjectMeta); err != nil {
return err
} else {
out.ObjectMeta = *newVal.(*v1.ObjectMeta)
}
return nil
}
}
func DeepCopy_wardle_FlunderList(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*FlunderList)
out := out.(*FlunderList)
*out = *in
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Flunder, len(*in))
for i := range *in {
if err := DeepCopy_wardle_Flunder(&(*in)[i], &(*out)[i], c); err != nil {
return err
}
}
}
return nil
}
}
func DeepCopy_wardle_FlunderSpec(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*FlunderSpec)
out := out.(*FlunderSpec)
*out = *in
return nil
}
}
func DeepCopy_wardle_FlunderStatus(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*FlunderStatus)
out := out.(*FlunderStatus)
*out = *in
return nil
}
}
/*
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 apiserver
import (
"k8s.io/apimachinery/pkg/apimachinery/announced"
"k8s.io/apimachinery/pkg/apimachinery/registered"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apimachinery/pkg/version"
"k8s.io/apiserver/pkg/registry/rest"
genericapiserver "k8s.io/apiserver/pkg/server"
"k8s.io/sample-apiserver/pkg/apis/wardle"
"k8s.io/sample-apiserver/pkg/apis/wardle/install"
"k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1"
wardlestorage "k8s.io/sample-apiserver/pkg/registry/wardle"
)
var (
groupFactoryRegistry = make(announced.APIGroupFactoryRegistry)
registry = registered.NewOrDie("")
Scheme = runtime.NewScheme()
Codecs = serializer.NewCodecFactory(Scheme)
)
func init() {
install.Install(groupFactoryRegistry, registry, Scheme)
// we need to add the options to empty v1
// TODO fix the server code to avoid this
metav1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
// TODO: keep the generic API server from wanting this
unversioned := schema.GroupVersion{Group: "", Version: "v1"}
Scheme.AddUnversionedTypes(unversioned,
&metav1.Status{},
&metav1.APIVersions{},
&metav1.APIGroupList{},
&metav1.APIGroup{},
&metav1.APIResourceList{},
)
}
type Config struct {
GenericConfig *genericapiserver.Config
}
// WardleServer contains state for a Kubernetes cluster master/api server.
type WardleServer struct {
GenericAPIServer *genericapiserver.GenericAPIServer
}
type completedConfig struct {
*Config
}
// Complete fills in any fields not set that are required to have valid data. It's mutating the receiver.
func (c *Config) Complete() completedConfig {
c.GenericConfig.Complete()
c.GenericConfig.Version = &version.Info{
Major: "1",
Minor: "0",
}
return completedConfig{c}
}
// SkipComplete provides a way to construct a server instance without config completion.
func (c *Config) SkipComplete() completedConfig {
return completedConfig{c}
}
// New returns a new instance of WardleServer from the given config.
func (c completedConfig) New() (*WardleServer, error) {
genericServer, err := c.Config.GenericConfig.SkipComplete().New() // completion is done in Complete, no need for a second time
if err != nil {
return nil, err
}
s := &WardleServer{
GenericAPIServer: genericServer,
}
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(wardle.GroupName, registry, Scheme, metav1.ParameterCodec, Codecs)
apiGroupInfo.GroupMeta.GroupVersion = v1alpha1.SchemeGroupVersion
v1alpha1storage := map[string]rest.Storage{}
v1alpha1storage["flunders"] = wardlestorage.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter)
apiGroupInfo.VersionedResourcesStorageMap["v1alpha1"] = v1alpha1storage
if err := s.GenericAPIServer.InstallAPIGroup(&apiGroupInfo); err != nil {
return nil, err
}
return s, nil
}
/*
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 server
import (
"fmt"
"io"
"github.com/pborman/uuid"
"github.com/spf13/cobra"
genericapiserver "k8s.io/apiserver/pkg/server"
genericoptions "k8s.io/apiserver/pkg/server/options"
"k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1"
"k8s.io/sample-apiserver/pkg/apiserver"
)
const defaultEtcdPathPrefix = "/registry/wardle.kubernetes.io"
type WardleServerOptions struct {
RecommendedOptions *genericoptions.RecommendedOptions
StdOut io.Writer
StdErr io.Writer
}
func NewWardleServerOptions(out, errOut io.Writer) *WardleServerOptions {
o := &WardleServerOptions{
RecommendedOptions: genericoptions.NewRecommendedOptions(defaultEtcdPathPrefix, apiserver.Scheme, apiserver.Codecs.LegacyCodec(v1alpha1.SchemeGroupVersion)),
StdOut: out,
StdErr: errOut,
}
o.RecommendedOptions.SecureServing.ServingOptions.BindPort = 443
return o
}
// NewCommandStartMaster provides a CLI handler for 'start master' command
func NewCommandStartWardleServer(out, errOut io.Writer, stopCh <-chan struct{}) *cobra.Command {
o := NewWardleServerOptions(out, errOut)
cmd := &cobra.Command{
Short: "Launch a wardle API server",
Long: "Launch a wardle API server",
RunE: func(c *cobra.Command, args []string) error {
if err := o.Complete(); err != nil {
return err
}
if err := o.Validate(args); err != nil {
return err
}
if err := o.RunWardleServer(stopCh); err != nil {
return err
}
return nil
},
}
flags := cmd.Flags()
o.RecommendedOptions.AddFlags(flags)
return cmd
}
func (o WardleServerOptions) Validate(args []string) error {
return nil
}
func (o *WardleServerOptions) Complete() error {
return nil
}
func (o WardleServerOptions) Config() (*apiserver.Config, error) {
// TODO have a "real" external address
if err := o.RecommendedOptions.SecureServing.MaybeDefaultWithSelfSignedCerts("localhost"); err != nil {
return nil, fmt.Errorf("error creating self-signed certificates: %v", err)
}
serverConfig := genericapiserver.NewConfig().WithSerializer(apiserver.Codecs)
if err := o.RecommendedOptions.ApplyTo(serverConfig); err != nil {
return nil, err
}
var err error
privilegedLoopbackToken := uuid.NewRandom().String()
if serverConfig.LoopbackClientConfig, err = serverConfig.SecureServingInfo.NewSelfClientConfig(privilegedLoopbackToken); err != nil {
return nil, err
}
config := &apiserver.Config{
GenericConfig: serverConfig,
}
return config, nil
}
func (o WardleServerOptions) RunWardleServer(stopCh <-chan struct{}) error {
config, err := o.Config()
if err != nil {
return err
}
server, err := config.Complete().New()
if err != nil {
return err
}
server.GenericAPIServer.PrepareRun().Run(stopCh)
return nil
}
/*
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 wardle
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/generic"
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
"k8s.io/sample-apiserver/pkg/apis/wardle"
)
// rest implements a RESTStorage for API services against etcd
type REST struct {
*genericregistry.Store
}
// NewREST returns a RESTStorage object that will work against API services.
func NewREST(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter) *REST {
strategy := NewStrategy(scheme)
store := &genericregistry.Store{
Copier: scheme,
NewFunc: func() runtime.Object { return &wardle.Flunder{} },
NewListFunc: func() runtime.Object { return &wardle.FlunderList{} },
ObjectNameFunc: func(obj runtime.Object) (string, error) {
return obj.(*wardle.Flunder).Name, nil
},
PredicateFunc: MatchFlunder,
QualifiedResource: wardle.Resource("flunders"),
CreateStrategy: strategy,
UpdateStrategy: strategy,
DeleteStrategy: strategy,
}
options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: GetAttrs}
if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up
}
return &REST{store}
}
/*
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 wardle
import (
"fmt"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/storage"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/sample-apiserver/pkg/apis/wardle"
)
type apiServerStrategy struct {
runtime.ObjectTyper
names.NameGenerator
}
func NewStrategy(typer runtime.ObjectTyper) apiServerStrategy {
return apiServerStrategy{typer, names.SimpleNameGenerator}
}
func (apiServerStrategy) NamespaceScoped() bool {
return false
}
func (apiServerStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) {
}
func (apiServerStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) {
}
func (apiServerStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList {
return field.ErrorList{}
// return validation.ValidateFlunder(obj.(*wardle.Flunder))
}
func (apiServerStrategy) AllowCreateOnUpdate() bool {
return false
}
func (apiServerStrategy) AllowUnconditionalUpdate() bool {
return false
}
func (apiServerStrategy) Canonicalize(obj runtime.Object) {
}
func (apiServerStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList {
return field.ErrorList{}
// return validation.ValidateFlunderUpdate(obj.(*wardle.Flunder), old.(*wardle.Flunder))
}
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
apiserver, ok := obj.(*wardle.Flunder)
if !ok {
return nil, nil, fmt.Errorf("given object is not a Flunder.")
}
return labels.Set(apiserver.ObjectMeta.Labels), FlunderToSelectableFields(apiserver), nil
}
// MatchFlunder is the filter used by the generic etcd backend to watch events
// from etcd to clients of the apiserver only interested in specific labels/fields.
func MatchFlunder(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
return storage.SelectionPredicate{
Label: label,
Field: field,
GetAttrs: GetAttrs,
}
}
// FlunderToSelectableFields returns a field set that represents the object.
func FlunderToSelectableFields(obj *wardle.Flunder) fields.Set {
return generic.ObjectMetaFieldsSet(&obj.ObjectMeta, true)
}
...@@ -12,11 +12,15 @@ go_test( ...@@ -12,11 +12,15 @@ go_test(
srcs = ["apiserver_test.go"], srcs = ["apiserver_test.go"],
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//cmd/libs/go2idl/client-gen/test_apis/testgroup/v1:go_default_library", "//test/integration/framework:go_default_library",
"//examples/apiserver:go_default_library",
"//vendor:github.com/golang/glog", "//vendor:github.com/golang/glog",
"//vendor:github.com/stretchr/testify/assert", "//vendor:github.com/stretchr/testify/assert",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/client-go/rest",
"//vendor:k8s.io/client-go/tools/clientcmd",
"//vendor:k8s.io/client-go/tools/clientcmd/api",
"//vendor:k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1",
"//vendor:k8s.io/sample-apiserver/pkg/cmd/server",
], ],
) )
......
...@@ -22,18 +22,25 @@ import ( ...@@ -22,18 +22,25 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"os"
"testing" "testing"
"time" "time"
"k8s.io/kubernetes/cmd/libs/go2idl/client-gen/test_apis/testgroup/v1"
"github.com/golang/glog" "github.com/golang/glog"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/examples/apiserver" "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"k8s.io/kubernetes/test/integration/framework"
"k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1"
"k8s.io/sample-apiserver/pkg/cmd/server"
) )
var groupVersion = v1.SchemeGroupVersion const securePort = "6444"
var groupVersion = v1alpha1.SchemeGroupVersion
var groupVersionForDiscovery = metav1.GroupVersionForDiscovery{ var groupVersionForDiscovery = metav1.GroupVersionForDiscovery{
GroupVersion: groupVersion.String(), GroupVersion: groupVersion.String(),
...@@ -41,52 +48,85 @@ var groupVersionForDiscovery = metav1.GroupVersionForDiscovery{ ...@@ -41,52 +48,85 @@ var groupVersionForDiscovery = metav1.GroupVersionForDiscovery{
} }
func TestRunServer(t *testing.T) { func TestRunServer(t *testing.T) {
serverIP := fmt.Sprintf("http://localhost:%d", apiserver.InsecurePort) masterConfig := framework.NewIntegrationTestMasterConfig()
_, s := framework.RunAMaster(masterConfig)
defer s.Close()
adminKubeConfig := createKubeConfig(masterConfig.GenericConfig.LoopbackClientConfig)
kubeconfigFile, _ := ioutil.TempFile("", "")
defer os.Remove(kubeconfigFile.Name())
clientcmd.WriteToFile(*adminKubeConfig, kubeconfigFile.Name())
stopCh := make(chan struct{}) stopCh := make(chan struct{})
go func() {
if err := apiserver.NewServerRunOptions().Run(stopCh); err != nil {
t.Fatalf("Error in bringing up the server: %v", err)
}
}()
defer close(stopCh) defer close(stopCh)
if err := waitForApiserverUp(serverIP); err != nil { cmd := server.NewCommandStartWardleServer(os.Stdout, os.Stderr, stopCh)
cmd.SetArgs([]string{
"--secure-port", securePort,
"--requestheader-username-headers", "",
"--authentication-kubeconfig", kubeconfigFile.Name(),
"--authorization-kubeconfig", kubeconfigFile.Name(),
"--etcd-servers", framework.GetEtcdURLFromEnv(),
})
go cmd.Execute()
serverLocation := fmt.Sprintf("https://localhost:%s", securePort)
if err := waitForApiserverUp(serverLocation); err != nil {
t.Fatalf("%v", err) t.Fatalf("%v", err)
} }
testSwaggerSpec(t, serverIP)
testAPIGroupList(t, serverIP) testAPIGroupList(t, serverLocation)
testAPIGroup(t, serverIP) testAPIGroup(t, serverLocation)
testAPIResourceList(t, serverIP) testAPIResourceList(t, serverLocation)
} }
func TestRunSecureServer(t *testing.T) { func createKubeConfig(clientCfg *rest.Config) *clientcmdapi.Config {
serverIP := fmt.Sprintf("https://localhost:%d", apiserver.SecurePort) clusterNick := "cluster"
stopCh := make(chan struct{}) userNick := "user"
go func() { contextNick := "context"
options := apiserver.NewServerRunOptions()
options.InsecureServing.BindPort = 0 config := clientcmdapi.NewConfig()
options.SecureServing.ServingOptions.BindPort = apiserver.SecurePort
if err := options.Run(stopCh); err != nil { credentials := clientcmdapi.NewAuthInfo()
t.Fatalf("Error in bringing up the server: %v", err) credentials.Token = clientCfg.BearerToken
} credentials.ClientCertificate = clientCfg.TLSClientConfig.CertFile
}() if len(credentials.ClientCertificate) == 0 {
defer close(stopCh) credentials.ClientCertificateData = clientCfg.TLSClientConfig.CertData
if err := waitForApiserverUp(serverIP); err != nil { }
t.Fatalf("%v", err) credentials.ClientKey = clientCfg.TLSClientConfig.KeyFile
if len(credentials.ClientKey) == 0 {
credentials.ClientKeyData = clientCfg.TLSClientConfig.KeyData
}
config.AuthInfos[userNick] = credentials
cluster := clientcmdapi.NewCluster()
cluster.Server = clientCfg.Host
cluster.CertificateAuthority = clientCfg.CAFile
if len(cluster.CertificateAuthority) == 0 {
cluster.CertificateAuthorityData = clientCfg.CAData
}
cluster.InsecureSkipTLSVerify = clientCfg.Insecure
if clientCfg.GroupVersion != nil {
cluster.APIVersion = clientCfg.GroupVersion.String()
} }
testSwaggerSpec(t, serverIP) config.Clusters[clusterNick] = cluster
testAPIGroupList(t, serverIP)
testAPIGroup(t, serverIP) context := clientcmdapi.NewContext()
testAPIResourceList(t, serverIP) context.Cluster = clusterNick
context.AuthInfo = userNick
config.Contexts[contextNick] = context
config.CurrentContext = contextNick
return config
} }
func waitForApiserverUp(serverIP string) error { func waitForApiserverUp(serverLocation string) error {
for start := time.Now(); time.Since(start) < time.Minute; time.Sleep(5 * time.Second) { for start := time.Now(); time.Since(start) < 10*time.Second; time.Sleep(5 * time.Second) {
glog.Errorf("Waiting for : %#v", serverIP) glog.Errorf("Waiting for : %#v", serverLocation)
tr := &http.Transport{ tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
} }
client := &http.Client{Transport: tr} client := &http.Client{Transport: tr}
_, err := client.Get(serverIP) _, err := client.Get(serverLocation)
if err == nil { if err == nil {
return nil return nil
} }
...@@ -116,65 +156,58 @@ func readResponse(serverURL string) ([]byte, error) { ...@@ -116,65 +156,58 @@ func readResponse(serverURL string) ([]byte, error) {
return contents, nil return contents, nil
} }
func testSwaggerSpec(t *testing.T, serverIP string) { func testAPIGroupList(t *testing.T, serverLocation string) {
serverURL := serverIP + "/swaggerapi" serverURL := serverLocation + "/apis"
_, err := readResponse(serverURL)
if err != nil {
t.Fatalf("%v", err)
}
}
func testAPIGroupList(t *testing.T, serverIP string) {
serverURL := serverIP + "/apis"
contents, err := readResponse(serverURL) contents, err := readResponse(serverURL)
if err != nil { if err != nil {
t.Fatalf("%v", err) t.Fatalf("%v", err)
} }
t.Log(string(contents))
var apiGroupList metav1.APIGroupList var apiGroupList metav1.APIGroupList
err = json.Unmarshal(contents, &apiGroupList) err = json.Unmarshal(contents, &apiGroupList)
if err != nil { if err != nil {
t.Fatalf("Error in unmarshalling response from server %s: %v", serverURL, err) t.Fatalf("Error in unmarshalling response from server %s: %v", serverURL, err)
} }
assert.Equal(t, 1, len(apiGroupList.Groups)) assert.Equal(t, 1, len(apiGroupList.Groups))
assert.Equal(t, apiGroupList.Groups[0].Name, groupVersion.Group) assert.Equal(t, groupVersion.Group, apiGroupList.Groups[0].Name)
assert.Equal(t, 1, len(apiGroupList.Groups[0].Versions)) assert.Equal(t, 1, len(apiGroupList.Groups[0].Versions))
assert.Equal(t, apiGroupList.Groups[0].Versions[0], groupVersionForDiscovery) assert.Equal(t, groupVersionForDiscovery, apiGroupList.Groups[0].Versions[0])
assert.Equal(t, apiGroupList.Groups[0].PreferredVersion, groupVersionForDiscovery) assert.Equal(t, groupVersionForDiscovery, apiGroupList.Groups[0].PreferredVersion)
} }
func testAPIGroup(t *testing.T, serverIP string) { func testAPIGroup(t *testing.T, serverLocation string) {
serverURL := serverIP + "/apis/testgroup.k8s.io" serverURL := serverLocation + "/apis/wardle.k8s.io"
contents, err := readResponse(serverURL) contents, err := readResponse(serverURL)
if err != nil { if err != nil {
t.Fatalf("%v", err) t.Fatalf("%v", err)
} }
t.Log(string(contents))
var apiGroup metav1.APIGroup var apiGroup metav1.APIGroup
err = json.Unmarshal(contents, &apiGroup) err = json.Unmarshal(contents, &apiGroup)
if err != nil { if err != nil {
t.Fatalf("Error in unmarshalling response from server %s: %v", serverURL, err) t.Fatalf("Error in unmarshalling response from server %s: %v", serverURL, err)
} }
assert.Equal(t, apiGroup.APIVersion, groupVersion.Version) assert.Equal(t, groupVersion.Group, apiGroup.Name)
assert.Equal(t, apiGroup.Name, groupVersion.Group)
assert.Equal(t, 1, len(apiGroup.Versions)) assert.Equal(t, 1, len(apiGroup.Versions))
assert.Equal(t, apiGroup.Versions[0].GroupVersion, groupVersion.String()) assert.Equal(t, groupVersion.String(), apiGroup.Versions[0].GroupVersion)
assert.Equal(t, apiGroup.Versions[0].Version, groupVersion.Version) assert.Equal(t, groupVersion.Version, apiGroup.Versions[0].Version)
assert.Equal(t, apiGroup.Versions[0], apiGroup.PreferredVersion) assert.Equal(t, apiGroup.PreferredVersion, apiGroup.Versions[0])
} }
func testAPIResourceList(t *testing.T, serverIP string) { func testAPIResourceList(t *testing.T, serverLocation string) {
serverURL := serverIP + "/apis/testgroup.k8s.io/v1" serverURL := serverLocation + "/apis/wardle.k8s.io/v1alpha1"
contents, err := readResponse(serverURL) contents, err := readResponse(serverURL)
if err != nil { if err != nil {
t.Fatalf("%v", err) t.Fatalf("%v", err)
} }
t.Log(string(contents))
var apiResourceList metav1.APIResourceList var apiResourceList metav1.APIResourceList
err = json.Unmarshal(contents, &apiResourceList) err = json.Unmarshal(contents, &apiResourceList)
if err != nil { if err != nil {
t.Fatalf("Error in unmarshalling response from server %s: %v", serverURL, err) t.Fatalf("Error in unmarshalling response from server %s: %v", serverURL, err)
} }
assert.Equal(t, apiResourceList.APIVersion, groupVersion.Version) assert.Equal(t, groupVersion.String(), apiResourceList.GroupVersion)
assert.Equal(t, apiResourceList.GroupVersion, groupVersion.String())
assert.Equal(t, 1, len(apiResourceList.APIResources)) assert.Equal(t, 1, len(apiResourceList.APIResources))
assert.Equal(t, apiResourceList.APIResources[0].Name, "testtypes") assert.Equal(t, "flunders", apiResourceList.APIResources[0].Name)
assert.True(t, apiResourceList.APIResources[0].Namespaced) assert.True(t, apiResourceList.APIResources[0].Namespaced)
} }
...@@ -34,6 +34,7 @@ go_library( ...@@ -34,6 +34,7 @@ go_library(
"//pkg/controller:go_default_library", "//pkg/controller:go_default_library",
"//pkg/controller/replication:go_default_library", "//pkg/controller/replication:go_default_library",
"//pkg/generated/openapi:go_default_library", "//pkg/generated/openapi:go_default_library",
"//pkg/kubeapiserver:go_default_library",
"//pkg/kubectl:go_default_library", "//pkg/kubectl:go_default_library",
"//pkg/kubelet/client:go_default_library", "//pkg/kubelet/client:go_default_library",
"//pkg/master:go_default_library", "//pkg/master:go_default_library",
......
...@@ -61,6 +61,7 @@ import ( ...@@ -61,6 +61,7 @@ import (
"k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller"
replicationcontroller "k8s.io/kubernetes/pkg/controller/replication" replicationcontroller "k8s.io/kubernetes/pkg/controller/replication"
"k8s.io/kubernetes/pkg/generated/openapi" "k8s.io/kubernetes/pkg/generated/openapi"
"k8s.io/kubernetes/pkg/kubeapiserver"
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
kubeletclient "k8s.io/kubernetes/pkg/kubelet/client" kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
"k8s.io/kubernetes/pkg/master" "k8s.io/kubernetes/pkg/master"
...@@ -364,13 +365,18 @@ func NewMasterConfig() *master.Config { ...@@ -364,13 +365,18 @@ func NewMasterConfig() *master.Config {
genericConfig.Authorizer = authorizerfactory.NewAlwaysAllowAuthorizer() genericConfig.Authorizer = authorizerfactory.NewAlwaysAllowAuthorizer()
genericConfig.AdmissionControl = admit.NewAlwaysAdmit() genericConfig.AdmissionControl = admit.NewAlwaysAdmit()
genericConfig.EnableMetrics = true genericConfig.EnableMetrics = true
genericConfig.RESTOptionsGetter = &kubeapiserver.RESTOptionsFactory{
StorageFactory: storageFactory,
EnableWatchCache: true,
EnableGarbageCollection: true,
DeleteCollectionWorkers: 1,
}
return &master.Config{ return &master.Config{
GenericConfig: genericConfig, GenericConfig: genericConfig,
APIResourceConfigSource: master.DefaultAPIResourceConfigSource(), APIResourceConfigSource: master.DefaultAPIResourceConfigSource(),
StorageFactory: storageFactory, StorageFactory: storageFactory,
EnableCoreControllers: true, EnableCoreControllers: true,
EnableWatchCache: true,
KubeletClientConfig: kubeletclient.KubeletClientConfig{Port: 10250}, KubeletClientConfig: kubeletclient.KubeletClientConfig{Port: 10250},
APIServerServicePort: 443, APIServerServicePort: 443,
MasterCount: 1, MasterCount: 1,
......
...@@ -122,7 +122,6 @@ func newOwnerRC(name, namespace string) *v1.ReplicationController { ...@@ -122,7 +122,6 @@ func newOwnerRC(name, namespace string) *v1.ReplicationController {
func setup(t *testing.T) (*httptest.Server, *garbagecollector.GarbageCollector, clientset.Interface) { func setup(t *testing.T) (*httptest.Server, *garbagecollector.GarbageCollector, clientset.Interface) {
masterConfig := framework.NewIntegrationTestMasterConfig() masterConfig := framework.NewIntegrationTestMasterConfig()
masterConfig.EnableCoreControllers = false masterConfig.EnableCoreControllers = false
masterConfig.GenericConfig.EnableGarbageCollection = true
_, s := framework.RunAMaster(masterConfig) _, s := framework.RunAMaster(masterConfig)
clientSet, err := clientset.NewForConfig(&restclient.Config{Host: s.URL}) clientSet, err := clientset.NewForConfig(&restclient.Config{Host: s.URL})
......
...@@ -9098,6 +9098,7 @@ go_library( ...@@ -9098,6 +9098,7 @@ go_library(
"//vendor:k8s.io/apiserver/pkg/endpoints/filters", "//vendor:k8s.io/apiserver/pkg/endpoints/filters",
"//vendor:k8s.io/apiserver/pkg/endpoints/openapi", "//vendor:k8s.io/apiserver/pkg/endpoints/openapi",
"//vendor:k8s.io/apiserver/pkg/endpoints/request", "//vendor:k8s.io/apiserver/pkg/endpoints/request",
"//vendor:k8s.io/apiserver/pkg/registry/generic",
"//vendor:k8s.io/apiserver/pkg/registry/rest", "//vendor:k8s.io/apiserver/pkg/registry/rest",
"//vendor:k8s.io/apiserver/pkg/server/filters", "//vendor:k8s.io/apiserver/pkg/server/filters",
"//vendor:k8s.io/apiserver/pkg/server/healthz", "//vendor:k8s.io/apiserver/pkg/server/healthz",
...@@ -14106,11 +14107,14 @@ go_library( ...@@ -14106,11 +14107,14 @@ go_library(
"//vendor:gopkg.in/natefinch/lumberjack.v2", "//vendor:gopkg.in/natefinch/lumberjack.v2",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1", "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/runtime", "//vendor:k8s.io/apimachinery/pkg/runtime",
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
"//vendor:k8s.io/apimachinery/pkg/util/net", "//vendor:k8s.io/apimachinery/pkg/util/net",
"//vendor:k8s.io/apiserver/pkg/admission", "//vendor:k8s.io/apiserver/pkg/admission",
"//vendor:k8s.io/apiserver/pkg/authentication/authenticatorfactory", "//vendor:k8s.io/apiserver/pkg/authentication/authenticatorfactory",
"//vendor:k8s.io/apiserver/pkg/authorization/authorizerfactory", "//vendor:k8s.io/apiserver/pkg/authorization/authorizerfactory",
"//vendor:k8s.io/apiserver/pkg/features", "//vendor:k8s.io/apiserver/pkg/features",
"//vendor:k8s.io/apiserver/pkg/registry/generic",
"//vendor:k8s.io/apiserver/pkg/registry/generic/registry",
"//vendor:k8s.io/apiserver/pkg/server", "//vendor:k8s.io/apiserver/pkg/server",
"//vendor:k8s.io/apiserver/pkg/storage/storagebackend", "//vendor:k8s.io/apiserver/pkg/storage/storagebackend",
"//vendor:k8s.io/apiserver/pkg/util/feature", "//vendor:k8s.io/apiserver/pkg/util/feature",
...@@ -15277,3 +15281,125 @@ go_test( ...@@ -15277,3 +15281,125 @@ go_test(
"//vendor:k8s.io/client-go/util/cert", "//vendor:k8s.io/client-go/util/cert",
], ],
) )
go_binary(
name = "k8s.io/sample-apiserver_bin",
library = ":k8s.io/sample-apiserver",
tags = ["automanaged"],
)
go_library(
name = "k8s.io/sample-apiserver",
srcs = ["k8s.io/sample-apiserver/main.go"],
tags = ["automanaged"],
deps = [
"//vendor:k8s.io/apimachinery/pkg/util/wait",
"//vendor:k8s.io/sample-apiserver/pkg/cmd/server",
],
)
go_library(
name = "k8s.io/sample-apiserver/pkg/apis/wardle",
srcs = [
"k8s.io/sample-apiserver/pkg/apis/wardle/doc.go",
"k8s.io/sample-apiserver/pkg/apis/wardle/register.go",
"k8s.io/sample-apiserver/pkg/apis/wardle/types.go",
"k8s.io/sample-apiserver/pkg/apis/wardle/zz_generated.deepcopy.go",
],
tags = ["automanaged"],
deps = [
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/conversion",
"//vendor:k8s.io/apimachinery/pkg/runtime",
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
],
)
go_library(
name = "k8s.io/sample-apiserver/pkg/apis/wardle/install",
srcs = ["k8s.io/sample-apiserver/pkg/apis/wardle/install/install.go"],
tags = ["automanaged"],
deps = [
"//vendor:k8s.io/apimachinery/pkg/apimachinery/announced",
"//vendor:k8s.io/apimachinery/pkg/apimachinery/registered",
"//vendor:k8s.io/apimachinery/pkg/runtime",
"//vendor:k8s.io/apimachinery/pkg/util/sets",
"//vendor:k8s.io/sample-apiserver/pkg/apis/wardle",
"//vendor:k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1",
],
)
go_library(
name = "k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1",
srcs = [
"k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/doc.go",
"k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/register.go",
"k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/types.go",
"k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/zz_generated.conversion.go",
"k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/zz_generated.deepcopy.go",
],
tags = ["automanaged"],
deps = [
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/conversion",
"//vendor:k8s.io/apimachinery/pkg/runtime",
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
"//vendor:k8s.io/sample-apiserver/pkg/apis/wardle",
],
)
go_library(
name = "k8s.io/sample-apiserver/pkg/apiserver",
srcs = ["k8s.io/sample-apiserver/pkg/apiserver/apiserver.go"],
tags = ["automanaged"],
deps = [
"//vendor:k8s.io/apimachinery/pkg/apimachinery/announced",
"//vendor:k8s.io/apimachinery/pkg/apimachinery/registered",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/runtime",
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
"//vendor:k8s.io/apimachinery/pkg/runtime/serializer",
"//vendor:k8s.io/apimachinery/pkg/version",
"//vendor:k8s.io/apiserver/pkg/registry/rest",
"//vendor:k8s.io/apiserver/pkg/server",
"//vendor:k8s.io/sample-apiserver/pkg/apis/wardle",
"//vendor:k8s.io/sample-apiserver/pkg/apis/wardle/install",
"//vendor:k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1",
"//vendor:k8s.io/sample-apiserver/pkg/registry/wardle",
],
)
go_library(
name = "k8s.io/sample-apiserver/pkg/cmd/server",
srcs = ["k8s.io/sample-apiserver/pkg/cmd/server/start.go"],
tags = ["automanaged"],
deps = [
"//vendor:github.com/pborman/uuid",
"//vendor:github.com/spf13/cobra",
"//vendor:k8s.io/apiserver/pkg/server",
"//vendor:k8s.io/apiserver/pkg/server/options",
"//vendor:k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1",
"//vendor:k8s.io/sample-apiserver/pkg/apiserver",
],
)
go_library(
name = "k8s.io/sample-apiserver/pkg/registry/wardle",
srcs = [
"k8s.io/sample-apiserver/pkg/registry/wardle/etcd.go",
"k8s.io/sample-apiserver/pkg/registry/wardle/strategy.go",
],
tags = ["automanaged"],
deps = [
"//vendor:k8s.io/apimachinery/pkg/fields",
"//vendor:k8s.io/apimachinery/pkg/labels",
"//vendor:k8s.io/apimachinery/pkg/runtime",
"//vendor:k8s.io/apimachinery/pkg/util/validation/field",
"//vendor:k8s.io/apiserver/pkg/endpoints/request",
"//vendor:k8s.io/apiserver/pkg/registry/generic",
"//vendor:k8s.io/apiserver/pkg/registry/generic/registry",
"//vendor:k8s.io/apiserver/pkg/storage",
"//vendor:k8s.io/apiserver/pkg/storage/names",
"//vendor:k8s.io/sample-apiserver/pkg/apis/wardle",
],
)
../../staging/src/k8s.io/sample-apiserver
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment