mirror of https://github.com/kubernetes/kops.git
Fix api-gen-docs
This commit is contained in:
parent
729d93541c
commit
a291b6161e
|
@ -621,6 +621,8 @@
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/kubernetes-incubator/apiserver-builder"
|
name = "github.com/kubernetes-incubator/apiserver-builder"
|
||||||
packages = [
|
packages = [
|
||||||
|
"cmd/apiregister-gen",
|
||||||
|
"cmd/apiregister-gen/generators",
|
||||||
"cmd/apiserver-boot",
|
"cmd/apiserver-boot",
|
||||||
"cmd/apiserver-boot/boot/build",
|
"cmd/apiserver-boot/boot/build",
|
||||||
"cmd/apiserver-boot/boot/create",
|
"cmd/apiserver-boot/boot/create",
|
||||||
|
@ -1786,6 +1788,6 @@
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "b2c3876a387bc89849c0113df69d24ad9987cbccea885c60ed499162851e4039"
|
inputs-digest = "c083db22a03ca0fe3ccc11361c91a444e674aa1ec6fb0aba6447b4b4982c0355"
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
|
|
@ -12,6 +12,7 @@ required = [
|
||||||
# Needed for docs generation
|
# Needed for docs generation
|
||||||
"k8s.io/code-generator/cmd/openapi-gen",
|
"k8s.io/code-generator/cmd/openapi-gen",
|
||||||
"github.com/kubernetes-incubator/apiserver-builder/cmd/apiserver-boot",
|
"github.com/kubernetes-incubator/apiserver-builder/cmd/apiserver-boot",
|
||||||
|
"github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen",
|
||||||
"github.com/kubernetes-incubator/reference-docs/gen-apidocs",
|
"github.com/kubernetes-incubator/reference-docs/gen-apidocs",
|
||||||
|
|
||||||
# Needed for bazel generation / verification
|
# Needed for bazel generation / verification
|
||||||
|
|
|
@ -33,11 +33,13 @@ cp ${WORK_DIR}/go/bin/openapi-gen ${GOPATH}/bin/
|
||||||
|
|
||||||
# Install the apiserver-builder commands
|
# Install the apiserver-builder commands
|
||||||
GOPATH=${WORK_DIR}/go/ go install github.com/kubernetes-incubator/apiserver-builder/cmd/...
|
GOPATH=${WORK_DIR}/go/ go install github.com/kubernetes-incubator/apiserver-builder/cmd/...
|
||||||
cp ${WORK_DIR}/go/bin/openapi-gen ${GOPATH}/bin/
|
cp ${WORK_DIR}/go/bin/apiserver-boot ${GOPATH}/bin/
|
||||||
|
cp ${WORK_DIR}/go/bin/apiregister-gen ${GOPATH}/bin/
|
||||||
|
|
||||||
# Install the reference docs commands (apiserver-builder commands invoke these)
|
# Install the reference docs commands (apiserver-builder commands invoke these)
|
||||||
GOPATH=${WORK_DIR}/go/ go install github.com/kubernetes-incubator/reference-docs/gen-apidocs/...
|
GOPATH=${WORK_DIR}/go/ go install github.com/kubernetes-incubator/reference-docs/gen-apidocs/...
|
||||||
cp ${WORK_DIR}/go/bin/openapi-gen ${GOPATH}/bin/
|
cp ${WORK_DIR}/go/bin/openapi-gen ${GOPATH}/bin/
|
||||||
|
cp ${WORK_DIR}/go/bin/gen-apidocs ${GOPATH}/bin/
|
||||||
|
|
||||||
# More code generators
|
# More code generators
|
||||||
GOPATH=${WORK_DIR}/go/ go install k8s.io/code-generator/cmd/lister-gen
|
GOPATH=${WORK_DIR}/go/ go install k8s.io/code-generator/cmd/lister-gen
|
||||||
|
@ -46,3 +48,15 @@ cp ${WORK_DIR}/go/bin/lister-gen ${GOPATH}/bin/
|
||||||
GOPATH=${WORK_DIR}/go/ go install k8s.io/code-generator/cmd/informer-gen
|
GOPATH=${WORK_DIR}/go/ go install k8s.io/code-generator/cmd/informer-gen
|
||||||
cp ${WORK_DIR}/go/bin/informer-gen ${GOPATH}/bin/
|
cp ${WORK_DIR}/go/bin/informer-gen ${GOPATH}/bin/
|
||||||
|
|
||||||
|
GOPATH=${WORK_DIR}/go/ go install k8s.io/code-generator/cmd/client-gen
|
||||||
|
cp ${WORK_DIR}/go/bin/client-gen ${GOPATH}/bin/
|
||||||
|
|
||||||
|
GOPATH=${WORK_DIR}/go/ go install k8s.io/code-generator/cmd/deepcopy-gen
|
||||||
|
cp ${WORK_DIR}/go/bin/deepcopy-gen ${GOPATH}/bin/
|
||||||
|
|
||||||
|
GOPATH=${WORK_DIR}/go/ go install k8s.io/code-generator/cmd/conversion-gen
|
||||||
|
cp ${WORK_DIR}/go/bin/conversion-gen ${GOPATH}/bin/
|
||||||
|
|
||||||
|
GOPATH=${WORK_DIR}/go/ go install k8s.io/code-generator/cmd/defaulter-gen
|
||||||
|
cp ${WORK_DIR}/go/bin/defaulter-gen ${GOPATH}/bin/
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
21
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/BUILD.bazel
generated
vendored
Normal file
21
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/BUILD.bazel
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = ["main.go"],
|
||||||
|
importmap = "vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen",
|
||||||
|
importpath = "github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen",
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
deps = [
|
||||||
|
"//vendor/github.com/golang/glog:go_default_library",
|
||||||
|
"//vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators:go_default_library",
|
||||||
|
"//vendor/k8s.io/apiserver/pkg/util/logs:go_default_library",
|
||||||
|
"//vendor/k8s.io/gengo/args:go_default_library",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
go_binary(
|
||||||
|
name = "apiregister-gen",
|
||||||
|
embed = [":go_default_library"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
28
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators/BUILD.bazel
generated
vendored
Normal file
28
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators/BUILD.bazel
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = [
|
||||||
|
"apis_generator.go",
|
||||||
|
"controller_generator.go",
|
||||||
|
"install_generator.go",
|
||||||
|
"package.go",
|
||||||
|
"parser.go",
|
||||||
|
"unversioned_generator.go",
|
||||||
|
"util.go",
|
||||||
|
"versioned_generator.go",
|
||||||
|
],
|
||||||
|
importmap = "vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators",
|
||||||
|
importpath = "github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = [
|
||||||
|
"//vendor/github.com/markbates/inflect:go_default_library",
|
||||||
|
"//vendor/github.com/pkg/errors:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||||
|
"//vendor/k8s.io/gengo/args:go_default_library",
|
||||||
|
"//vendor/k8s.io/gengo/generator:go_default_library",
|
||||||
|
"//vendor/k8s.io/gengo/namer:go_default_library",
|
||||||
|
"//vendor/k8s.io/gengo/types:go_default_library",
|
||||||
|
],
|
||||||
|
)
|
100
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators/apis_generator.go
generated
vendored
Normal file
100
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators/apis_generator.go
generated
vendored
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
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 generators
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"k8s.io/gengo/generator"
|
||||||
|
)
|
||||||
|
|
||||||
|
type apiGenerator struct {
|
||||||
|
generator.DefaultGen
|
||||||
|
apis *APIs
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ generator.Generator = &apiGenerator{}
|
||||||
|
|
||||||
|
func CreateApisGenerator(apis *APIs, filename string) generator.Generator {
|
||||||
|
return &apiGenerator{
|
||||||
|
generator.DefaultGen{OptionalName: filename},
|
||||||
|
apis,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *apiGenerator) Imports(c *generator.Context) []string {
|
||||||
|
imports := []string{
|
||||||
|
"github.com/kubernetes-incubator/apiserver-builder/pkg/builders",
|
||||||
|
}
|
||||||
|
for _, group := range d.apis.Groups {
|
||||||
|
imports = append(imports, group.PkgPath)
|
||||||
|
for _, version := range group.Versions {
|
||||||
|
imports = append(imports, fmt.Sprintf(
|
||||||
|
"%s%s \"%s\"", group.Group, version.Version, version.Pkg.Path))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return imports
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *apiGenerator) Finalize(context *generator.Context, w io.Writer) error {
|
||||||
|
temp := template.Must(template.New("apis-template").Parse(APIsTemplate))
|
||||||
|
err := temp.Execute(w, d.apis)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var APIsTemplate = `
|
||||||
|
// GetAllApiBuilders returns all known APIGroupBuilders
|
||||||
|
// so they can be registered with the apiserver
|
||||||
|
func GetAllApiBuilders() []*builders.APIGroupBuilder {
|
||||||
|
return []*builders.APIGroupBuilder{
|
||||||
|
{{ range $group := .Groups -}}
|
||||||
|
Get{{ $group.GroupTitle }}APIBuilder(),
|
||||||
|
{{ end -}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{{ range $group := .Groups -}}
|
||||||
|
var {{ $group.Group }}ApiGroup = builders.NewApiGroupBuilder(
|
||||||
|
"{{ $group.Group }}.{{ $group.Domain }}",
|
||||||
|
"{{ $group.PkgPath}}").
|
||||||
|
WithUnVersionedApi({{ $group.Group }}.ApiVersion).
|
||||||
|
WithVersionedApis(
|
||||||
|
{{ range $version := $group.Versions -}}
|
||||||
|
{{ $group.Group }}{{ $version.Version }}.ApiVersion,
|
||||||
|
{{ end -}}
|
||||||
|
).
|
||||||
|
WithRootScopedKinds(
|
||||||
|
{{ range $version := $group.Versions -}}
|
||||||
|
{{ range $res := $version.Resources -}}
|
||||||
|
{{ if $res.NonNamespaced -}}
|
||||||
|
"{{ $res.Kind }}",
|
||||||
|
{{ end -}}
|
||||||
|
{{ end -}}
|
||||||
|
{{ end -}}
|
||||||
|
)
|
||||||
|
|
||||||
|
func Get{{ $group.GroupTitle }}APIBuilder() *builders.APIGroupBuilder {
|
||||||
|
return {{ $group.Group }}ApiGroup
|
||||||
|
}
|
||||||
|
{{ end -}}
|
||||||
|
`
|
357
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators/controller_generator.go
generated
vendored
Normal file
357
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators/controller_generator.go
generated
vendored
Normal file
|
@ -0,0 +1,357 @@
|
||||||
|
/*
|
||||||
|
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 generators
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/markbates/inflect"
|
||||||
|
"k8s.io/gengo/generator"
|
||||||
|
)
|
||||||
|
|
||||||
|
type controllerGenerator struct {
|
||||||
|
generator.DefaultGen
|
||||||
|
controller Controller
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ generator.Generator = &controllerGenerator{}
|
||||||
|
|
||||||
|
func CreateControllerGenerator(controller Controller, filename string) generator.Generator {
|
||||||
|
return &controllerGenerator{
|
||||||
|
generator.DefaultGen{OptionalName: filename},
|
||||||
|
controller,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *controllerGenerator) Imports(c *generator.Context) []string {
|
||||||
|
im := []string{
|
||||||
|
"github.com/golang/glog",
|
||||||
|
"github.com/kubernetes-incubator/apiserver-builder/pkg/controller",
|
||||||
|
"k8s.io/apimachinery/pkg/api/errors",
|
||||||
|
"k8s.io/client-go/rest",
|
||||||
|
"k8s.io/client-go/tools/cache",
|
||||||
|
"k8s.io/client-go/util/workqueue",
|
||||||
|
d.controller.Repo + "/pkg/controller/sharedinformers",
|
||||||
|
}
|
||||||
|
|
||||||
|
return im
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *controllerGenerator) Finalize(context *generator.Context, w io.Writer) error {
|
||||||
|
temp := template.Must(template.New("controller-template").Funcs(
|
||||||
|
template.FuncMap{
|
||||||
|
"title": strings.Title,
|
||||||
|
"plural": inflect.NewDefaultRuleset().Pluralize,
|
||||||
|
},
|
||||||
|
).Parse(ControllerAPITemplate))
|
||||||
|
return temp.Execute(w, d.controller)
|
||||||
|
}
|
||||||
|
|
||||||
|
var ControllerAPITemplate = `
|
||||||
|
// {{.Target.Kind}}Controller implements the controller.{{.Target.Kind}}Controller interface
|
||||||
|
type {{.Target.Kind}}Controller struct {
|
||||||
|
queue *controller.QueueWorker
|
||||||
|
|
||||||
|
// Handles messages
|
||||||
|
controller *{{.Target.Kind}}ControllerImpl
|
||||||
|
|
||||||
|
Name string
|
||||||
|
|
||||||
|
BeforeReconcile func(key string)
|
||||||
|
AfterReconcile func(key string, err error)
|
||||||
|
|
||||||
|
Informers *sharedinformers.SharedInformers
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewController returns a new {{.Target.Kind}}Controller for responding to {{.Target.Kind}} events
|
||||||
|
func New{{.Target.Kind}}Controller(config *rest.Config, si *sharedinformers.SharedInformers) *{{.Target.Kind}}Controller {
|
||||||
|
q := workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "{{.Target.Kind}}")
|
||||||
|
|
||||||
|
queue := &controller.QueueWorker{q, 10, "{{.Target.Kind}}", nil}
|
||||||
|
c := &{{.Target.Kind}}Controller{queue, nil, "{{.Target.Kind}}", nil, nil, si}
|
||||||
|
|
||||||
|
// For non-generated code to add events
|
||||||
|
uc := &{{.Target.Kind}}ControllerImpl{}
|
||||||
|
var ci sharedinformers.Controller = uc
|
||||||
|
|
||||||
|
// Call the Init method that is implemented.
|
||||||
|
// Support multiple Init methods for backwards compatibility
|
||||||
|
if i, ok := ci.(sharedinformers.LegacyControllerInit); ok {
|
||||||
|
i.Init(config, si, c.LookupAndReconcile)
|
||||||
|
} else if i, ok := ci.(sharedinformers.ControllerInit); ok {
|
||||||
|
i.Init(&sharedinformers.ControllerInitArgumentsImpl{si, config, c.LookupAndReconcile})
|
||||||
|
}
|
||||||
|
|
||||||
|
c.controller = uc
|
||||||
|
|
||||||
|
queue.Reconcile = c.reconcile
|
||||||
|
if c.Informers.WorkerQueues == nil {
|
||||||
|
c.Informers.WorkerQueues = map[string]*controller.QueueWorker{}
|
||||||
|
}
|
||||||
|
c.Informers.WorkerQueues["{{.Target.Kind}}"] = queue
|
||||||
|
si.Factory.{{title .Target.Group}}().{{title .Target.Version}}().{{plural .Target.Kind }}().Informer().
|
||||||
|
AddEventHandler(&controller.QueueingEventHandler{q, nil, false})
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *{{.Target.Kind}}Controller) GetName() string {
|
||||||
|
return c.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *{{.Target.Kind}}Controller) LookupAndReconcile(key string) (err error) {
|
||||||
|
return c.reconcile(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *{{.Target.Kind}}Controller) reconcile(key string) (err error) {
|
||||||
|
var namespace, name string
|
||||||
|
|
||||||
|
if c.BeforeReconcile != nil {
|
||||||
|
c.BeforeReconcile(key)
|
||||||
|
}
|
||||||
|
if c.AfterReconcile != nil {
|
||||||
|
// Wrap in a function so err is evaluated after it is set
|
||||||
|
defer func() { c.AfterReconcile(key, err) }()
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace, name, err = cache.SplitMetaNamespaceKey(key)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := c.controller.Get(namespace, name)
|
||||||
|
if errors.IsNotFound(err) {
|
||||||
|
glog.Infof("Not doing work for {{.Target.Kind}} %v because it has been deleted", key)
|
||||||
|
// Set error so it is picked up by AfterReconcile and the return function
|
||||||
|
err = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("Unable to retrieve {{.Target.Kind}} %v from store: %v", key, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set error so it is picked up by AfterReconcile and the return function
|
||||||
|
err = c.controller.Reconcile(u)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *{{.Target.Kind}}Controller) Run(stopCh <-chan struct{}) {
|
||||||
|
for _, q := range c.Informers.WorkerQueues {
|
||||||
|
q.Run(stopCh)
|
||||||
|
}
|
||||||
|
controller.GetDefaults(c.controller).Run(stopCh)
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
type allControllerGenerator struct {
|
||||||
|
generator.DefaultGen
|
||||||
|
Controllers []Controller
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ generator.Generator = &allControllerGenerator{}
|
||||||
|
|
||||||
|
func CreateAllControllerGenerator(controllers []Controller, filename string) generator.Generator {
|
||||||
|
return &allControllerGenerator{
|
||||||
|
generator.DefaultGen{OptionalName: filename},
|
||||||
|
controllers,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *allControllerGenerator) Imports(c *generator.Context) []string {
|
||||||
|
if len(d.Controllers) == 0 {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
repo := d.Controllers[0].Repo
|
||||||
|
im := []string{
|
||||||
|
"k8s.io/client-go/rest",
|
||||||
|
"github.com/kubernetes-incubator/apiserver-builder/pkg/controller",
|
||||||
|
repo + "/pkg/controller/sharedinformers",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import package for each controller
|
||||||
|
repos := map[string]string{}
|
||||||
|
for _, c := range d.Controllers {
|
||||||
|
repos[c.Pkg.Path] = ""
|
||||||
|
}
|
||||||
|
for k, _ := range repos {
|
||||||
|
im = append(im, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
return im
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *allControllerGenerator) Finalize(context *generator.Context, w io.Writer) error {
|
||||||
|
temp := template.Must(template.New("all-controller-template").Funcs(
|
||||||
|
template.FuncMap{
|
||||||
|
"title": strings.Title,
|
||||||
|
"plural": inflect.NewDefaultRuleset().Pluralize,
|
||||||
|
},
|
||||||
|
).Parse(AllControllerAPITemplate))
|
||||||
|
return temp.Execute(w, d)
|
||||||
|
}
|
||||||
|
|
||||||
|
var AllControllerAPITemplate = `
|
||||||
|
|
||||||
|
func GetAllControllers(config *rest.Config) ([]controller.Controller, chan struct{}) {
|
||||||
|
shutdown := make(chan struct{})
|
||||||
|
si := sharedinformers.NewSharedInformers(config, shutdown)
|
||||||
|
return []controller.Controller{
|
||||||
|
{{ range $c := .Controllers -}}
|
||||||
|
{{ $c.Pkg.Name }}.New{{ $c.Target.Kind }}Controller(config, si),
|
||||||
|
{{ end -}}
|
||||||
|
}, shutdown
|
||||||
|
}
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
type informersGenerator struct {
|
||||||
|
generator.DefaultGen
|
||||||
|
Controllers []Controller
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ generator.Generator = &informersGenerator{}
|
||||||
|
|
||||||
|
func CreateInformersGenerator(controllers []Controller, filename string) generator.Generator {
|
||||||
|
return &informersGenerator{
|
||||||
|
generator.DefaultGen{OptionalName: filename},
|
||||||
|
controllers,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *informersGenerator) Imports(c *generator.Context) []string {
|
||||||
|
if len(d.Controllers) == 0 {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
repo := d.Controllers[0].Repo
|
||||||
|
return []string{
|
||||||
|
"time",
|
||||||
|
"github.com/kubernetes-incubator/apiserver-builder/pkg/controller",
|
||||||
|
"k8s.io/client-go/rest",
|
||||||
|
repo + "/pkg/client/clientset_generated/clientset",
|
||||||
|
repo + "/pkg/client/informers_generated/externalversions",
|
||||||
|
"k8s.io/client-go/tools/cache",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *informersGenerator) Finalize(context *generator.Context, w io.Writer) error {
|
||||||
|
temp := template.Must(template.New("informersGenerator-template").Funcs(
|
||||||
|
template.FuncMap{
|
||||||
|
"title": strings.Title,
|
||||||
|
"plural": inflect.NewDefaultRuleset().Pluralize,
|
||||||
|
},
|
||||||
|
).Parse(InformersTemplate))
|
||||||
|
return temp.Execute(w, d.Controllers)
|
||||||
|
}
|
||||||
|
|
||||||
|
var InformersTemplate = `
|
||||||
|
// SharedInformers wraps all informers used by controllers so that
|
||||||
|
// they are shared across controller implementations
|
||||||
|
type SharedInformers struct {
|
||||||
|
controller.SharedInformersDefaults
|
||||||
|
Factory externalversions.SharedInformerFactory
|
||||||
|
}
|
||||||
|
|
||||||
|
// newSharedInformers returns a set of started informers
|
||||||
|
func NewSharedInformers(config *rest.Config, shutdown <-chan struct{}) *SharedInformers {
|
||||||
|
si := &SharedInformers{
|
||||||
|
controller.SharedInformersDefaults{},
|
||||||
|
externalversions.NewSharedInformerFactory(clientset.NewForConfigOrDie(config), 10*time.Minute),
|
||||||
|
}
|
||||||
|
if si.SetupKubernetesTypes() {
|
||||||
|
si.InitKubernetesInformers(config)
|
||||||
|
}
|
||||||
|
si.Init()
|
||||||
|
si.startInformers(shutdown)
|
||||||
|
si.StartAdditionalInformers(shutdown)
|
||||||
|
return si
|
||||||
|
}
|
||||||
|
|
||||||
|
// startInformers starts all of the informers
|
||||||
|
func (si *SharedInformers) startInformers(shutdown <-chan struct{}) {
|
||||||
|
{{ range $c := . -}}
|
||||||
|
go si.Factory.{{title $c.Target.Group}}().{{title $c.Target.Version}}().{{plural $c.Target.Kind}}().Informer().Run(shutdown)
|
||||||
|
{{ end -}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ControllerInitArguments are arguments provided to the Init function for a new controller.
|
||||||
|
type ControllerInitArguments interface {
|
||||||
|
// GetSharedInformers returns the SharedInformers that can be used to access
|
||||||
|
// informers and listers for watching and indexing Kubernetes Resources
|
||||||
|
GetSharedInformers() *SharedInformers
|
||||||
|
|
||||||
|
// GetRestConfig returns the Config to create new client-go clients
|
||||||
|
GetRestConfig() *rest.Config
|
||||||
|
|
||||||
|
// Watch uses resourceInformer to watch a resource. When create, update, or deletes
|
||||||
|
// to the resource type are encountered, watch uses watchResourceToReconcileResourceKey
|
||||||
|
// to lookup the key for the resource reconciled by the controller (maybe a different type
|
||||||
|
// than the watched resource), and enqueue it to be reconciled.
|
||||||
|
// watchName: name of the informer. may appear in logs
|
||||||
|
// resourceInformer: gotten from the SharedInformer. controls which resource type is watched
|
||||||
|
// getReconcileKey: takes an instance of the watched resource and returns
|
||||||
|
// a key for the reconciled resource type to enqueue.
|
||||||
|
Watch(watchName string, resourceInformer cache.SharedIndexInformer,
|
||||||
|
getReconcileKey func(interface{}) (string, error))
|
||||||
|
}
|
||||||
|
|
||||||
|
type ControllerInitArgumentsImpl struct {
|
||||||
|
Si *SharedInformers
|
||||||
|
Rc *rest.Config
|
||||||
|
Rk func(key string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c ControllerInitArgumentsImpl) GetSharedInformers() *SharedInformers {
|
||||||
|
return c.Si
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c ControllerInitArgumentsImpl) GetRestConfig() *rest.Config {
|
||||||
|
return c.Rc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Watch uses resourceInformer to watch a resource. When create, update, or deletes
|
||||||
|
// to the resource type are encountered, watch uses watchResourceToReconcileResourceKey
|
||||||
|
// to lookup the key for the resource reconciled by the controller (maybe a different type
|
||||||
|
// than the watched resource), and enqueue it to be reconciled.
|
||||||
|
// watchName: name of the informer. may appear in logs
|
||||||
|
// resourceInformer: gotten from the SharedInformer. controls which resource type is watched
|
||||||
|
// getReconcileKey: takes an instance of the watched resource and returns
|
||||||
|
// a key for the reconciled resource type to enqueue.
|
||||||
|
func (c ControllerInitArgumentsImpl) Watch(
|
||||||
|
watchName string, resourceInformer cache.SharedIndexInformer,
|
||||||
|
getReconcileKey func(interface{}) (string, error)) {
|
||||||
|
c.Si.Watch(watchName, resourceInformer, getReconcileKey, c.Rk)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Controller interface {}
|
||||||
|
|
||||||
|
// LegacyControllerInit old controllers may implement this, and we keep
|
||||||
|
// it for backwards compatibility.
|
||||||
|
type LegacyControllerInit interface {
|
||||||
|
Init(config *rest.Config, si *SharedInformers, r func(key string) error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ControllerInit new controllers should implement this. It is more flexible in
|
||||||
|
// allowing additional options to be passed in
|
||||||
|
type ControllerInit interface {
|
||||||
|
Init(args ControllerInitArguments)
|
||||||
|
}
|
||||||
|
`
|
68
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators/install_generator.go
generated
vendored
Normal file
68
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators/install_generator.go
generated
vendored
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
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 generators
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"k8s.io/gengo/generator"
|
||||||
|
)
|
||||||
|
|
||||||
|
type installGenerator struct {
|
||||||
|
generator.DefaultGen
|
||||||
|
apigroup *APIGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ generator.Generator = &unversionedGenerator{}
|
||||||
|
|
||||||
|
func CreateInstallGenerator(apigroup *APIGroup, filename string) generator.Generator {
|
||||||
|
return &installGenerator{
|
||||||
|
generator.DefaultGen{OptionalName: filename},
|
||||||
|
apigroup,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *installGenerator) Imports(c *generator.Context) []string {
|
||||||
|
return []string{
|
||||||
|
"k8s.io/apimachinery/pkg/apimachinery/announced",
|
||||||
|
"k8s.io/apimachinery/pkg/apimachinery/registered",
|
||||||
|
"k8s.io/apimachinery/pkg/runtime",
|
||||||
|
path.Dir(d.apigroup.Pkg.Path),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *installGenerator) Finalize(context *generator.Context, w io.Writer) error {
|
||||||
|
temp := template.Must(template.New("install-template").Parse(InstallAPITemplate))
|
||||||
|
err := temp.Execute(w, d.apigroup)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var InstallAPITemplate = `
|
||||||
|
func Install(
|
||||||
|
groupFactoryRegistry announced.APIGroupFactoryRegistry,
|
||||||
|
registry *registered.APIRegistrationManager,
|
||||||
|
scheme *runtime.Scheme) {
|
||||||
|
|
||||||
|
apis.Get{{ .GroupTitle }}APIBuilder().Install(groupFactoryRegistry, registry, scheme)
|
||||||
|
}
|
||||||
|
`
|
178
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators/package.go
generated
vendored
Normal file
178
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators/package.go
generated
vendored
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
/*
|
||||||
|
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 generators
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
"k8s.io/gengo/args"
|
||||||
|
"k8s.io/gengo/generator"
|
||||||
|
"k8s.io/gengo/namer"
|
||||||
|
"k8s.io/gengo/types"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CustomArgs is used tby the go2idl framework to pass args specific to this
|
||||||
|
// generator.
|
||||||
|
type CustomArgs struct{}
|
||||||
|
|
||||||
|
type Gen struct {
|
||||||
|
p []generator.Package
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Gen) Execute(arguments *args.GeneratorArgs) error {
|
||||||
|
return arguments.Execute(
|
||||||
|
g.NameSystems(),
|
||||||
|
g.DefaultNameSystem(),
|
||||||
|
g.Packages)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultNameSystem returns the default name system for ordering the types to be
|
||||||
|
// processed by the generators in this package.
|
||||||
|
func (g *Gen) DefaultNameSystem() string {
|
||||||
|
return "public"
|
||||||
|
}
|
||||||
|
|
||||||
|
// NameSystems returns the name system used by the generators in this package.
|
||||||
|
func (g *Gen) NameSystems() namer.NameSystems {
|
||||||
|
return namer.NameSystems{
|
||||||
|
"public": namer.NewPublicNamer(1),
|
||||||
|
"raw": namer.NewRawNamer("", nil),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Gen) ParsePackages(context *generator.Context, arguments *args.GeneratorArgs) (sets.String, sets.String, string, string) {
|
||||||
|
versionedPkgs := sets.NewString()
|
||||||
|
unversionedPkgs := sets.NewString()
|
||||||
|
mainPkg := ""
|
||||||
|
apisPkg := ""
|
||||||
|
for _, o := range context.Order {
|
||||||
|
if IsAPIResource(o) {
|
||||||
|
versioned := o.Name.Package
|
||||||
|
versionedPkgs.Insert(versioned)
|
||||||
|
unversioned := filepath.Dir(versioned)
|
||||||
|
unversionedPkgs.Insert(unversioned)
|
||||||
|
|
||||||
|
if apis := filepath.Dir(unversioned); apis != apisPkg && len(apisPkg) > 0 {
|
||||||
|
panic(errors.Errorf(
|
||||||
|
"Found multiple apis directory paths: %v and %v", apisPkg, apis))
|
||||||
|
} else {
|
||||||
|
apisPkg = apis
|
||||||
|
mainPkg = filepath.Dir(apisPkg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return versionedPkgs, unversionedPkgs, apisPkg, mainPkg
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Gen) Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
|
||||||
|
g.p = generator.Packages{}
|
||||||
|
|
||||||
|
b := NewAPIsBuilder(context, arguments)
|
||||||
|
for _, apigroup := range b.APIs.Groups {
|
||||||
|
for _, apiversion := range apigroup.Versions {
|
||||||
|
factory := &packageFactory{apiversion.Pkg.Path, arguments}
|
||||||
|
// Add generators for versioned types
|
||||||
|
gen := CreateVersionedGenerator(apiversion, apigroup, arguments.OutputFileBaseName)
|
||||||
|
g.p = append(g.p, factory.createPackage(gen))
|
||||||
|
}
|
||||||
|
|
||||||
|
factory := &packageFactory{apigroup.Pkg.Path, arguments}
|
||||||
|
gen := CreateUnversionedGenerator(apigroup, arguments.OutputFileBaseName)
|
||||||
|
g.p = append(g.p, factory.createPackage(gen))
|
||||||
|
|
||||||
|
factory = &packageFactory{path.Join(apigroup.Pkg.Path, "install"), arguments}
|
||||||
|
gen = CreateInstallGenerator(apigroup, arguments.OutputFileBaseName)
|
||||||
|
g.p = append(g.p, factory.createPackage(gen))
|
||||||
|
}
|
||||||
|
|
||||||
|
factory := &packageFactory{b.APIs.Pkg.Path, arguments}
|
||||||
|
gen := CreateApisGenerator(b.APIs, arguments.OutputFileBaseName)
|
||||||
|
g.p = append(g.p, factory.createPackage(gen))
|
||||||
|
|
||||||
|
// Add generators for Controllers.
|
||||||
|
repo := ""
|
||||||
|
for _, c := range b.Controllers {
|
||||||
|
repo = c.Repo
|
||||||
|
factory = &packageFactory{c.Pkg.Path, arguments}
|
||||||
|
cgen := CreateControllerGenerator(c, arguments.OutputFileBaseName)
|
||||||
|
g.p = append(g.p, factory.createPackage(cgen))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(b.Controllers) > 0 {
|
||||||
|
factory = &packageFactory{context.Universe[repo+"/pkg/controller"].Path, arguments}
|
||||||
|
cgen := CreateAllControllerGenerator(b.Controllers, arguments.OutputFileBaseName)
|
||||||
|
g.p = append(g.p, factory.createPackage(cgen))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(b.Controllers) > 0 {
|
||||||
|
factory = &packageFactory{context.Universe[repo+"/pkg/controller/sharedinformers"].Path, arguments}
|
||||||
|
cgen := CreateInformersGenerator(b.Controllers, arguments.OutputFileBaseName)
|
||||||
|
g.p = append(g.p, factory.createPackage(cgen))
|
||||||
|
}
|
||||||
|
return g.p
|
||||||
|
}
|
||||||
|
|
||||||
|
type packageFactory struct {
|
||||||
|
path string
|
||||||
|
arguments *args.GeneratorArgs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a package with a generator
|
||||||
|
func (f *packageFactory) createPackage(gen generator.Generator) generator.Package {
|
||||||
|
path := f.path
|
||||||
|
name := strings.Split(filepath.Base(f.path), ".")[0]
|
||||||
|
return &generator.DefaultPackage{
|
||||||
|
PackageName: name,
|
||||||
|
PackagePath: path,
|
||||||
|
HeaderText: f.getHeader(),
|
||||||
|
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
||||||
|
return []generator.Generator{gen}
|
||||||
|
},
|
||||||
|
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||||
|
return t.Name.Package == f.path
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the header for generated files
|
||||||
|
func (f *packageFactory) getHeader() []byte {
|
||||||
|
header := []byte(`/*
|
||||||
|
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 apiregister-gen. Do not edit it manually!
|
||||||
|
|
||||||
|
`)
|
||||||
|
return header
|
||||||
|
}
|
761
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators/parser.go
generated
vendored
Normal file
761
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators/parser.go
generated
vendored
Normal file
|
@ -0,0 +1,761 @@
|
||||||
|
/*
|
||||||
|
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 generators
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
"k8s.io/gengo/args"
|
||||||
|
"k8s.io/gengo/generator"
|
||||||
|
"k8s.io/gengo/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type APIs struct {
|
||||||
|
// Domain is the domain portion of the group - e.g. k8s.io
|
||||||
|
Domain string
|
||||||
|
// Package is the name of the go package the api group is under - e.g. github.com/pwittrock/apiserver-helloworld/apis
|
||||||
|
Package string
|
||||||
|
Pkg *types.Package
|
||||||
|
// Groups is a list of API groups
|
||||||
|
Groups map[string]*APIGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
type Controller struct {
|
||||||
|
Target schema.GroupVersionKind
|
||||||
|
Resource string
|
||||||
|
Pkg *types.Package
|
||||||
|
Repo string
|
||||||
|
}
|
||||||
|
|
||||||
|
type APIGroup struct {
|
||||||
|
// Package is the name of the go package the api group is under - e.g. github.com/pwittrock/apiserver-helloworld/apis
|
||||||
|
Package string
|
||||||
|
// Domain is the domain portion of the group - e.g. k8s.io
|
||||||
|
Domain string
|
||||||
|
// Group is the short name of the group - e.g. mushroomkingdom
|
||||||
|
Group string
|
||||||
|
GroupTitle string
|
||||||
|
// Versions is the list of all versions for this group keyed by name
|
||||||
|
Versions map[string]*APIVersion
|
||||||
|
|
||||||
|
UnversionedResources map[string]*APIResource
|
||||||
|
|
||||||
|
// Structs is a list of unversioned definitions that must be generated
|
||||||
|
Structs []*Struct
|
||||||
|
Pkg *types.Package
|
||||||
|
PkgPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Struct struct {
|
||||||
|
// Name is the name of the type
|
||||||
|
Name string
|
||||||
|
// GenClient
|
||||||
|
GenClient bool
|
||||||
|
GenDeepCopy bool
|
||||||
|
NonNamespaced bool
|
||||||
|
|
||||||
|
GenUnversioned bool
|
||||||
|
// Fields is the list of fields appearing in the struct
|
||||||
|
Fields []*Field
|
||||||
|
}
|
||||||
|
|
||||||
|
type Field struct {
|
||||||
|
// Name is the name of the field
|
||||||
|
Name string
|
||||||
|
// For versioned Kubernetes types, this is the versioned package
|
||||||
|
VersionedPackage string
|
||||||
|
// For versioned Kubernetes types, this is the unversioned package
|
||||||
|
UnversionedImport string
|
||||||
|
UnversionedType string
|
||||||
|
}
|
||||||
|
|
||||||
|
type APIVersion struct {
|
||||||
|
// Domain is the group domain - e.g. k8s.io
|
||||||
|
Domain string
|
||||||
|
// Group is the group name - e.g. mushroomkingdom
|
||||||
|
Group string
|
||||||
|
// Version is the api version - e.g. v1beta1
|
||||||
|
Version string
|
||||||
|
// Resources is a list of resources appearing in the API version keyed by name
|
||||||
|
Resources map[string]*APIResource
|
||||||
|
// Pkg is the Package object from code-gen
|
||||||
|
Pkg *types.Package
|
||||||
|
}
|
||||||
|
|
||||||
|
type APIResource struct {
|
||||||
|
// Domain is the group domain - e.g. k8s.io
|
||||||
|
Domain string
|
||||||
|
// Group is the group name - e.g. mushroomkingdom
|
||||||
|
Group string
|
||||||
|
// Version is the api version - e.g. v1beta1
|
||||||
|
Version string
|
||||||
|
// Kind is the resource name - e.g. PeachesCastle
|
||||||
|
Kind string
|
||||||
|
// Resource is the resource name - e.g. peachescastles
|
||||||
|
Resource string
|
||||||
|
// REST is the rest.Storage implementation used to handle requests
|
||||||
|
// This field is optional. The standard REST implementation will be used
|
||||||
|
// by default.
|
||||||
|
REST string
|
||||||
|
// Subresources is a map of subresources keyed by name
|
||||||
|
Subresources map[string]*APISubresource
|
||||||
|
// Type is the Type object from code-gen
|
||||||
|
Type *types.Type
|
||||||
|
// Strategy is name of the struct to use for the strategy
|
||||||
|
Strategy string
|
||||||
|
// Strategy is name of the struct to use for the strategy
|
||||||
|
StatusStrategy string
|
||||||
|
// NonNamespaced indicates that the resource kind is non namespaced
|
||||||
|
NonNamespaced bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type APISubresource struct {
|
||||||
|
// Domain is the group domain - e.g. k8s.io
|
||||||
|
Domain string
|
||||||
|
// Group is the group name - e.g. mushroomkingdom
|
||||||
|
Group string
|
||||||
|
// Version is the api version - e.g. v1beta1
|
||||||
|
Version string
|
||||||
|
// Kind is the resource name - e.g. PeachesCastle
|
||||||
|
Kind string
|
||||||
|
// Resource is the resource name - e.g. peachescastles
|
||||||
|
Resource string
|
||||||
|
// Request is the subresource request type - e.g. ScaleCastle
|
||||||
|
Request string
|
||||||
|
// REST is the rest.Storage implementation used to handle requests
|
||||||
|
REST string
|
||||||
|
// Path is the subresource path - e.g. scale
|
||||||
|
Path string
|
||||||
|
|
||||||
|
// ImportPackage is the import statement that must appear for the Request
|
||||||
|
ImportPackage string
|
||||||
|
|
||||||
|
// RequestType is the type of the request
|
||||||
|
RequestType *types.Type
|
||||||
|
|
||||||
|
// RESTType is the type of the request handler
|
||||||
|
RESTType *types.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
type APIsBuilder struct {
|
||||||
|
context *generator.Context
|
||||||
|
arguments *args.GeneratorArgs
|
||||||
|
Domain string
|
||||||
|
VersionedPkgs sets.String
|
||||||
|
UnversionedPkgs sets.String
|
||||||
|
APIsPkg string
|
||||||
|
APIsPkgRaw *types.Package
|
||||||
|
GroupNames sets.String
|
||||||
|
|
||||||
|
APIs *APIs
|
||||||
|
Controllers []Controller
|
||||||
|
|
||||||
|
ByGroupKindVersion map[string]map[string]map[string]*APIResource
|
||||||
|
ByGroupVersionKind map[string]map[string]map[string]*APIResource
|
||||||
|
SubByGroupVersionKind map[string]map[string]map[string]*types.Type
|
||||||
|
Groups map[string]types.Package
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAPIsBuilder(context *generator.Context, arguments *args.GeneratorArgs) *APIsBuilder {
|
||||||
|
b := &APIsBuilder{
|
||||||
|
context: context,
|
||||||
|
arguments: arguments,
|
||||||
|
}
|
||||||
|
b.ParsePackages()
|
||||||
|
b.ParseDomain()
|
||||||
|
b.ParseGroupNames()
|
||||||
|
b.ParseIndex()
|
||||||
|
b.ParseControllers()
|
||||||
|
b.ParseAPIs()
|
||||||
|
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *APIsBuilder) ParseControllers() {
|
||||||
|
for _, c := range b.context.Order {
|
||||||
|
if IsController(c) {
|
||||||
|
tags := ParseControllerTag(b.GetControllerTag(c))
|
||||||
|
repo := strings.Split(c.Name.Package, "/pkg/controller")[0]
|
||||||
|
pkg := b.context.Universe[c.Name.Package]
|
||||||
|
b.Controllers = append(b.Controllers, Controller{
|
||||||
|
tags.gvk, tags.resource, pkg, repo})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *APIsBuilder) ParseAPIs() {
|
||||||
|
apis := &APIs{
|
||||||
|
Domain: b.Domain,
|
||||||
|
Package: b.APIsPkg,
|
||||||
|
Groups: map[string]*APIGroup{},
|
||||||
|
}
|
||||||
|
|
||||||
|
for group, versionMap := range b.ByGroupVersionKind {
|
||||||
|
apiGroup := &APIGroup{
|
||||||
|
Group: group,
|
||||||
|
GroupTitle: strings.Title(group),
|
||||||
|
Domain: b.Domain,
|
||||||
|
Versions: map[string]*APIVersion{},
|
||||||
|
UnversionedResources: map[string]*APIResource{},
|
||||||
|
}
|
||||||
|
|
||||||
|
for version, kindMap := range versionMap {
|
||||||
|
apiVersion := &APIVersion{
|
||||||
|
Domain: b.Domain,
|
||||||
|
Group: group,
|
||||||
|
Version: version,
|
||||||
|
Resources: map[string]*APIResource{},
|
||||||
|
}
|
||||||
|
for kind, resource := range kindMap {
|
||||||
|
apiResource := &APIResource{
|
||||||
|
Domain: resource.Domain,
|
||||||
|
Version: resource.Version,
|
||||||
|
Group: resource.Group,
|
||||||
|
Resource: resource.Resource,
|
||||||
|
Type: resource.Type,
|
||||||
|
REST: resource.REST,
|
||||||
|
Kind: resource.Kind,
|
||||||
|
Subresources: resource.Subresources,
|
||||||
|
StatusStrategy: resource.StatusStrategy,
|
||||||
|
Strategy: resource.Strategy,
|
||||||
|
NonNamespaced: resource.NonNamespaced,
|
||||||
|
}
|
||||||
|
apiVersion.Resources[kind] = apiResource
|
||||||
|
// Set the package for the api version
|
||||||
|
apiVersion.Pkg = b.context.Universe[resource.Type.Name.Package]
|
||||||
|
// Set the package for the api group
|
||||||
|
apiGroup.Pkg = b.context.Universe[filepath.Dir(resource.Type.Name.Package)]
|
||||||
|
apiGroup.PkgPath = apiGroup.Pkg.Path
|
||||||
|
|
||||||
|
apiGroup.UnversionedResources[kind] = apiResource
|
||||||
|
}
|
||||||
|
|
||||||
|
apiGroup.Versions[version] = apiVersion
|
||||||
|
}
|
||||||
|
b.ParseStructs(apiGroup)
|
||||||
|
apis.Groups[group] = apiGroup
|
||||||
|
}
|
||||||
|
apis.Pkg = b.context.Universe[b.APIsPkg]
|
||||||
|
b.APIs = apis
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseIndex indexes all types with the comment "// +resource=RESOURCE" by GroupVersionKind and
|
||||||
|
// GroupKindVersion
|
||||||
|
func (b *APIsBuilder) ParseIndex() {
|
||||||
|
b.ByGroupVersionKind = map[string]map[string]map[string]*APIResource{}
|
||||||
|
b.ByGroupKindVersion = map[string]map[string]map[string]*APIResource{}
|
||||||
|
|
||||||
|
b.SubByGroupVersionKind = map[string]map[string]map[string]*types.Type{}
|
||||||
|
for _, c := range b.context.Order {
|
||||||
|
if IsAPISubresource(c) {
|
||||||
|
group := GetGroup(c)
|
||||||
|
version := GetVersion(c, group)
|
||||||
|
kind := GetKind(c, group)
|
||||||
|
if _, f := b.SubByGroupVersionKind[group]; !f {
|
||||||
|
b.SubByGroupVersionKind[group] = map[string]map[string]*types.Type{}
|
||||||
|
}
|
||||||
|
if _, f := b.SubByGroupVersionKind[group][version]; !f {
|
||||||
|
b.SubByGroupVersionKind[group][version] = map[string]*types.Type{}
|
||||||
|
}
|
||||||
|
b.SubByGroupVersionKind[group][version][kind] = c
|
||||||
|
}
|
||||||
|
|
||||||
|
if !IsAPIResource(c) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
r := &APIResource{
|
||||||
|
Type: c,
|
||||||
|
NonNamespaced: IsNonNamespaced(c),
|
||||||
|
}
|
||||||
|
r.Group = GetGroup(c)
|
||||||
|
r.Version = GetVersion(c, r.Group)
|
||||||
|
r.Kind = GetKind(c, r.Group)
|
||||||
|
r.Domain = b.Domain
|
||||||
|
|
||||||
|
rt := ParseResourceTag(b.GetResourceTag(c))
|
||||||
|
|
||||||
|
r.Resource = rt.Resource
|
||||||
|
r.REST = rt.REST
|
||||||
|
|
||||||
|
r.Strategy = rt.Strategy
|
||||||
|
|
||||||
|
// If not defined, default the strategy to the {{.Kind}}Strategy for backwards compatibility
|
||||||
|
if len(r.Strategy) == 0 {
|
||||||
|
r.Strategy = fmt.Sprintf("%sStrategy", r.Kind)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the Status strategy to mirror the non-status strategy
|
||||||
|
r.StatusStrategy = strings.TrimSuffix(r.Strategy, "Strategy")
|
||||||
|
r.StatusStrategy = fmt.Sprintf("%sStatusStrategy", r.StatusStrategy)
|
||||||
|
|
||||||
|
if _, f := b.ByGroupKindVersion[r.Group]; !f {
|
||||||
|
b.ByGroupKindVersion[r.Group] = map[string]map[string]*APIResource{}
|
||||||
|
}
|
||||||
|
if _, f := b.ByGroupKindVersion[r.Group][r.Kind]; !f {
|
||||||
|
b.ByGroupKindVersion[r.Group][r.Kind] = map[string]*APIResource{}
|
||||||
|
}
|
||||||
|
if _, f := b.ByGroupVersionKind[r.Group]; !f {
|
||||||
|
b.ByGroupVersionKind[r.Group] = map[string]map[string]*APIResource{}
|
||||||
|
}
|
||||||
|
if _, f := b.ByGroupVersionKind[r.Group][r.Version]; !f {
|
||||||
|
b.ByGroupVersionKind[r.Group][r.Version] = map[string]*APIResource{}
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ByGroupKindVersion[r.Group][r.Kind][r.Version] = r
|
||||||
|
b.ByGroupVersionKind[r.Group][r.Version][r.Kind] = r
|
||||||
|
|
||||||
|
// Do subresources
|
||||||
|
if !HasSubresource(c) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
r.Type = c
|
||||||
|
r.Subresources = b.GetSubresources(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *APIsBuilder) GetSubresources(c *APIResource) map[string]*APISubresource {
|
||||||
|
r := map[string]*APISubresource{}
|
||||||
|
subresources := b.GetSubresourceTags(c.Type)
|
||||||
|
|
||||||
|
if len(subresources) == 0 {
|
||||||
|
// Not a subresource
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
for _, subresource := range subresources {
|
||||||
|
// Parse the values for each subresource
|
||||||
|
tags := ParseSubresourceTag(c, subresource)
|
||||||
|
sr := &APISubresource{
|
||||||
|
Kind: tags.Kind,
|
||||||
|
Request: tags.RequestKind,
|
||||||
|
Path: tags.Path,
|
||||||
|
REST: tags.REST,
|
||||||
|
Domain: b.Domain,
|
||||||
|
Version: c.Version,
|
||||||
|
Resource: c.Resource,
|
||||||
|
Group: c.Group,
|
||||||
|
}
|
||||||
|
if !b.IsInPackage(tags) {
|
||||||
|
// Out of package Request types require an import and are prefixed with the
|
||||||
|
// package name - e.g. v1.Scale
|
||||||
|
sr.Request, sr.ImportPackage = b.GetNameAndImport(tags)
|
||||||
|
}
|
||||||
|
if v, found := r[sr.Path]; found {
|
||||||
|
log.Fatalf("Multiple subresources registered for path %s: %v %v",
|
||||||
|
sr.Path, v, subresource)
|
||||||
|
}
|
||||||
|
r[sr.Path] = sr
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the subresource Request type is in the same package as the resource type
|
||||||
|
func (b *APIsBuilder) IsInPackage(tags SubresourceTags) bool {
|
||||||
|
return !strings.Contains(tags.RequestKind, ".")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNameAndImport converts
|
||||||
|
func (b *APIsBuilder) GetNameAndImport(tags SubresourceTags) (string, string) {
|
||||||
|
last := strings.LastIndex(tags.RequestKind, ".")
|
||||||
|
importPackage := tags.RequestKind[:last]
|
||||||
|
|
||||||
|
// Set the request kind to the struct name
|
||||||
|
tags.RequestKind = tags.RequestKind[last+1:]
|
||||||
|
// Find the package
|
||||||
|
pkg := filepath.Base(importPackage)
|
||||||
|
// Prefix the struct name with the package it is in
|
||||||
|
return strings.Join([]string{pkg, tags.RequestKind}, "."), importPackage
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResourceTags contains the tags present in a "+resource=" comment
|
||||||
|
type ResourceTags struct {
|
||||||
|
Resource string
|
||||||
|
REST string
|
||||||
|
Strategy string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseResourceTag parses the tags in a "+resource=" comment into a ResourceTags struct
|
||||||
|
func ParseResourceTag(tag string) ResourceTags {
|
||||||
|
result := ResourceTags{}
|
||||||
|
for _, elem := range strings.Split(tag, ",") {
|
||||||
|
kv := strings.Split(elem, "=")
|
||||||
|
if len(kv) != 2 {
|
||||||
|
log.Fatalf("// +resource: tags must be key value pairs. Expected "+
|
||||||
|
"keys [path=<subresourcepath>] "+
|
||||||
|
"Got string: [%s]", tag)
|
||||||
|
}
|
||||||
|
value := kv[1]
|
||||||
|
switch kv[0] {
|
||||||
|
case "rest":
|
||||||
|
result.REST = value
|
||||||
|
case "path":
|
||||||
|
result.Resource = value
|
||||||
|
case "strategy":
|
||||||
|
result.Strategy = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResourceTags contains the tags present in a "+resource=" comment
|
||||||
|
type ControllerTags struct {
|
||||||
|
gvk schema.GroupVersionKind
|
||||||
|
resource string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseResourceTag parses the tags in a "+resource=" comment into a ResourceTags struct
|
||||||
|
func ParseControllerTag(tag string) ControllerTags {
|
||||||
|
result := ControllerTags{}
|
||||||
|
for _, elem := range strings.Split(tag, ",") {
|
||||||
|
kv := strings.Split(elem, "=")
|
||||||
|
if len(kv) != 2 {
|
||||||
|
log.Fatalf("// +controller: tags must be key value pairs. Expected "+
|
||||||
|
"keys [group=<group>,version=<version>,kind=<kind>,resource=<resource>] "+
|
||||||
|
"Got string: [%s]", tag)
|
||||||
|
}
|
||||||
|
value := kv[1]
|
||||||
|
switch kv[0] {
|
||||||
|
case "group":
|
||||||
|
result.gvk.Group = value
|
||||||
|
case "version":
|
||||||
|
result.gvk.Version = value
|
||||||
|
case "kind":
|
||||||
|
result.gvk.Kind = value
|
||||||
|
case "resource":
|
||||||
|
result.resource = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubresourceTags contains the tags present in a "+subresource=" comment
|
||||||
|
type SubresourceTags struct {
|
||||||
|
Path string
|
||||||
|
Kind string
|
||||||
|
RequestKind string
|
||||||
|
REST string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseSubresourceTag parses the tags in a "+subresource=" comment into a SubresourceTags struct
|
||||||
|
func ParseSubresourceTag(c *APIResource, tag string) SubresourceTags {
|
||||||
|
result := SubresourceTags{}
|
||||||
|
for _, elem := range strings.Split(tag, ",") {
|
||||||
|
kv := strings.Split(elem, "=")
|
||||||
|
if len(kv) != 2 {
|
||||||
|
log.Fatalf("// +subresource: tags must be key value pairs. Expected "+
|
||||||
|
"keys [request=<requestType>,rest=<restImplType>,path=<subresourcepath>] "+
|
||||||
|
"Got string: [%s]", tag)
|
||||||
|
}
|
||||||
|
value := kv[1]
|
||||||
|
switch kv[0] {
|
||||||
|
case "request":
|
||||||
|
result.RequestKind = value
|
||||||
|
case "rest":
|
||||||
|
result.REST = value
|
||||||
|
case "path":
|
||||||
|
// Strip the parent resource
|
||||||
|
result.Path = strings.Replace(value, c.Resource+"/", "", -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetResourceTag returns the value of the "+resource=" comment tag
|
||||||
|
func (b *APIsBuilder) GetResourceTag(c *types.Type) string {
|
||||||
|
comments := Comments(c.CommentLines)
|
||||||
|
resource := comments.GetTag("resource", ":")
|
||||||
|
if len(resource) == 0 {
|
||||||
|
panic(errors.Errorf("Must specify +resource comment for type %v", c.Name))
|
||||||
|
}
|
||||||
|
return resource
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *APIsBuilder) GenClient(c *types.Type) bool {
|
||||||
|
comments := Comments(c.CommentLines)
|
||||||
|
resource := comments.GetTag("resource", ":")
|
||||||
|
return len(resource) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *APIsBuilder) GenDeepCopy(c *types.Type) bool {
|
||||||
|
comments := Comments(c.CommentLines)
|
||||||
|
return comments.HasTag("subresource-request")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *APIsBuilder) GetControllerTag(c *types.Type) string {
|
||||||
|
comments := Comments(c.CommentLines)
|
||||||
|
resource := comments.GetTag("controller", ":")
|
||||||
|
if len(resource) == 0 {
|
||||||
|
panic(errors.Errorf("Must specify +controller comment for type %v", c.Name))
|
||||||
|
}
|
||||||
|
return resource
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *APIsBuilder) GetSubresourceTags(c *types.Type) []string {
|
||||||
|
comments := Comments(c.CommentLines)
|
||||||
|
return comments.GetTags("subresource", ":")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseGroupNames initializes b.GroupNames with the set of all groups
|
||||||
|
func (b *APIsBuilder) ParseGroupNames() {
|
||||||
|
b.GroupNames = sets.String{}
|
||||||
|
for p := range b.UnversionedPkgs {
|
||||||
|
pkg := b.context.Universe[p]
|
||||||
|
if pkg == nil {
|
||||||
|
// If the input had no Go files, for example.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
b.GroupNames.Insert(filepath.Base(p))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParsePackages parses out the sets of Versioned, Unversioned packages and identifies the root Apis package.
|
||||||
|
func (b *APIsBuilder) ParsePackages() {
|
||||||
|
b.VersionedPkgs = sets.NewString()
|
||||||
|
b.UnversionedPkgs = sets.NewString()
|
||||||
|
for _, o := range b.context.Order {
|
||||||
|
if IsAPIResource(o) {
|
||||||
|
versioned := o.Name.Package
|
||||||
|
b.VersionedPkgs.Insert(versioned)
|
||||||
|
|
||||||
|
unversioned := filepath.Dir(versioned)
|
||||||
|
b.UnversionedPkgs.Insert(unversioned)
|
||||||
|
|
||||||
|
if apis := filepath.Dir(unversioned); apis != b.APIsPkg && len(b.APIsPkg) > 0 {
|
||||||
|
panic(errors.Errorf(
|
||||||
|
"Found multiple apis directory paths: %v and %v. "+
|
||||||
|
"Do you have a +resource tag on a resource that is not in a version "+
|
||||||
|
"directory?", b.APIsPkg, apis))
|
||||||
|
} else {
|
||||||
|
b.APIsPkg = apis
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseDomain parses the domain from the apis/doc.go file comment "// +domain=YOUR_DOMAIN".
|
||||||
|
func (b *APIsBuilder) ParseDomain() {
|
||||||
|
pkg := b.context.Universe[b.APIsPkg]
|
||||||
|
if pkg == nil {
|
||||||
|
// If the input had no Go files, for example.
|
||||||
|
panic(errors.Errorf("Missing apis package."))
|
||||||
|
}
|
||||||
|
comments := Comments(pkg.Comments)
|
||||||
|
b.Domain = comments.GetTag("domain", "=")
|
||||||
|
if len(b.Domain) == 0 {
|
||||||
|
panic("Could not find string matching // +domain=.+ in apis/doc.go")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type GenUnversionedType struct {
|
||||||
|
Type *types.Type
|
||||||
|
Resource *APIResource
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *APIsBuilder) ParseStructs(apigroup *APIGroup) {
|
||||||
|
remaining := []GenUnversionedType{}
|
||||||
|
for _, version := range apigroup.Versions {
|
||||||
|
for _, resource := range version.Resources {
|
||||||
|
remaining = append(remaining, GenUnversionedType{resource.Type, resource})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, version := range b.SubByGroupVersionKind[apigroup.Group] {
|
||||||
|
for _, kind := range version {
|
||||||
|
remaining = append(remaining, GenUnversionedType{kind, nil})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done := sets.String{}
|
||||||
|
for len(remaining) > 0 {
|
||||||
|
// Pop the next element from the list
|
||||||
|
next := remaining[0]
|
||||||
|
remaining[0] = remaining[len(remaining)-1]
|
||||||
|
remaining = remaining[:len(remaining)-1]
|
||||||
|
|
||||||
|
// Already processed this type. Skip it
|
||||||
|
if done.Has(next.Type.Name.Name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
done.Insert(next.Type.Name.Name)
|
||||||
|
|
||||||
|
// Generate the struct and append to the list
|
||||||
|
result, additionalTypes := apigroup.DoType(next.Type)
|
||||||
|
|
||||||
|
// This is a resource, so generate the client
|
||||||
|
if b.GenClient(next.Type) {
|
||||||
|
result.GenClient = true
|
||||||
|
result.GenDeepCopy = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if next.Resource != nil {
|
||||||
|
result.NonNamespaced = IsNonNamespaced(next.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.GenDeepCopy(next.Type) {
|
||||||
|
result.GenDeepCopy = true
|
||||||
|
}
|
||||||
|
apigroup.Structs = append(apigroup.Structs, result)
|
||||||
|
|
||||||
|
// Add the newly discovered subtypes
|
||||||
|
for _, at := range additionalTypes {
|
||||||
|
remaining = append(remaining, GenUnversionedType{at, nil})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (apigroup *APIGroup) DoType(t *types.Type) (*Struct, []*types.Type) {
|
||||||
|
remaining := []*types.Type{}
|
||||||
|
|
||||||
|
s := &Struct{
|
||||||
|
Name: t.Name.Name,
|
||||||
|
GenClient: false,
|
||||||
|
GenUnversioned: true, // Generate unversioned structs by default
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range t.CommentLines {
|
||||||
|
if strings.Contains(c, "+genregister:unversioned=false") {
|
||||||
|
// Don't generate the unversioned struct
|
||||||
|
s.GenUnversioned = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, member := range t.Members {
|
||||||
|
uType := member.Type.Name.Name
|
||||||
|
memberName := member.Name
|
||||||
|
uImport := ""
|
||||||
|
|
||||||
|
// Use the element type for Pointers, Maps and Slices
|
||||||
|
mSubType := member.Type
|
||||||
|
hasElem := false
|
||||||
|
for mSubType.Elem != nil {
|
||||||
|
mSubType = mSubType.Elem
|
||||||
|
hasElem = true
|
||||||
|
}
|
||||||
|
if hasElem {
|
||||||
|
// Strip the package from the field type
|
||||||
|
uType = strings.Replace(member.Type.String(), mSubType.Name.Package+".", "", 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
base := filepath.Base(member.Type.String())
|
||||||
|
samepkg := t.Name.Package == mSubType.Name.Package
|
||||||
|
|
||||||
|
// If not in the same package, calculate the import pkg
|
||||||
|
if !samepkg {
|
||||||
|
parts := strings.Split(base, ".")
|
||||||
|
if len(parts) > 1 {
|
||||||
|
// Don't generate unversioned types for core types, just use the versioned types
|
||||||
|
if strings.HasPrefix(mSubType.Name.Package, "k8s.io/api/") {
|
||||||
|
// Import the package under an alias so it doesn't conflict with other groups
|
||||||
|
// having the same version
|
||||||
|
importAlias := path.Base(path.Dir(mSubType.Name.Package)) + path.Base(mSubType.Name.Package)
|
||||||
|
uImport = fmt.Sprintf("%s \"%s\"", importAlias, mSubType.Name.Package)
|
||||||
|
if hasElem {
|
||||||
|
// Replace the full package with the alias when referring to the type
|
||||||
|
uType = strings.Replace(member.Type.String(), mSubType.Name.Package, importAlias, 1)
|
||||||
|
} else {
|
||||||
|
// Replace the full package with the alias when referring to the type
|
||||||
|
uType = fmt.Sprintf("%s.%s", importAlias, parts[1])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch member.Type.Name.Package {
|
||||||
|
case "k8s.io/apimachinery/pkg/apis/meta/v1":
|
||||||
|
// Use versioned types for meta/v1
|
||||||
|
uImport = fmt.Sprintf("%s \"%s\"", "metav1", "k8s.io/apimachinery/pkg/apis/meta/v1")
|
||||||
|
uType = "metav1." + parts[1]
|
||||||
|
default:
|
||||||
|
// Use unversioned types for everything else
|
||||||
|
t := member.Type
|
||||||
|
|
||||||
|
if t.Elem != nil {
|
||||||
|
// Handle Pointers, Maps, Slices
|
||||||
|
|
||||||
|
// We need to parse the package from the Type String
|
||||||
|
t = t.Elem
|
||||||
|
str := member.Type.String()
|
||||||
|
startPkg := strings.LastIndexAny(str, "*]")
|
||||||
|
endPkg := strings.LastIndexAny(str, ".")
|
||||||
|
pkg := str[startPkg+1 : endPkg]
|
||||||
|
name := str[endPkg+1:]
|
||||||
|
prefix := str[:startPkg+1]
|
||||||
|
|
||||||
|
uImportBase := path.Base(pkg)
|
||||||
|
uImportName := path.Base(path.Dir(pkg)) + uImportBase
|
||||||
|
uImport = fmt.Sprintf("%s \"%s\"", uImportName, pkg)
|
||||||
|
|
||||||
|
uType = prefix + uImportName + "." + name
|
||||||
|
|
||||||
|
//fmt.Printf("\nDifferent Parent Package: %s\nChild Package: %s\nKind: %s (Kind.String() %s)\nImport stmt: %s\nType: %s\n\n",
|
||||||
|
// pkg,
|
||||||
|
// member.Type.Name.Package,
|
||||||
|
// member.Type.Kind,
|
||||||
|
// member.Type.String(),
|
||||||
|
// uImport,
|
||||||
|
// uType)
|
||||||
|
} else {
|
||||||
|
// Handle non- Pointer, Maps, Slices
|
||||||
|
pkg := t.Name.Package
|
||||||
|
name := t.Name.Name
|
||||||
|
|
||||||
|
// Come up with the alias the package is imported under
|
||||||
|
// Concatenate with directory package to reduce naming collisions
|
||||||
|
uImportBase := path.Base(pkg)
|
||||||
|
uImportName := path.Base(path.Dir(pkg)) + uImportBase
|
||||||
|
|
||||||
|
// Create the import statement
|
||||||
|
uImport = fmt.Sprintf("%s \"%s\"", uImportName, pkg)
|
||||||
|
|
||||||
|
// Create the field type name - should be <pkgalias>.<TypeName>
|
||||||
|
uType = uImportName + "." + name
|
||||||
|
|
||||||
|
//fmt.Printf("\nDifferent Parent Package: %s\nChild Package: %s\nKind: %s (Kind.String() %s)\nImport stmt: %s\nType: %s\n\n",
|
||||||
|
// pkg,
|
||||||
|
// member.Type.Name.Package,
|
||||||
|
// member.Type.Kind,
|
||||||
|
// member.Type.String(),
|
||||||
|
// uImport,
|
||||||
|
// uType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if member.Embedded {
|
||||||
|
memberName = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Fields = append(s.Fields, &Field{
|
||||||
|
Name: memberName,
|
||||||
|
VersionedPackage: member.Type.Name.Package,
|
||||||
|
UnversionedImport: uImport,
|
||||||
|
UnversionedType: uType,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Add this member Type for processing if it isn't a primitive and
|
||||||
|
// is part of the same API group
|
||||||
|
if !mSubType.IsPrimitive() && GetGroup(mSubType) == GetGroup(t) {
|
||||||
|
remaining = append(remaining, mSubType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s, remaining
|
||||||
|
}
|
292
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators/unversioned_generator.go
generated
vendored
Normal file
292
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators/unversioned_generator.go
generated
vendored
Normal file
|
@ -0,0 +1,292 @@
|
||||||
|
/*
|
||||||
|
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 generators
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
"k8s.io/gengo/generator"
|
||||||
|
)
|
||||||
|
|
||||||
|
type unversionedGenerator struct {
|
||||||
|
generator.DefaultGen
|
||||||
|
apigroup *APIGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ generator.Generator = &unversionedGenerator{}
|
||||||
|
|
||||||
|
func CreateUnversionedGenerator(apigroup *APIGroup, filename string) generator.Generator {
|
||||||
|
return &unversionedGenerator{
|
||||||
|
generator.DefaultGen{OptionalName: filename},
|
||||||
|
apigroup,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *unversionedGenerator) Imports(c *generator.Context) []string {
|
||||||
|
imports := sets.NewString(
|
||||||
|
"fmt",
|
||||||
|
"github.com/kubernetes-incubator/apiserver-builder/pkg/builders",
|
||||||
|
"k8s.io/apimachinery/pkg/apis/meta/internalversion",
|
||||||
|
"k8s.io/apimachinery/pkg/runtime",
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema",
|
||||||
|
"k8s.io/apiserver/pkg/endpoints/request",
|
||||||
|
"k8s.io/apiserver/pkg/registry/rest")
|
||||||
|
|
||||||
|
// Get imports for all fields
|
||||||
|
for _, s := range d.apigroup.Structs {
|
||||||
|
for _, f := range s.Fields {
|
||||||
|
if len(f.UnversionedImport) > 0 {
|
||||||
|
imports.Insert(f.UnversionedImport)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return imports.List()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *unversionedGenerator) Finalize(context *generator.Context, w io.Writer) error {
|
||||||
|
temp := template.Must(template.New("unversioned-wiring-template").Parse(UnversionedAPITemplate))
|
||||||
|
err := temp.Execute(w, d.apigroup)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var UnversionedAPITemplate = `
|
||||||
|
var (
|
||||||
|
{{ range $api := .UnversionedResources -}}
|
||||||
|
Internal{{ $api.Kind }} = builders.NewInternalResource(
|
||||||
|
"{{ $api.Resource }}",
|
||||||
|
"{{ $api.Kind }}",
|
||||||
|
func() runtime.Object { return &{{ $api.Kind }}{} },
|
||||||
|
func() runtime.Object { return &{{ $api.Kind }}List{} },
|
||||||
|
)
|
||||||
|
Internal{{ $api.Kind }}Status = builders.NewInternalResourceStatus(
|
||||||
|
"{{ $api.Resource }}",
|
||||||
|
"{{ $api.Kind }}Status",
|
||||||
|
func() runtime.Object { return &{{ $api.Kind }}{} },
|
||||||
|
func() runtime.Object { return &{{ $api.Kind }}List{} },
|
||||||
|
)
|
||||||
|
{{ range $subresource := .Subresources -}}
|
||||||
|
Internal{{$subresource.REST}} = builders.NewInternalSubresource(
|
||||||
|
"{{$subresource.Resource}}", "{{$subresource.Request}}", "{{$subresource.Path}}",
|
||||||
|
func() runtime.Object { return &{{$subresource.Request}}{} },
|
||||||
|
)
|
||||||
|
{{ end -}}
|
||||||
|
{{ end -}}
|
||||||
|
|
||||||
|
// Registered resources and subresources
|
||||||
|
ApiVersion = builders.NewApiGroup("{{.Group}}.{{.Domain}}").WithKinds(
|
||||||
|
{{ range $api := .UnversionedResources -}}
|
||||||
|
Internal{{$api.Kind}},
|
||||||
|
Internal{{$api.Kind}}Status,
|
||||||
|
{{ range $subresource := $api.Subresources -}}
|
||||||
|
Internal{{$subresource.REST}},
|
||||||
|
{{ end -}}
|
||||||
|
{{ end -}}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Required by code generated by go2idl
|
||||||
|
AddToScheme = ApiVersion.SchemaBuilder.AddToScheme
|
||||||
|
SchemeBuilder = ApiVersion.SchemaBuilder
|
||||||
|
localSchemeBuilder = &SchemeBuilder
|
||||||
|
SchemeGroupVersion = ApiVersion.GroupVersion
|
||||||
|
)
|
||||||
|
|
||||||
|
// Required by code generated by go2idl
|
||||||
|
// Kind takes an unqualified kind and returns a Group qualified GroupKind
|
||||||
|
func Kind(kind string) schema.GroupKind {
|
||||||
|
return SchemeGroupVersion.WithKind(kind).GroupKind()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required by code generated by go2idl
|
||||||
|
// Resource takes an unqualified resource and returns a Group qualified GroupResource
|
||||||
|
func Resource(resource string) schema.GroupResource {
|
||||||
|
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||||
|
}
|
||||||
|
|
||||||
|
{{ range $s := .Structs -}}
|
||||||
|
{{ if $s.GenUnversioned -}}
|
||||||
|
{{ if $s.GenClient }}// +genclient{{end}}
|
||||||
|
{{ if $s.GenClient }}// +genclient{{ if $s.NonNamespaced }}:nonNamespaced{{end}}{{end}}
|
||||||
|
{{ if $s.GenDeepCopy }}// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object{{end}}
|
||||||
|
|
||||||
|
type {{ $s.Name }} struct {
|
||||||
|
{{ range $f := $s.Fields -}}
|
||||||
|
{{ $f.Name }} {{ $f.UnversionedType }}
|
||||||
|
{{ end -}}
|
||||||
|
}
|
||||||
|
{{ end -}}
|
||||||
|
{{ end -}}
|
||||||
|
|
||||||
|
{{ range $api := .UnversionedResources -}}
|
||||||
|
//
|
||||||
|
// {{.Kind}} Functions and Structs
|
||||||
|
//
|
||||||
|
// +k8s:deepcopy-gen=false
|
||||||
|
type {{.Strategy}} struct {
|
||||||
|
builders.DefaultStorageStrategy
|
||||||
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen=false
|
||||||
|
type {{.StatusStrategy}} struct {
|
||||||
|
builders.DefaultStatusStorageStrategy
|
||||||
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|
||||||
|
type {{$api.Kind}}List struct {
|
||||||
|
metav1.TypeMeta
|
||||||
|
metav1.ListMeta
|
||||||
|
Items []{{$api.Kind}}
|
||||||
|
}
|
||||||
|
|
||||||
|
{{ range $subresource := $api.Subresources -}}
|
||||||
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|
||||||
|
type {{$subresource.Request}}List struct {
|
||||||
|
metav1.TypeMeta
|
||||||
|
metav1.ListMeta
|
||||||
|
Items []{{$subresource.Request}}
|
||||||
|
}
|
||||||
|
{{ end -}}
|
||||||
|
|
||||||
|
func ({{$api.Kind}}) NewStatus() interface{} {
|
||||||
|
return {{$api.Kind}}Status{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pc *{{$api.Kind}}) GetStatus() interface{} {
|
||||||
|
return pc.Status
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pc *{{$api.Kind}}) SetStatus(s interface{}) {
|
||||||
|
pc.Status = s.({{$api.Kind}}Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pc *{{$api.Kind}}) GetSpec() interface{} {
|
||||||
|
return pc.Spec
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pc *{{$api.Kind}}) SetSpec(s interface{}) {
|
||||||
|
pc.Spec = s.({{$api.Kind}}Spec)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pc *{{$api.Kind}}) GetObjectMeta() *metav1.ObjectMeta {
|
||||||
|
return &pc.ObjectMeta
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pc *{{$api.Kind}}) SetGeneration(generation int64) {
|
||||||
|
pc.ObjectMeta.Generation = generation
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pc {{$api.Kind}}) GetGeneration() int64 {
|
||||||
|
return pc.ObjectMeta.Generation
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registry is an interface for things that know how to store {{.Kind}}.
|
||||||
|
// +k8s:deepcopy-gen=false
|
||||||
|
type {{.Kind}}Registry interface {
|
||||||
|
List{{.Kind}}s(ctx request.Context, options *internalversion.ListOptions) (*{{.Kind}}List, error)
|
||||||
|
Get{{.Kind}}(ctx request.Context, id string, options *metav1.GetOptions) (*{{.Kind}}, error)
|
||||||
|
Create{{.Kind}}(ctx request.Context, id *{{.Kind}}) (*{{.Kind}}, error)
|
||||||
|
Update{{.Kind}}(ctx request.Context, id *{{.Kind}}) (*{{.Kind}}, error)
|
||||||
|
Delete{{.Kind}}(ctx request.Context, id string) (bool, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRegistry returns a new Registry interface for the given Storage. Any mismatched types will panic.
|
||||||
|
func New{{.Kind}}Registry(sp builders.StandardStorageProvider) {{.Kind}}Registry {
|
||||||
|
return &storage{{.Kind}}{sp}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implement Registry
|
||||||
|
// storage puts strong typing around storage calls
|
||||||
|
// +k8s:deepcopy-gen=false
|
||||||
|
type storage{{.Kind}} struct {
|
||||||
|
builders.StandardStorageProvider
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *storage{{.Kind}}) List{{.Kind}}s(ctx request.Context, options *internalversion.ListOptions) (*{{.Kind}}List, error) {
|
||||||
|
if options != nil && options.FieldSelector != nil && !options.FieldSelector.Empty() {
|
||||||
|
return nil, fmt.Errorf("field selector not supported yet")
|
||||||
|
}
|
||||||
|
st := s.GetStandardStorage()
|
||||||
|
obj, err := st.List(ctx, options)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return obj.(*{{.Kind}}List), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *storage{{.Kind}}) Get{{.Kind}}(ctx request.Context, id string, options *metav1.GetOptions) (*{{.Kind}}, error) {
|
||||||
|
st := s.GetStandardStorage()
|
||||||
|
obj, err := st.Get(ctx, id, options)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return obj.(*{{.Kind}}), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *storage{{.Kind}}) Create{{.Kind}}(ctx request.Context, object *{{.Kind}}) (*{{.Kind}}, error) {
|
||||||
|
st := s.GetStandardStorage()
|
||||||
|
obj, err := st.Create(ctx, object, nil, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return obj.(*{{.Kind}}), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *storage{{.Kind}}) Update{{.Kind}}(ctx request.Context, object *{{.Kind}}) (*{{.Kind}}, error) {
|
||||||
|
st := s.GetStandardStorage()
|
||||||
|
obj, _, err := st.Update(ctx, object.Name, rest.DefaultUpdatedObjectInfo(object), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return obj.(*{{.Kind}}), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *storage{{.Kind}}) Delete{{.Kind}}(ctx request.Context, id string) (bool, error) {
|
||||||
|
st := s.GetStandardStorage()
|
||||||
|
_, sync, err := st.Delete(ctx, id, nil)
|
||||||
|
return sync, err
|
||||||
|
}
|
||||||
|
|
||||||
|
{{ end -}}
|
||||||
|
`
|
||||||
|
|
||||||
|
var installTemplate = `
|
||||||
|
{{.BoilerPlate}}
|
||||||
|
|
||||||
|
package install
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kubernetes-incubator/apiserver-builder/example/pkg/apis"
|
||||||
|
"k8s.io/apimachinery/pkg/apimachinery/announced"
|
||||||
|
"k8s.io/apimachinery/pkg/apimachinery/registered"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Install(
|
||||||
|
groupFactoryRegistry announced.APIGroupFactoryRegistry,
|
||||||
|
registry *registered.APIRegistrationManager,
|
||||||
|
scheme *runtime.Scheme) {
|
||||||
|
|
||||||
|
apis.{{ title .Group }}APIBuilder().Install(groupFactoryRegistry, registry, scheme)
|
||||||
|
}
|
||||||
|
`
|
167
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators/util.go
generated
vendored
Normal file
167
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators/util.go
generated
vendored
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
/*
|
||||||
|
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 generators
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"k8s.io/gengo/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IsAPIResource returns true if t has a +resource comment tag
|
||||||
|
func IsAPIResource(t *types.Type) bool {
|
||||||
|
for _, c := range t.CommentLines {
|
||||||
|
if strings.Contains(c, "+resource") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNonNamespaced returns true if t has a +nonNamespaced comment tag
|
||||||
|
func IsNonNamespaced(t *types.Type) bool {
|
||||||
|
if !IsAPIResource(t) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range t.CommentLines {
|
||||||
|
if strings.Contains(c, "+genclient:nonNamespaced") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range t.SecondClosestCommentLines {
|
||||||
|
if strings.Contains(c, "+genclient:nonNamespaced") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsController(t *types.Type) bool {
|
||||||
|
for _, c := range t.CommentLines {
|
||||||
|
if strings.Contains(c, "+controller") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsAPISubresource returns true if t has a +subresource-request comment tag
|
||||||
|
func IsAPISubresource(t *types.Type) bool {
|
||||||
|
for _, c := range t.CommentLines {
|
||||||
|
if strings.Contains(c, "+subresource-request") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasSubresource returns true if t is an APIResource with one or more Subresources
|
||||||
|
func HasSubresource(t *types.Type) bool {
|
||||||
|
if !IsAPIResource(t) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, c := range t.CommentLines {
|
||||||
|
if strings.Contains(c, "+subresource") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsUnversioned(t *types.Type, group string) bool {
|
||||||
|
return IsApisDir(filepath.Base(filepath.Dir(t.Name.Package))) && GetGroup(t) == group
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsVersioned(t *types.Type, group string) bool {
|
||||||
|
dir := filepath.Base(filepath.Dir(filepath.Dir(t.Name.Package)))
|
||||||
|
return IsApisDir(dir) && GetGroup(t) == group
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetVersion(t *types.Type, group string) string {
|
||||||
|
if !IsVersioned(t, group) {
|
||||||
|
panic(errors.Errorf("Cannot get version for unversioned type %v", t.Name))
|
||||||
|
}
|
||||||
|
return filepath.Base(t.Name.Package)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetGroup(t *types.Type) string {
|
||||||
|
return filepath.Base(GetGroupPackage(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetGroupPackage(t *types.Type) string {
|
||||||
|
if IsApisDir(filepath.Base(filepath.Dir(t.Name.Package))) {
|
||||||
|
return t.Name.Package
|
||||||
|
}
|
||||||
|
return filepath.Dir(t.Name.Package)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetKind(t *types.Type, group string) string {
|
||||||
|
if !IsVersioned(t, group) && !IsUnversioned(t, group) {
|
||||||
|
panic(errors.Errorf("Cannot get kind for type not in group %v", t.Name))
|
||||||
|
}
|
||||||
|
return t.Name.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsApisDir returns true if a directory path is a Kubernetes api directory
|
||||||
|
func IsApisDir(dir string) bool {
|
||||||
|
return dir == "apis" || dir == "api"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comments is a structure for using comment tags on go structs and fields
|
||||||
|
type Comments []string
|
||||||
|
|
||||||
|
// GetTags returns the value for the first comment with a prefix matching "+name="
|
||||||
|
// e.g. "+name=foo\n+name=bar" would return "foo"
|
||||||
|
func (c Comments) GetTag(name, sep string) string {
|
||||||
|
for _, c := range c {
|
||||||
|
prefix := fmt.Sprintf("+%s%s", name, sep)
|
||||||
|
if strings.HasPrefix(c, prefix) {
|
||||||
|
return strings.Replace(c, prefix, "", 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Comments) HasTag(name string) bool {
|
||||||
|
for _, c := range c {
|
||||||
|
prefix := fmt.Sprintf("+%s", name)
|
||||||
|
if strings.HasPrefix(c, prefix) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTags returns the value for all comments with a prefix and separator. E.g. for "name" and "="
|
||||||
|
// "+name=foo\n+name=bar" would return []string{"foo", "bar"}
|
||||||
|
func (c Comments) GetTags(name, sep string) []string {
|
||||||
|
tags := []string{}
|
||||||
|
for _, c := range c {
|
||||||
|
prefix := fmt.Sprintf("+%s%s", name, sep)
|
||||||
|
if strings.HasPrefix(c, prefix) {
|
||||||
|
tags = append(tags, strings.Replace(c, prefix, "", 1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tags
|
||||||
|
}
|
173
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators/versioned_generator.go
generated
vendored
Normal file
173
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators/versioned_generator.go
generated
vendored
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
/*
|
||||||
|
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 generators
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"k8s.io/gengo/generator"
|
||||||
|
)
|
||||||
|
|
||||||
|
type versionedGenerator struct {
|
||||||
|
generator.DefaultGen
|
||||||
|
apiversion *APIVersion
|
||||||
|
apigroup *APIGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ generator.Generator = &versionedGenerator{}
|
||||||
|
|
||||||
|
func CreateVersionedGenerator(apiversion *APIVersion, apigroup *APIGroup, filename string) generator.Generator {
|
||||||
|
return &versionedGenerator{
|
||||||
|
generator.DefaultGen{OptionalName: filename},
|
||||||
|
apiversion,
|
||||||
|
apigroup,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasSubresources(version *APIVersion) bool {
|
||||||
|
for _, v := range version.Resources {
|
||||||
|
if len(v.Subresources) != 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *versionedGenerator) Imports(c *generator.Context) []string {
|
||||||
|
imports := []string{
|
||||||
|
"metav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"",
|
||||||
|
"k8s.io/apimachinery/pkg/runtime",
|
||||||
|
"github.com/kubernetes-incubator/apiserver-builder/pkg/builders",
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema",
|
||||||
|
d.apigroup.Pkg.Path,
|
||||||
|
}
|
||||||
|
if hasSubresources(d.apiversion) {
|
||||||
|
imports = append(imports, "k8s.io/apiserver/pkg/registry/rest")
|
||||||
|
}
|
||||||
|
|
||||||
|
return imports
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *versionedGenerator) Finalize(context *generator.Context, w io.Writer) error {
|
||||||
|
temp := template.Must(template.New("versioned-template").Parse(VersionedAPITemplate))
|
||||||
|
return temp.Execute(w, d.apiversion)
|
||||||
|
}
|
||||||
|
|
||||||
|
var VersionedAPITemplate = `
|
||||||
|
var (
|
||||||
|
{{ range $api := .Resources -}}
|
||||||
|
|
||||||
|
{{ if $api.REST -}}
|
||||||
|
{{$api.Group}}{{$api.Kind}}Storage = builders.NewApiResourceWithStorage( // Resource status endpoint
|
||||||
|
{{ $api.Group }}.Internal{{ $api.Kind }},
|
||||||
|
{{.Kind}}SchemeFns{},
|
||||||
|
func() runtime.Object { return &{{ $api.Kind }}{} }, // Register versioned resource
|
||||||
|
func() runtime.Object { return &{{ $api.Kind }}List{} }, // Register versioned resource list
|
||||||
|
New{{ $api.REST }},
|
||||||
|
)
|
||||||
|
{{ else -}}
|
||||||
|
{{$api.Group}}{{$api.Kind}}Storage = builders.NewApiResource( // Resource status endpoint
|
||||||
|
{{ $api.Group }}.Internal{{ $api.Kind }},
|
||||||
|
{{.Kind}}SchemeFns{},
|
||||||
|
func() runtime.Object { return &{{ $api.Kind }}{} }, // Register versioned resource
|
||||||
|
func() runtime.Object { return &{{ $api.Kind }}List{} }, // Register versioned resource list
|
||||||
|
&{{ $api.Strategy }}{builders.StorageStrategySingleton},
|
||||||
|
)
|
||||||
|
{{ end -}}
|
||||||
|
{{ end -}}
|
||||||
|
|
||||||
|
ApiVersion = builders.NewApiVersion("{{.Group}}.{{.Domain}}", "{{.Version}}").WithResources(
|
||||||
|
{{ range $api := .Resources -}}
|
||||||
|
{{$api.Group}}{{$api.Kind}}Storage,
|
||||||
|
{{ if $api.REST }}{{ else -}}
|
||||||
|
builders.NewApiResource( // Resource status endpoint
|
||||||
|
{{ $api.Group }}.Internal{{ $api.Kind }}Status,
|
||||||
|
{{.Kind}}SchemeFns{},
|
||||||
|
func() runtime.Object { return &{{ $api.Kind }}{} }, // Register versioned resource
|
||||||
|
func() runtime.Object { return &{{ $api.Kind }}List{} }, // Register versioned resource list
|
||||||
|
&{{ $api.StatusStrategy }}{builders.StatusStorageStrategySingleton},
|
||||||
|
),{{ end -}}
|
||||||
|
|
||||||
|
{{ range $subresource := $api.Subresources -}}
|
||||||
|
builders.NewApiResourceWithStorage(
|
||||||
|
{{ $api.Group }}.Internal{{ $subresource.REST }},
|
||||||
|
builders.SchemeFnsSingleton,
|
||||||
|
func() runtime.Object { return &{{ $subresource.Request }}{} }, // Register versioned resource
|
||||||
|
nil,
|
||||||
|
func() rest.Storage { return &{{ $subresource.REST }}{ {{$api.Group}}.New{{$api.Kind}}Registry({{$api.Group}}{{$api.Kind}}Storage) } },
|
||||||
|
),
|
||||||
|
{{ end -}}
|
||||||
|
{{ end -}}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Required by code generated by go2idl
|
||||||
|
AddToScheme = ApiVersion.SchemaBuilder.AddToScheme
|
||||||
|
SchemeBuilder = ApiVersion.SchemaBuilder
|
||||||
|
localSchemeBuilder = &SchemeBuilder
|
||||||
|
SchemeGroupVersion = ApiVersion.GroupVersion
|
||||||
|
)
|
||||||
|
|
||||||
|
// Required by code generated by go2idl
|
||||||
|
// Kind takes an unqualified kind and returns a Group qualified GroupKind
|
||||||
|
func Kind(kind string) schema.GroupKind {
|
||||||
|
return SchemeGroupVersion.WithKind(kind).GroupKind()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required by code generated by go2idl
|
||||||
|
// Resource takes an unqualified resource and returns a Group qualified GroupResource
|
||||||
|
func Resource(resource string) schema.GroupResource {
|
||||||
|
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||||
|
}
|
||||||
|
|
||||||
|
{{ range $api := .Resources -}}
|
||||||
|
//
|
||||||
|
// {{.Kind}} Functions and Structs
|
||||||
|
//
|
||||||
|
// +k8s:deepcopy-gen=false
|
||||||
|
type {{.Kind}}SchemeFns struct {
|
||||||
|
builders.DefaultSchemeFns
|
||||||
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen=false
|
||||||
|
type {{.Strategy}} struct {
|
||||||
|
builders.DefaultStorageStrategy
|
||||||
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen=false
|
||||||
|
type {{.StatusStrategy}} struct {
|
||||||
|
builders.DefaultStatusStorageStrategy
|
||||||
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|
||||||
|
type {{$api.Kind}}List struct {
|
||||||
|
metav1.TypeMeta ` + "`json:\",inline\"`" + `
|
||||||
|
metav1.ListMeta ` + "`json:\"metadata,omitempty\"`" + `
|
||||||
|
Items []{{$api.Kind}} ` + "`json:\"items\"`" + `
|
||||||
|
}
|
||||||
|
|
||||||
|
{{ range $subresource := $api.Subresources -}}
|
||||||
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|
||||||
|
type {{$subresource.Request}}List struct {
|
||||||
|
metav1.TypeMeta ` + "`json:\",inline\"`" + `
|
||||||
|
metav1.ListMeta ` + "`json:\"metadata,omitempty\"`" + `
|
||||||
|
Items []{{$subresource.Request}} ` + "`json:\"items\"`" + `
|
||||||
|
}
|
||||||
|
{{ end }}{{ end -}}
|
||||||
|
`
|
51
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/main.go
generated
vendored
Normal file
51
vendor/github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/main.go
generated
vendored
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
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 (
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"github.com/kubernetes-incubator/apiserver-builder/cmd/apiregister-gen/generators"
|
||||||
|
"k8s.io/apiserver/pkg/util/logs"
|
||||||
|
"k8s.io/gengo/args"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
logs.InitLogs()
|
||||||
|
defer logs.FlushLogs()
|
||||||
|
|
||||||
|
if len(os.Getenv("GOMAXPROCS")) == 0 {
|
||||||
|
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||||
|
}
|
||||||
|
|
||||||
|
arguments := args.Default()
|
||||||
|
|
||||||
|
// Override defaults.
|
||||||
|
arguments.OutputFileBaseName = "zz_generated.api.register"
|
||||||
|
|
||||||
|
// Custom args.
|
||||||
|
customArgs := &generators.CustomArgs{}
|
||||||
|
arguments.CustomArgs = customArgs
|
||||||
|
|
||||||
|
g := generators.Gen{}
|
||||||
|
if err := g.Execute(arguments); err != nil {
|
||||||
|
glog.Fatalf("Error: %v", err)
|
||||||
|
}
|
||||||
|
glog.V(2).Info("Completed successfully.")
|
||||||
|
}
|
Loading…
Reference in New Issue