create apiserver for extensions
This commit is contained in:
		
							
								
								
									
										42
									
								
								staging/src/k8s.io/kube-apiextensions-server/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								staging/src/k8s.io/kube-apiextensions-server/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| /* | ||||
| 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 main | ||||
|  | ||||
| import ( | ||||
| 	"flag" | ||||
| 	"os" | ||||
| 	"runtime" | ||||
|  | ||||
| 	"k8s.io/apimachinery/pkg/util/wait" | ||||
| 	"k8s.io/apiserver/pkg/util/logs" | ||||
| 	"k8s.io/kube-apiextensions-server/pkg/cmd/server" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	logs.InitLogs() | ||||
| 	defer logs.FlushLogs() | ||||
|  | ||||
| 	if len(os.Getenv("GOMAXPROCS")) == 0 { | ||||
| 		runtime.GOMAXPROCS(runtime.NumCPU()) | ||||
| 	} | ||||
|  | ||||
| 	cmd := server.NewCommandStartCustomResourcesServer(os.Stdout, os.Stderr, wait.NeverStop) | ||||
| 	cmd.Flags().AddGoFlagSet(flag.CommandLine) | ||||
| 	if err := cmd.Execute(); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,116 @@ | ||||
| /* | ||||
| 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 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/kube-apiextensions-server/pkg/apis/apiextensions" | ||||
| 	"k8s.io/kube-apiextensions-server/pkg/apis/apiextensions/install" | ||||
| 	"k8s.io/kube-apiextensions-server/pkg/apis/apiextensions/v1alpha1" | ||||
| 	"k8s.io/kube-apiextensions-server/pkg/registry/customresource" | ||||
|  | ||||
| 	// make sure the generated client works | ||||
| 	_ "k8s.io/kube-apiextensions-server/pkg/client/clientset/clientset" | ||||
| 	_ "k8s.io/kube-apiextensions-server/pkg/client/clientset/internalclientset" | ||||
| 	_ "k8s.io/kube-apiextensions-server/pkg/client/informers/externalversions" | ||||
| 	_ "k8s.io/kube-apiextensions-server/pkg/client/informers/internalversion" | ||||
| ) | ||||
|  | ||||
| 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 | ||||
| 	metav1.AddToGroupVersion(Scheme, schema.GroupVersion{Group: "", Version: "v1"}) | ||||
|  | ||||
| 	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 | ||||
| } | ||||
|  | ||||
| type CustomResources 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: "0", | ||||
| 		Minor: "1", | ||||
| 	} | ||||
|  | ||||
| 	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 CustomResources from the given config. | ||||
| func (c completedConfig) New() (*CustomResources, 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 := &CustomResources{ | ||||
| 		GenericAPIServer: genericServer, | ||||
| 	} | ||||
|  | ||||
| 	apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apiextensions.GroupName, registry, Scheme, metav1.ParameterCodec, Codecs) | ||||
| 	apiGroupInfo.GroupMeta.GroupVersion = v1alpha1.SchemeGroupVersion | ||||
| 	v1alpha1storage := map[string]rest.Storage{} | ||||
| 	v1alpha1storage["customresources"] = customresource.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter) | ||||
| 	apiGroupInfo.VersionedResourcesStorageMap["v1alpha1"] = v1alpha1storage | ||||
|  | ||||
| 	if err := s.GenericAPIServer.InstallAPIGroup(&apiGroupInfo); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return s, nil | ||||
| } | ||||
| @@ -0,0 +1,114 @@ | ||||
| /* | ||||
| 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 server | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net" | ||||
|  | ||||
| 	"github.com/spf13/cobra" | ||||
|  | ||||
| 	genericapiserver "k8s.io/apiserver/pkg/server" | ||||
| 	genericoptions "k8s.io/apiserver/pkg/server/options" | ||||
| 	"k8s.io/kube-apiextensions-server/pkg/apis/apiextensions/v1alpha1" | ||||
| 	"k8s.io/kube-apiextensions-server/pkg/apiserver" | ||||
| ) | ||||
|  | ||||
| const defaultEtcdPathPrefix = "/registry/apiextensions.kubernetes.io" | ||||
|  | ||||
| type CustomResourcesServerOptions struct { | ||||
| 	RecommendedOptions *genericoptions.RecommendedOptions | ||||
|  | ||||
| 	StdOut io.Writer | ||||
| 	StdErr io.Writer | ||||
| } | ||||
|  | ||||
| func NewCustomResourcesServerOptions(out, errOut io.Writer) *CustomResourcesServerOptions { | ||||
| 	o := &CustomResourcesServerOptions{ | ||||
| 		RecommendedOptions: genericoptions.NewRecommendedOptions(defaultEtcdPathPrefix, apiserver.Scheme, apiserver.Codecs.LegacyCodec(v1alpha1.SchemeGroupVersion)), | ||||
|  | ||||
| 		StdOut: out, | ||||
| 		StdErr: errOut, | ||||
| 	} | ||||
|  | ||||
| 	return o | ||||
| } | ||||
|  | ||||
| func NewCommandStartCustomResourcesServer(out, errOut io.Writer, stopCh <-chan struct{}) *cobra.Command { | ||||
| 	o := NewCustomResourcesServerOptions(out, errOut) | ||||
|  | ||||
| 	cmd := &cobra.Command{ | ||||
| 		Short: "Launch an API extensions API server", | ||||
| 		Long:  "Launch an API extensions 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.RunCustomResourcesServer(stopCh); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			return nil | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	flags := cmd.Flags() | ||||
| 	o.RecommendedOptions.AddFlags(flags) | ||||
|  | ||||
| 	return cmd | ||||
| } | ||||
|  | ||||
| func (o CustomResourcesServerOptions) Validate(args []string) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (o *CustomResourcesServerOptions) Complete() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (o CustomResourcesServerOptions) Config() (*apiserver.Config, error) { | ||||
| 	// TODO have a "real" external address | ||||
| 	if err := o.RecommendedOptions.SecureServing.MaybeDefaultWithSelfSignedCerts("localhost", nil, []net.IP{net.ParseIP("127.0.0.1")}); err != nil { | ||||
| 		return nil, fmt.Errorf("error creating self-signed certificates: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	serverConfig := genericapiserver.NewConfig(apiserver.Codecs) | ||||
| 	if err := o.RecommendedOptions.ApplyTo(serverConfig); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	config := &apiserver.Config{ | ||||
| 		GenericConfig: serverConfig, | ||||
| 	} | ||||
| 	return config, nil | ||||
| } | ||||
|  | ||||
| func (o CustomResourcesServerOptions) RunCustomResourcesServer(stopCh <-chan struct{}) error { | ||||
| 	config, err := o.Config() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	server, err := config.Complete().New() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return server.GenericAPIServer.PrepareRun().Run(stopCh) | ||||
| } | ||||
| @@ -0,0 +1,54 @@ | ||||
| /* | ||||
| 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 customresource | ||||
|  | ||||
| import ( | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apiserver/pkg/registry/generic" | ||||
| 	genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" | ||||
| 	"k8s.io/kube-apiextensions-server/pkg/apis/apiextensions" | ||||
| ) | ||||
|  | ||||
| // 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 &apiextensions.CustomResource{} }, | ||||
| 		NewListFunc: func() runtime.Object { return &apiextensions.CustomResourceList{} }, | ||||
| 		ObjectNameFunc: func(obj runtime.Object) (string, error) { | ||||
| 			return obj.(*apiextensions.CustomResource).Name, nil | ||||
| 		}, | ||||
| 		PredicateFunc:     MatchCustomResource, | ||||
| 		QualifiedResource: apiextensions.Resource("customresources"), | ||||
|  | ||||
| 		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} | ||||
| } | ||||
| @@ -0,0 +1,93 @@ | ||||
| /* | ||||
| 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 customresource | ||||
|  | ||||
| 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/kube-apiextensions-server/pkg/apis/apiextensions" | ||||
| ) | ||||
|  | ||||
| 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{} | ||||
| } | ||||
|  | ||||
| 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{} | ||||
| } | ||||
|  | ||||
| func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { | ||||
| 	apiserver, ok := obj.(*apiextensions.CustomResource) | ||||
| 	if !ok { | ||||
| 		return nil, nil, fmt.Errorf("given object is not a CustomResource.") | ||||
| 	} | ||||
| 	return labels.Set(apiserver.ObjectMeta.Labels), CustomResourceToSelectableFields(apiserver), nil | ||||
| } | ||||
|  | ||||
| // MatchCustomResource 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 MatchCustomResource(label labels.Selector, field fields.Selector) storage.SelectionPredicate { | ||||
| 	return storage.SelectionPredicate{ | ||||
| 		Label:    label, | ||||
| 		Field:    field, | ||||
| 		GetAttrs: GetAttrs, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // CustomResourceToSelectableFields returns a field set that represents the object. | ||||
| func CustomResourceToSelectableFields(obj *apiextensions.CustomResource) fields.Set { | ||||
| 	return generic.ObjectMetaFieldsSet(&obj.ObjectMeta, true) | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 deads2k
					deads2k