Kubebuilder: Configurable per-project paths

Created on 4 Nov 2019  路  5Comments  路  Source: kubernetes-sigs/kubebuilder

Paths where every file is placed is hardcoded in kubebuilder. The current scaffold is a good starting point, but some projects may want to use a different layout.

Files that should have a configurable path:

  • [ ] Dockerfile: currently in root directory.
  • [ ] main.go: currently in root directory.
  • [ ] KIND_types.go, groupversion_info.go & zz-generated.deepcopy.go: currently in the api/VERSION directory.
  • [ ] KIND_controller.go & suite_test.go: currently in controllers directory.
  • [ ] manager: currently under the bin directory.
  • [ ] All the *.yaml files: currently under config directory.
  • [ ] boilerplate.go.txt: currently in hack directory.

Haven't used webhooks but they will probably also have some hard-coded paths.

For example, following https://github.com/golang-standards/project-layout, the wanted layout would be:

root
+- build
| +- package
| | +- Dockerfile
| +- manager
+- cmd
| +- manager
| | +- main.go
+- config
| +- boilerplate.go.txt
+- deployments
| +- certmanager
| +- crd
| +- default
| +- manager
| +- prometheus
| +- rbac
| +- samples
| +- webhook
+- internal
| +- api
| | +- v1alpha1
| | | +- KIND_types.go
| | | +- groupversion_info.go
| | | +- zz-generated.deepcopy.go
| +- controllers
| | +- KIND_controller.go
| | +- suite_test.go

Some implementation considerations:
Dockerfile, main.go, manager and all the *.yaml files are required from the Makefile. The rest should be pretty starightforward.
Paths should be stored either as a string or as an array. If stored as a string, / should be used as the separator. Then the scaffolding would split by / and use path/filepath.Join to be platform independent. If stored as an array, only the path/filepath.Join step would be required.
Paths require some templating. {group}, {version} and {kind} could be used. As fmt.Sprintf doesn't support named parameters, they should first be replaced internally by %[1]s, %[2]s and %[3]s, and then use fmt.Sprintf for formatting.

This feature requests would also prepare for multi-group apis. If the api path configuration option contains a {group} tag, multi-group is enabled, if it doesn't, it is disabled.

/kind feature

kinfeature

Most helpful comment

I do agree that kubebuilder must have an opinion, but I think that some degree of configurable paths would provide nicer project structures while still keeping the starting learning curve smooth.

I have taken into account the design decissions in https://github.com/kubernetes-sigs/kubebuilder/blob/master/designs/simplified-scaffolding.md. I think that the effort that was done in reducing the number of scaffolded files was really needed as it was hard to understand for newcommers. However, while having api and controllers as directories under the root project directory makes the files easier to find, they also polute a bit the root directory and do not follow de-facto standards as having go libraries under pkg or internal and commands under cmd.

What about the following configurable paths:

  • Entrypoint directory: currently ., in my previous example cmd/manager. main.go would be placed in this directory.
  • Library directory: currently ., in my previous example internal. api/apis, controllers and webhook directories as they are now will be placed inside this directory.
  • Binary directory: currently bin, in my previous example build. Binaries will be output to this directory (it may allow things like $GOBIN).
  • Deployment directory: currently config, in my previous example deployments. All the k8s and kustomize YAML files subdirectories.
  • Dockerfile directory: currently ., in my previous example build/package. Dockerfile would be placed here. It would still be called with the root directory as the context for docker build.
  • Boilerplate directory: currently hack, in my previous example config.

This would allow some project customization while still providing opinion on how those directories are organized internally. The default values would still be the current ones, and they would only be modified through som flags in kubebuilder init ... command. The paths will be stored in PROJECT. There will be no automated way to change this after creation, as it would require modifying imports though all the project, and other hardcoded paths such as in the Makefile or the Dockerfile.

All 5 comments

How would you get the PROJECT configuration values inside the Makefile?

So, I'm a bit wary of this -- kubebuilder is supposed to have opinions. I wouldn't mind having a "scaffold this one file to this location" perhaps, but I'm really not sure how deep we want to go on full configuration of KB itself (willing to be convinced otherwise, but thusfar we've been reluctant to support other API paths, and such).

I do agree that kubebuilder must have an opinion, but I think that some degree of configurable paths would provide nicer project structures while still keeping the starting learning curve smooth.

I have taken into account the design decissions in https://github.com/kubernetes-sigs/kubebuilder/blob/master/designs/simplified-scaffolding.md. I think that the effort that was done in reducing the number of scaffolded files was really needed as it was hard to understand for newcommers. However, while having api and controllers as directories under the root project directory makes the files easier to find, they also polute a bit the root directory and do not follow de-facto standards as having go libraries under pkg or internal and commands under cmd.

What about the following configurable paths:

  • Entrypoint directory: currently ., in my previous example cmd/manager. main.go would be placed in this directory.
  • Library directory: currently ., in my previous example internal. api/apis, controllers and webhook directories as they are now will be placed inside this directory.
  • Binary directory: currently bin, in my previous example build. Binaries will be output to this directory (it may allow things like $GOBIN).
  • Deployment directory: currently config, in my previous example deployments. All the k8s and kustomize YAML files subdirectories.
  • Dockerfile directory: currently ., in my previous example build/package. Dockerfile would be placed here. It would still be called with the root directory as the context for docker build.
  • Boilerplate directory: currently hack, in my previous example config.

This would allow some project customization while still providing opinion on how those directories are organized internally. The default values would still be the current ones, and they would only be modified through som flags in kubebuilder init ... command. The paths will be stored in PROJECT. There will be no automated way to change this after creation, as it would require modifying imports though all the project, and other hardcoded paths such as in the Makefile or the Dockerfile.

Since we're talking about making things better: I'd like to raise an open question regarding webhook-related-functions location, is api/.../v1 the right package to define the validation and defaulting?

  • Sure, it is nice tho that you can add Methods to your type directly
  • But if you have some delegated validations, using helpers and/or external imports, it will bloat up the before pretty clean api/.../v1 package. How about a api/.../v1/validation package?

    • Maybe for that reason the core/meta/etc. package has validation separate from the plain api package: 1, 2, 3

    • (I had issues with dependency complexity/version incompatibility, while I just wanted to use and read the CRD type I've defined here from somewhere else)

Plugins should be able to work around this, closing in favor of plugins

Was this page helpful?
0 / 5 - 0 ratings

Related issues

gerred picture gerred  路  4Comments

derailed picture derailed  路  5Comments

narayanasamyr picture narayanasamyr  路  4Comments

quanguachong picture quanguachong  路  3Comments

cheyang picture cheyang  路  4Comments