feat: add crd gen

Signed-off-by: runzexia <runzexia@yunify.com>
This commit is contained in:
runzexia
2019-07-30 13:36:54 +08:00
parent 9ce52aeb00
commit 1c10391faf
817 changed files with 203429 additions and 27953 deletions

View File

@@ -0,0 +1,95 @@
package main
import (
"go/build"
"io/ioutil"
"k8s.io/apimachinery/pkg/api/meta"
"kubesphere.io/kubesphere/tools/lib"
"log"
"os"
"path/filepath"
"github.com/go-openapi/spec"
s2iv1alpha1 "github.com/kubesphere/s2ioperator/pkg/apis/devops/v1alpha1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
urlruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/kube-openapi/pkg/common"
tenantinstall "kubesphere.io/kubesphere/pkg/apis/tenant/crdinstall"
tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
)
func main() {
var (
Scheme = runtime.NewScheme()
Codecs = serializer.NewCodecFactory(Scheme)
)
// tmp install s2i api group because
// cannot use Scheme (type *"kubesphere.io/kubesphere/vendor/k8s.io/apimachinery/pkg/runtime".Scheme) as type *"github.com/kubesphere/s2ioperator/vendor/k8s.io/apimachinery/pkg/runtime".Scheme in argument to "github.com/kubesphere/s2ioperator/pkg/apis/devops/install".Install
urlruntime.Must(s2iv1alpha1.AddToScheme(Scheme))
urlruntime.Must(Scheme.SetVersionPriority(s2iv1alpha1.SchemeGroupVersion))
tenantinstall.Install(Scheme)
mapper := meta.NewDefaultRESTMapper(nil)
mapper.AddSpecific(tenantv1alpha1.SchemeGroupVersion.WithKind(tenantv1alpha1.ResourceKindWorkspace),
tenantv1alpha1.SchemeGroupVersion.WithResource(tenantv1alpha1.ResourcePluralWorkspace),
tenantv1alpha1.SchemeGroupVersion.WithResource(tenantv1alpha1.ResourceSingularWorkspace), meta.RESTScopeRoot)
mapper.AddSpecific(s2iv1alpha1.SchemeGroupVersion.WithKind(s2iv1alpha1.ResourceKindS2iBuilder),
s2iv1alpha1.SchemeGroupVersion.WithResource(s2iv1alpha1.ResourcePluralS2iBuilder),
s2iv1alpha1.SchemeGroupVersion.WithResource(s2iv1alpha1.ResourceSingularS2iBuilder), meta.RESTScopeRoot)
mapper.AddSpecific(s2iv1alpha1.SchemeGroupVersion.WithKind(s2iv1alpha1.ResourceKindS2iBuilderTemplate),
s2iv1alpha1.SchemeGroupVersion.WithResource(s2iv1alpha1.ResourcePluralS2iBuilderTemplate),
s2iv1alpha1.SchemeGroupVersion.WithResource(s2iv1alpha1.ResourceSingularS2iBuilderTemplate), meta.RESTScopeRoot)
mapper.AddSpecific(s2iv1alpha1.SchemeGroupVersion.WithKind(s2iv1alpha1.ResourceKindS2iRun),
s2iv1alpha1.SchemeGroupVersion.WithResource(s2iv1alpha1.ResourcePluralS2iRun),
s2iv1alpha1.SchemeGroupVersion.WithResource(s2iv1alpha1.ResourceSingularS2iRun), meta.RESTScopeRoot)
spec, err := lib.RenderOpenAPISpec(lib.Config{
Scheme: Scheme,
Codecs: Codecs,
Info: spec.InfoProps{
Title: "KubeSphere Advanced",
Version: "v2.0.0",
Contact: &spec.ContactInfo{
Name: "KubeSphere",
URL: "https://kubesphere.io/",
Email: "kubesphere@yunify.com",
},
License: &spec.License{
Name: "Apache 2.0",
URL: "https://www.apache.org/licenses/LICENSE-2.0.html",
},
},
OpenAPIDefinitions: []common.GetOpenAPIDefinitions{
tenantv1alpha1.GetOpenAPIDefinitions,
s2iv1alpha1.GetOpenAPIDefinitions,
},
Resources: []schema.GroupVersionResource{
tenantv1alpha1.SchemeGroupVersion.WithResource(tenantv1alpha1.ResourcePluralWorkspace),
s2iv1alpha1.SchemeGroupVersion.WithResource(s2iv1alpha1.ResourcePluralS2iRun),
s2iv1alpha1.SchemeGroupVersion.WithResource(s2iv1alpha1.ResourcePluralS2iBuilderTemplate),
s2iv1alpha1.SchemeGroupVersion.WithResource(s2iv1alpha1.ResourcePluralS2iBuilder),
},
Mapper: mapper,
})
if err != nil {
log.Fatal(err)
}
filename := build.Default.GOPATH + "/src/kubesphere.io/kubesphere/api/openapi-spec/swagger.json"
err = os.MkdirAll(filepath.Dir(filename), 0755)
if err != nil {
log.Fatal(err)
}
err = ioutil.WriteFile(filename, []byte(spec), 0644)
if err != nil {
log.Fatal(err)
}
}

159
tools/lib/render.go Normal file
View File

@@ -0,0 +1,159 @@
package lib
import (
"encoding/json"
"fmt"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apiserver/pkg/registry/rest"
"log"
"net"
"github.com/go-openapi/spec"
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"
apiopenapi "k8s.io/apiserver/pkg/endpoints/openapi"
genericapiserver "k8s.io/apiserver/pkg/server"
genericoptions "k8s.io/apiserver/pkg/server/options"
"k8s.io/kube-openapi/pkg/builder"
"k8s.io/kube-openapi/pkg/common"
)
type Config struct {
Scheme *runtime.Scheme
Codecs serializer.CodecFactory
Info spec.InfoProps
OpenAPIDefinitions []common.GetOpenAPIDefinitions
Resources []schema.GroupVersionResource
Mapper *meta.DefaultRESTMapper
}
func (c *Config) GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
out := map[string]common.OpenAPIDefinition{}
for _, def := range c.OpenAPIDefinitions {
for k, v := range def(ref) {
out[k] = v
}
}
return out
}
func RenderOpenAPISpec(cfg Config) (string, error) {
// we need to add the options to empty v1
// TODO fix the server code to avoid this
metav1.AddToGroupVersion(cfg.Scheme, schema.GroupVersion{Version: "v1"})
// TODO: keep the generic API server from wanting this
unversioned := schema.GroupVersion{Group: "", Version: "v1"}
cfg.Scheme.AddUnversionedTypes(unversioned,
&metav1.Status{},
&metav1.APIVersions{},
&metav1.APIGroupList{},
&metav1.APIGroup{},
&metav1.APIResourceList{},
)
recommendedOptions := genericoptions.NewRecommendedOptions("/registry/foo.com", cfg.Codecs.LegacyCodec(), nil)
recommendedOptions.SecureServing.BindPort = 8443
recommendedOptions.Etcd = nil
recommendedOptions.Authentication = nil
recommendedOptions.Authorization = nil
recommendedOptions.CoreAPI = nil
recommendedOptions.Admission = nil
// TODO have a "real" external address
if err := recommendedOptions.SecureServing.MaybeDefaultWithSelfSignedCerts("localhost", nil, []net.IP{net.ParseIP("127.0.0.1")}); err != nil {
log.Fatal(fmt.Errorf("error creating self-signed certificates: %v", err))
}
serverConfig := genericapiserver.NewRecommendedConfig(cfg.Codecs)
if err := recommendedOptions.ApplyTo(serverConfig, cfg.Scheme); err != nil {
log.Fatal(err)
return "", err
}
serverConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(cfg.GetOpenAPIDefinitions, apiopenapi.NewDefinitionNamer(cfg.Scheme))
serverConfig.OpenAPIConfig.Info.InfoProps = cfg.Info
genericServer, err := serverConfig.Complete().New("stash-server", genericapiserver.NewEmptyDelegate()) // completion is done in Complete, no need for a second time
if err != nil {
log.Fatal(err)
return "", err
}
{
// api router map
table := map[schema.GroupVersion]map[string]ResourceInfo{}
for _, gvr := range cfg.Resources {
var resmap map[string]ResourceInfo
// init ResourceInfo map
if m, found := table[gvr.GroupVersion()]; found {
resmap = m
} else {
resmap = map[string]ResourceInfo{}
table[gvr.GroupVersion()] = resmap
}
gvk, err := cfg.Mapper.KindFor(gvr)
if err != nil {
log.Fatal(err)
return "", err
}
obj, err := cfg.Scheme.New(gvk)
if err != nil {
return "", err
}
list, err := cfg.Scheme.New(gvk.GroupVersion().WithKind(gvk.Kind + "List"))
if err != nil {
log.Fatal(err)
return "", err
}
resmap[gvr.Resource] = ResourceInfo{
gvk: gvk,
obj: obj,
list: list,
}
}
for gv, resmap := range table {
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(gv.Group, cfg.Scheme, metav1.ParameterCodec, cfg.Codecs)
apiGroupInfo.MetaGroupVersion = &gv
storage := map[string]rest.Storage{}
for r, stuff := range resmap {
storage[r] = NewREST(stuff)
storage[r+"/status"] = NewStatusREST(
StatusResourceInfo{
gvk: struct {
Group string
Version string
Kind string
}{Group: stuff.gvk.Group, Version: stuff.gvk.Version, Kind: stuff.gvk.Kind},
obj: stuff.obj,
})
}
apiGroupInfo.VersionedResourcesStorageMap[gv.Version] = storage
if err := genericServer.InstallAPIGroup(&apiGroupInfo); err != nil {
log.Fatal(err)
return "", err
}
}
}
spec, err := builder.BuildOpenAPISpec(genericServer.Handler.GoRestfulContainer.RegisteredWebServices(), serverConfig.OpenAPIConfig)
if err != nil {
log.Fatal(err)
return "", err
}
data, err := json.MarshalIndent(spec, "", " ")
if err != nil {
log.Fatal(err)
return "", err
}
return string(data), nil
}

112
tools/lib/storage.go Normal file
View File

@@ -0,0 +1,112 @@
package lib
import (
"context"
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/apiserver/pkg/registry/rest"
)
type ResourceInfo struct {
gvk schema.GroupVersionKind
obj runtime.Object
list runtime.Object
}
type StatusResourceInfo struct {
gvk schema.GroupVersionKind
obj runtime.Object
}
type StandardStorage struct {
cfg ResourceInfo
}
type StatusStandardStorage struct {
cfg StatusResourceInfo
}
var _ rest.GroupVersionKindProvider = &StandardStorage{}
var _ rest.StandardStorage = &StandardStorage{}
var _ rest.GroupVersionKindProvider = &StatusStandardStorage{}
var _ rest.Patcher = &StatusStandardStorage{}
func NewREST(cfg ResourceInfo) *StandardStorage {
return &StandardStorage{cfg}
}
func NewStatusREST(cfg StatusResourceInfo) *StatusStandardStorage {
return &StatusStandardStorage{cfg}
}
func (r *StandardStorage) GroupVersionKind(containingGV schema.GroupVersion) schema.GroupVersionKind {
return r.cfg.gvk
}
// Getter
func (r *StandardStorage) New() runtime.Object {
return r.cfg.obj
}
func (r *StandardStorage) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
return r.New(), nil
}
func (r *StandardStorage) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
return r.New(), nil
}
// Lister
func (r *StandardStorage) NewList() runtime.Object {
return r.cfg.list
}
func (r *StandardStorage) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) {
return r.NewList(), nil
}
// CreaterUpdater
func (r *StandardStorage) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
return r.New(), true, nil
}
// GracefulDeleter
func (r *StandardStorage) Delete(ctx context.Context, name string, options *metav1.DeleteOptions) (runtime.Object, bool, error) {
return r.New(), true, nil
}
// CollectionDeleter
func (r *StandardStorage) DeleteCollection(ctx context.Context, options *metav1.DeleteOptions, listOptions *metainternalversion.ListOptions) (runtime.Object, error) {
return r.NewList(), nil
}
// Watcher
func (r *StandardStorage) Watch(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) {
return nil, nil
}
func (r *StandardStorage) NamespaceScoped() bool {
return false
}
func (r *StatusStandardStorage) GroupVersionKind(containingGV schema.GroupVersion) schema.GroupVersionKind {
return r.cfg.gvk
}
// Patcher
func (r *StatusStandardStorage) New() runtime.Object {
return r.cfg.obj
}
// Patcher
func (r *StatusStandardStorage) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
return r.New(), true, nil
}
// Patcher
func (r *StatusStandardStorage) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
return r.New(), nil
}

7
tools/tools.go Normal file
View File

@@ -0,0 +1,7 @@
// +build tools
package tools
import (
_ "k8s.io/kube-openapi/cmd/openapi-gen/"
)