Skip to content

Commit 391d011

Browse files
author
Phillip Wittrock
authored
Merge pull request #132 from Liujingfang1/tmpcore
Add support for creating core type controllers
2 parents b8eff8f + fe2d0f9 commit 391d011

File tree

11 files changed

+275
-34
lines changed

11 files changed

+275
-34
lines changed

build/test.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export TEST_ASSET_ETCD=/tmp/kubebuilder/bin/etcd
3333
kubebuilder init repo --domain sample.kubernetes.io
3434
kubebuilder create resource --group insect --version v1beta1 --kind Bee
3535
kubebuilder create resource --group insect --version v1beta1 --kind Wasp
36+
kubebuilder create controller --group apps --version v1beta2 --kind Deployment --core-type
3637

3738
# Verify the controller-manager builds and the tests pass
3839
go build ./cmd/...

cmd/internal/codegen/parse/parser.go

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,13 @@ limitations under the License.
1717
package parse
1818

1919
import (
20+
"go/build"
2021
"path/filepath"
22+
"strings"
23+
"os"
24+
"bufio"
25+
26+
"github.com/golang/glog"
2127

2228
"github.com/kubernetes-sigs/kubebuilder/cmd/internal/codegen"
2329
"github.com/pkg/errors"
@@ -114,6 +120,39 @@ func (b *APIs) parseDomain() {
114120
comments := Comments(pkg.Comments)
115121
b.Domain = comments.getTag("domain", "=")
116122
if len(b.Domain) == 0 {
117-
panic("Could not find string matching // +domain=.+ in apis/doc.go")
123+
b.Domain = parseDomainFromFiles(b.context.Inputs)
124+
if len(b.Domain) == 0 {
125+
panic("Could not find string matching // +domain=.+ in apis/doc.go")
126+
}
127+
}
128+
}
129+
130+
func parseDomainFromFiles(paths []string) string {
131+
var domain string
132+
for _, path := range paths {
133+
if strings.HasSuffix(path, "pkg/apis") {
134+
filePath := strings.Join([]string{build.Default.GOPATH, "src", path, "doc.go"}, "/")
135+
lines := []string{}
136+
137+
file, err := os.Open(filePath)
138+
if err != nil {
139+
glog.Fatal(err)
140+
}
141+
defer file.Close()
142+
scanner := bufio.NewScanner(file)
143+
for scanner.Scan() {
144+
if strings.HasPrefix(scanner.Text(), "//") {
145+
lines = append(lines, strings.Replace(scanner.Text(), "// ", "", 1))
146+
}
147+
}
148+
if err := scanner.Err(); err != nil {
149+
glog.Fatal(err)
150+
}
151+
152+
comments := Comments(lines)
153+
domain = comments.getTag("domain", "=")
154+
break
155+
}
118156
}
157+
return domain
119158
}

cmd/kubebuilder-gen/internal/controllergen/inject.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,21 @@ func (d *injectGenerator) Imports(c *generator.Context) []string {
4343

4444
repo := d.Controllers[0].Repo
4545
im := []string{
46-
"time",
4746
"github.com/kubernetes-sigs/kubebuilder/pkg/controller",
4847
"k8s.io/client-go/rest",
4948
repo + "/pkg/controller/sharedinformers",
5049
repo + "/pkg/client/informers/externalversions",
5150
repo + "/pkg/inject/args",
5251
"rbacv1 \"k8s.io/api/rbac/v1\"",
53-
"k8s.io/client-go/kubernetes/scheme",
54-
"rscheme " + "\"" + repo + "/pkg/client/clientset/versioned/scheme\"",
5552
}
5653

54+
if len(d.APIS.Groups) > 0 {
55+
im = append(im, []string{
56+
"time",
57+
"k8s.io/client-go/kubernetes/scheme",
58+
"rscheme " + "\"" + repo + "/pkg/client/clientset/versioned/scheme\""}...
59+
)
60+
}
5761
// Import package for each controller
5862
repos := map[string]string{}
5963
for _, c := range d.Controllers {
@@ -100,7 +104,7 @@ func (d *injectGenerator) Finalize(context *generator.Context, w io.Writer) erro
100104

101105
var injectAPITemplate = `
102106
func init() {
103-
rscheme.AddToScheme(scheme.Scheme)
107+
{{ $length := len .APIS.Groups }}{{if ne $length 0 }}rscheme.AddToScheme(scheme.Scheme){{ end }}
104108
105109
// Inject Informers
106110
Inject = append(Inject, func(arguments args.InjectArgs) error {

cmd/kubebuilder/create/resource/controller.go renamed to cmd/kubebuilder/create/controller/controller.go

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package resource
17+
package controller
1818

1919
import (
2020
"fmt"
@@ -25,7 +25,20 @@ import (
2525
"github.com/kubernetes-sigs/kubebuilder/cmd/kubebuilder/util"
2626
)
2727

28-
func doController(dir string, args resourceTemplateArgs) bool {
28+
type controllerTemplateArgs struct {
29+
BoilerPlate string
30+
Domain string
31+
Group string
32+
Version string
33+
Kind string
34+
Resource string
35+
Repo string
36+
PluralizedKind string
37+
NonNamespacedKind bool
38+
CoreType bool
39+
}
40+
41+
func doController(dir string, args controllerTemplateArgs) bool {
2942
path := filepath.Join(dir, "pkg", "controller", strings.ToLower(createutil.KindName), "controller.go")
3043
fmt.Printf("\t%s\n", filepath.Join(
3144
"pkg", "controller", strings.ToLower(createutil.KindName), "controller.go"))
@@ -42,11 +55,17 @@ import (
4255
"github.com/kubernetes-sigs/kubebuilder/pkg/controller"
4356
"github.com/kubernetes-sigs/kubebuilder/pkg/controller/types"
4457
"k8s.io/client-go/tools/record"
45-
58+
{{if .CoreType}}
59+
{{.Group}}{{.Version}}client "k8s.io/client-go/kubernetes/typed/{{.Group}}/{{.Version}}"
60+
{{.Group}}{{.Version}}lister "k8s.io/client-go/listers/{{.Group}}/{{.Version}}"
61+
{{.Group}}{{.Version}} "k8s.io/api/{{.Group}}/{{.Version}}"
62+
{{.Group}}{{.Version}}informer "k8s.io/client-go/informers/{{.Group}}/{{.Version}}"
63+
{{else}}
4664
{{.Group}}{{.Version}}client "{{.Repo}}/pkg/client/clientset/versioned/typed/{{.Group}}/{{.Version}}"
4765
{{.Group}}{{.Version}}lister "{{.Repo}}/pkg/client/listers/{{.Group}}/{{.Version}}"
4866
{{.Group}}{{.Version}} "{{.Repo}}/pkg/apis/{{.Group}}/{{.Version}}"
4967
{{.Group}}{{.Version}}informer "{{.Repo}}/pkg/client/informers/externalversions/{{.Group}}/{{.Version}}"
68+
{{end}}
5069
"{{.Repo}}/pkg/inject/args"
5170
)
5271
@@ -59,7 +78,7 @@ func (bc *{{.Kind}}Controller) Reconcile(k types.ReconcileKey) error {
5978
log.Printf("Implement the Reconcile function on {{lower .Kind}}.{{.Kind}}Controller to reconcile %s\n", k.Name)
6079
return nil
6180
}
62-
81+
{{if .CoreType}}// +kubebuilder:informers:group={{ .Group }},version={{ .Version }},kind={{ .Kind }}{{end}}
6382
// +kubebuilder:controller:group={{ .Group }},version={{ .Version }},kind={{ .Kind}},resource={{ .Resource }}
6483
type {{.Kind}}Controller struct {
6584
// INSERT ADDITIONAL FIELDS HERE
@@ -76,7 +95,8 @@ func ProvideController(arguments args.InjectArgs) (*controller.GenericController
7695
// INSERT INITIALIZATIONS FOR ADDITIONAL FIELDS HERE
7796
bc := &{{.Kind}}Controller{
7897
{{lower .Kind}}Lister: arguments.ControllerManager.GetInformerProvider(&{{.Group}}{{.Version}}.{{.Kind}}{}).({{.Group}}{{.Version}}informer.{{.Kind}}Informer).Lister(),
79-
{{lower .Kind}}client: arguments.Clientset.{{title .Group}}{{title .Version}}(),
98+
{{if .CoreType}}{{lower .Kind}}client: arguments.KubernetesClientSet.{{title .Group}}{{title .Version}}(),{{else}}
99+
{{lower .Kind}}client: arguments.Clientset.{{title .Group}}{{title .Version}}(),{{end}}
80100
{{lower .Kind}}recorder: arguments.CreateRecorder("{{.Kind}}Controller"),
81101
}
82102

cmd/kubebuilder/create/resource/controllertest.go renamed to cmd/kubebuilder/create/controller/controllertest.go

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package resource
17+
package controller
1818

1919
import (
2020
"fmt"
@@ -25,7 +25,7 @@ import (
2525
"github.com/kubernetes-sigs/kubebuilder/cmd/kubebuilder/util"
2626
)
2727

28-
func doControllerTest(dir string, args resourceTemplateArgs) bool {
28+
func doControllerTest(dir string, args controllerTemplateArgs) bool {
2929
path := filepath.Join(dir, "pkg", "controller", strings.ToLower(createutil.KindName),
3030
fmt.Sprintf("%s_suite_test.go",
3131
strings.ToLower(createutil.KindName)))
@@ -52,16 +52,17 @@ import (
5252
"github.com/kubernetes-sigs/kubebuilder/pkg/test"
5353
"k8s.io/client-go/kubernetes"
5454
"k8s.io/client-go/rest"
55-
56-
"{{ .Repo }}/pkg/client/clientset/versioned"
55+
{{if not .CoreType}}"{{ .Repo }}/pkg/client/clientset/versioned"{{end}}
5756
"{{ .Repo }}/pkg/inject"
5857
"{{ .Repo }}/pkg/inject/args"
5958
)
6059
6160
var (
6261
testenv *test.TestEnvironment
6362
config *rest.Config
63+
{{if not .CoreType}}
6464
cs *versioned.Clientset
65+
{{end}}
6566
ks *kubernetes.Clientset
6667
shutdown chan struct{}
6768
ctrl *controller.GenericController
@@ -77,7 +78,9 @@ var _ = BeforeSuite(func() {
7778
var err error
7879
config, err = testenv.Start()
7980
Expect(err).NotTo(HaveOccurred())
81+
{{if not .CoreType}}
8082
cs = versioned.NewForConfigOrDie(config)
83+
{{end}}
8184
ks = kubernetes.NewForConfigOrDie(config)
8285
8386
shutdown = make(chan struct{})
@@ -112,9 +115,13 @@ import (
112115
113116
"github.com/kubernetes-sigs/kubebuilder/pkg/controller/types"
114117
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
115-
118+
{{if .CoreType}}
119+
. "k8s.io/api/{{.Group}}/{{.Version}}"
120+
. "k8s.io/client-go/kubernetes/typed/{{.Group}}/{{.Version}}"
121+
{{else}}
116122
. "{{ .Repo }}/pkg/apis/{{ .Group }}/{{ .Version }}"
117123
. "{{ .Repo }}/pkg/client/clientset/versioned/typed/{{ .Group }}/{{ .Version }}"
124+
{{end}}
118125
)
119126
120127
// EDIT THIS FILE!
@@ -153,7 +160,11 @@ var _ = Describe("{{ .Kind }} controller", func() {
153160
}
154161
155162
// Create the instance
163+
{{if .CoreType}}
164+
client = ks.{{title .Group}}{{title .Version}}().{{ plural .Kind }}({{ if not .NonNamespacedKind }}"default"{{ end }})
165+
{{else}}
156166
client = cs.{{title .Group}}{{title .Version}}().{{ plural .Kind }}({{ if not .NonNamespacedKind }}"default"{{ end }})
167+
{{end}}
157168
_, err := client.Create(&instance)
158169
Expect(err).ShouldNot(HaveOccurred())
159170
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
Copyright 2018 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package controller
18+
19+
import (
20+
"fmt"
21+
"log"
22+
"os"
23+
24+
createutil "github.com/kubernetes-sigs/kubebuilder/cmd/kubebuilder/create/util"
25+
generatecmd "github.com/kubernetes-sigs/kubebuilder/cmd/kubebuilder/generate"
26+
"github.com/kubernetes-sigs/kubebuilder/cmd/kubebuilder/util"
27+
"github.com/markbates/inflect"
28+
"github.com/spf13/cobra"
29+
"strings"
30+
)
31+
32+
type ControllerArguments struct {
33+
nonNamespacedKind bool
34+
generate bool
35+
CoreType bool
36+
}
37+
38+
func AddCreateController(cmd *cobra.Command) {
39+
var c ControllerArguments
40+
41+
createControllerCmd := &cobra.Command{
42+
Use: "controller",
43+
Short: "Creates a controller for an API group, version and resource",
44+
Long: `Creates a controller for an API group, version and resource.
45+
46+
Also creates:
47+
- controller reconcile function
48+
- tests for the controller
49+
`,
50+
Example: `# Create a controller for resource "Bee" in the "insect" group with version "v1beta"
51+
kubebuilder create controller --group insect --version v1beta1 --kind Bee
52+
53+
# Create a controller for k8s core type "Deployment" in the "apps" group with version "v1beta2"
54+
kubebuilder create controller --group apps --version v1beta2 --kind Deployment --core-type
55+
`,
56+
Run: c.RunCreateController,
57+
}
58+
createutil.RegisterResourceFlags(createControllerCmd)
59+
createControllerCmd.Flags().BoolVar(&c.nonNamespacedKind, "non-namespaced", false, "if set, the API kind will be non namespaced")
60+
createControllerCmd.Flags().BoolVar(&c.generate, "generate", true, "generate controller code")
61+
createControllerCmd.Flags().BoolVar(&c.CoreType, "core-type", false, "generate controller for core type")
62+
cmd.AddCommand(createControllerCmd)
63+
}
64+
65+
func (c *ControllerArguments) RunCreateController(cmd *cobra.Command, args []string) {
66+
if _, err := os.Stat("pkg"); err != nil {
67+
log.Fatalf("could not find 'pkg' directory. must run kubebuilder init before creating controller")
68+
}
69+
70+
util.GetDomain()
71+
c.Validate()
72+
73+
cr := util.GetCopyright(createutil.Copyright)
74+
75+
fmt.Printf("Creating controller ...\n")
76+
c.CreateController(cr)
77+
if c.generate {
78+
fmt.Printf("Generating code for new controller... " +
79+
"Regenerate after editing controller files by running `kubebuilder generate clean; kubebuilder generate`.\n")
80+
generatecmd.RunGenerate(cmd, args)
81+
}
82+
fmt.Printf("Next: Run the controller and create an instance with:\n" +
83+
"$ GOBIN=${PWD}/bin go install ${PWD#$GOPATH/src/}/cmd/controller-manager\n" +
84+
"$ bin/controller-manager --kubeconfig ~/.kube/config\n" +
85+
"$ kubectl apply -f hack/sample/" + strings.ToLower(createutil.KindName) + ".yaml\n")
86+
}
87+
88+
func (c *ControllerArguments) Validate() {
89+
createutil.ValidateResourceFlags()
90+
}
91+
92+
func (c *ControllerArguments) CreateController(boilerplate string) {
93+
args := controllerTemplateArgs{
94+
boilerplate,
95+
util.Domain,
96+
createutil.GroupName,
97+
createutil.VersionName,
98+
createutil.KindName,
99+
createutil.ResourceName,
100+
util.Repo,
101+
inflect.NewDefaultRuleset().Pluralize(createutil.KindName),
102+
c.nonNamespacedKind,
103+
c.CoreType,
104+
}
105+
106+
dir, err := os.Getwd()
107+
if err != nil {
108+
log.Fatal(err)
109+
}
110+
fmt.Printf("Edit your controller function...\n")
111+
doController(dir, args)
112+
doControllerTest(dir, args)
113+
}

cmd/kubebuilder/create/create.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package create
1818

1919
import (
2020
"github.com/kubernetes-sigs/kubebuilder/cmd/kubebuilder/create/config"
21+
"github.com/kubernetes-sigs/kubebuilder/cmd/kubebuilder/create/controller"
2122
"github.com/kubernetes-sigs/kubebuilder/cmd/kubebuilder/create/example"
2223
"github.com/kubernetes-sigs/kubebuilder/cmd/kubebuilder/create/resource"
2324
"github.com/kubernetes-sigs/kubebuilder/cmd/kubebuilder/create/util"
@@ -41,6 +42,7 @@ func AddCreate(cmd *cobra.Command) {
4142
resource.AddCreateResource(createCmd)
4243
config.AddCreateConfig(createCmd)
4344
example.AddCreateExample(createCmd)
45+
controller.AddCreateController(createCmd)
4446
}
4547

4648
func RunCreate(cmd *cobra.Command, args []string) {

cmd/kubebuilder/create/resource/run.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ import (
2020
"fmt"
2121
"log"
2222
"os"
23-
2423
"strings"
2524

25+
controllerct "github.com/kubernetes-sigs/kubebuilder/cmd/kubebuilder/create/controller"
2626
createutil "github.com/kubernetes-sigs/kubebuilder/cmd/kubebuilder/create/util"
2727
generatecmd "github.com/kubernetes-sigs/kubebuilder/cmd/kubebuilder/generate"
2828
"github.com/kubernetes-sigs/kubebuilder/cmd/kubebuilder/util"
@@ -113,13 +113,11 @@ func createResource(boilerplate string) {
113113
doResourceTest(dir, args)
114114

115115
if controller {
116-
fmt.Printf("Edit your controller function...\n")
117-
doController(dir, args)
118-
doControllerTest(dir, args)
116+
fmt.Printf("Creating controller ...\n")
117+
c := controllerct.ControllerArguments{CoreType: false}
118+
c.CreateController(boilerplate)
119119
}
120120

121-
//doDockerfile(filepath.Join(dir, "build"), args)
122-
//doExample(dir, args)
123121
fmt.Printf("Edit your sample resource instance...\n")
124122
doSample(dir, args)
125123
}

0 commit comments

Comments
 (0)