Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Add the rest of the missing fields and stabilize config v3 #1968

Merged
merged 1 commit into from
Jan 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 10 additions & 11 deletions VERSIONING.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ take care of building and publishing the artifacts.
| Name | Example | Description |
|--- |--- |--- |
| KubeBuilder version | `v2.2.0`, `v2.3.0`, `v2.3.1` | Tagged versions of the KubeBuilder project, representing changes to the source code in this repository. See the [releases][kb-releases] page for binary releases. |
| Project version | `"1"`, `"2"`, `"3-alpha"` | Project version defines the scheme of a `PROJECT` configuration file. This version is defined in a `PROJECT` file's `version`. |
| Plugin version | `v2`, `v3-alpha` | Represents the version of an individual plugin, as well as the corresponding scaffolding that it generates. This version is defined in a plugin key, ex. `go.kubebuilder.io/v2`. See the [design doc][cli-plugins-versioning] for more details. |
| Project version | `"1"`, `"2"`, `"3"` | Project version defines the scheme of a `PROJECT` configuration file. This version is defined in a `PROJECT` file's `version`. |
| Plugin version | `v2`, `v3` | Represents the version of an individual plugin, as well as the corresponding scaffolding that it generates. This version is defined in a plugin key, ex. `go.kubebuilder.io/v2`. See the [design doc][cli-plugins-versioning] for more details. |

### Incrementing versions

Expand All @@ -76,32 +76,31 @@ Project versions should only be increased if a breaking change is introduced in
Similarly, the introduction of a new plugin version might only lead to a new minor version release of KubeBuilder, since no breaking change is being made to the CLI itself. It'd only be a breaking change to KubeBuilder if we remove support for an older plugin version. See the plugins design doc [versioning section][cli-plugins-versioning]
for more details on plugin versioning.

**NOTE:** the scheme for project version `"2"` was defined before the concept of plugins was introduced, so plugin `go.kubebuilder.io/v2` is implicitly used for those project types. Schema for project versions `"3-alpha"` and beyond define a `layout` key that informs the plugin system of which plugin to use.
**NOTE:** the scheme for project version `"2"` was defined before the concept of plugins was introduced, so plugin `go.kubebuilder.io/v2` is implicitly used for those project types. Schema for project versions `"3"` and beyond define a `layout` key that informs the plugin system of which plugin to use.

## Introducing changes to plugins

Changes made to plugins only require a plugin version increase if and only if a change is made to a plugin
that breaks projects scaffolded with the previous plugin version. Once a plugin version `vX` is stabilized (it doesn't
have an "alpha" or "beta" suffix), a new plugin package should be created containing a new plugin with version
`v(X+1)-alpha`. Typically this is done by (semantically) `cp -r pkg/plugin/vX pkg/plugin/v(X+1)` then updating
`v(X+1)-alpha`. Typically this is done by (semantically) `cp -r pkg/plugins/golang/vX pkg/plugins/golang/v(X+1)` then updating
version numbers and paths. All further breaking changes to the plugin should be made in this package; the `vX`
plugin would then be frozen to breaking changes.

You must also add a migration guide to the [migrations](https://book.kubebuilder.io/migrations.html)
section of the KubeBuilder book in your PR. It should detail the steps required
for users to upgrade their projects from `vX` to `v(X+1)-alpha`.

### Example

KubeBuilder scaffolds projects with plugin `go.kubebuilder.io/v2` by default. A `v3-alpha` version
was created after `v2` stabilized.
KubeBuilder scaffolds projects with plugin `go.kubebuilder.io/v3` by default.

You create a feature that adds a new marker to the file `main.go` scaffolded by `init`
that `create api` will use to update that file. The changes introduced in your feature
would cause errors if used with projects built with plugins `go.kubebuilder.io/v2`
without users manually updating their projects. Thus, your changes introduce a breaking change
to plugin `go.kubebuilder.io`, and can only be merged into plugin version `v3-alpha`.
This plugin's package should exist already, so a PR must be made against the

You must also add a migration guide to the [migrations](https://book.kubebuilder.io/migrations.html)
section of the KubeBuilder book in your PR. It should detail the steps required
for users to upgrade their projects from `v2` to `v3-alpha`.
Adirio marked this conversation as resolved.
Show resolved Hide resolved
This plugin's package should exist already.

[kb-releases]:https://github.com/kubernetes-sigs/kubebuilder/releases
[cli-plugins-versioning]:docs/book/src/reference/cli-plugins.md
6 changes: 3 additions & 3 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (

"sigs.k8s.io/kubebuilder/v3/pkg/cli"
cfgv2 "sigs.k8s.io/kubebuilder/v3/pkg/config/v2"
cfgv3alpha "sigs.k8s.io/kubebuilder/v3/pkg/config/v3alpha"
cfgv3 "sigs.k8s.io/kubebuilder/v3/pkg/config/v3"
pluginv2 "sigs.k8s.io/kubebuilder/v3/pkg/plugins/golang/v2"
pluginv3 "sigs.k8s.io/kubebuilder/v3/pkg/plugins/golang/v3"
)
Expand All @@ -30,13 +30,13 @@ func main() {
c, err := cli.New(
cli.WithCommandName("kubebuilder"),
cli.WithVersion(versionString()),
cli.WithDefaultProjectVersion(cfgv3alpha.Version),
cli.WithDefaultProjectVersion(cfgv3.Version),
cli.WithPlugins(
&pluginv2.Plugin{},
&pluginv3.Plugin{},
),
cli.WithDefaultPlugins(cfgv2.Version, &pluginv2.Plugin{}),
cli.WithDefaultPlugins(cfgv3alpha.Version, &pluginv3.Plugin{}),
cli.WithDefaultPlugins(cfgv3.Version, &pluginv3.Plugin{}),
Adirio marked this conversation as resolved.
Show resolved Hide resolved
cli.WithCompletion,
)
if err != nil {
Expand Down
17 changes: 11 additions & 6 deletions docs/book/src/component-config-tutorial/testdata/project/PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,23 @@ multigroup: true
projectName: project
repo: tutorial.kubebuilder.io/project
resources:
- crdVersion: v1
- api:
crdVersion: v1
group: batch
kind: CronJob
version: v1
webhookVersion: v1
- crdVersion: v1
webhooks:
webhookVersion: v1
- api:
crdVersion: v1
group: batch
kind: CronJob
version: v2
webhookVersion: v1
- crdVersion: v1
webhooks:
webhookVersion: v1
- api:
crdVersion: v1
group: config
kind: ProjectConfig
version: v2
version: 3-alpha
version: "3"
38 changes: 7 additions & 31 deletions docs/book/src/migration/project/v2_v3.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ layout: go.kubebuilder.io/v2

- Update the `version`

The `version` field represents the version of Project layouts. So, you ought to update this to `3-alpha`:
The `version` field represents the version of Project layouts. So, you ought to update this to `"3"`:

```
...
version: 3-alpha`
version: "3"
...
```

Expand All @@ -58,7 +58,7 @@ resources:
- group: webapp
kind: Guestbook
version: v1
version: 3-alpha
version: "3"
```

### Verification
Expand All @@ -68,47 +68,23 @@ fine.

## Migrating your projects to use v3+ plugins

<aside class="note warning">

<h1>Note</h1>

`v3+` plugins are still in alpha phase and are not scaffolded by default. You are able to use them, try it out and get all improvements made so far by initializing projects with the arg `--plugins=go.kubebuilder.io/v3-alpha`:

```sh
kubebuilder init --domain my.domain --plugins=go.kubebuilder.io/v3-alpha
```

</aside>

<aside class="note warning">

<h1>Note</h1>

Currently, the plugin `v3-alpha` has NO breaking changes. However, until it is declared stable breaking changes can be made related to K8s API deprecations of `v1beta1` versions of `CustomResourceDefinition` and `ValidatingWebhookConfiguration` and to upgrade the `cert-manager`. More info:

- [cert-manager related configuration should be migrated to cert-manager.io/v1 #1666
](https://github.com/kubernetes-sigs/kubebuilder/issues/1666)
- [Set preserveUnknownFields to false in the CRD conversion webhook patch #933](https://github.com/kubernetes-sigs/kubebuilder/issues/933)
- [Migrate existing KB project to v1 CRDs and Webhooks with minimal user effort #1065
](https://github.com/kubernetes-sigs/kubebuilder/issues/1065)

</aside>
In order to migrate your projects to v3 some changes need to be manually done to the PROJECT file, and some other scaffolded files.
Adirio marked this conversation as resolved.
Show resolved Hide resolved

Adirio marked this conversation as resolved.
Show resolved Hide resolved
### Update your PROJECT file

Update the `layout` setting to the new plugin version ` go.kubebuilder.io/v3-alpha` as follows:
Update the `layout` setting to the new plugin version `go.kubebuilder.io/v3` as follows:

```sh
$ cat PROJECT
domain: my.domain
layout: go.kubebuilder.io/v3-alpha
layout: go.kubebuilder.io/v3
projectName: example
repo: example
resources:
- group: webapp
kind: Guestbook
version: v1
version: 3-alpha
version: "3"

```

Expand Down
4 changes: 2 additions & 2 deletions pkg/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (

internalconfig "sigs.k8s.io/kubebuilder/v3/pkg/cli/internal/config"
"sigs.k8s.io/kubebuilder/v3/pkg/config"
cfgv3alpha "sigs.k8s.io/kubebuilder/v3/pkg/config/v3alpha"
cfgv3 "sigs.k8s.io/kubebuilder/v3/pkg/config/v3"
"sigs.k8s.io/kubebuilder/v3/pkg/plugin"
)

Expand Down Expand Up @@ -131,7 +131,7 @@ func newCLI(opts ...Option) (*cli, error) {
// Default cli options.
c := &cli{
commandName: "kubebuilder",
defaultProjectVersion: cfgv3alpha.Version,
defaultProjectVersion: cfgv3.Version,
defaultPlugins: make(map[config.Version][]string),
plugins: make(map[string]plugin.Plugin),
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (

"sigs.k8s.io/kubebuilder/v3/pkg/config"
cfgv2 "sigs.k8s.io/kubebuilder/v3/pkg/config/v2"
cfgv3alpha "sigs.k8s.io/kubebuilder/v3/pkg/config/v3alpha"
cfgv3 "sigs.k8s.io/kubebuilder/v3/pkg/config/v3"
"sigs.k8s.io/kubebuilder/v3/pkg/plugin"
)

Expand Down Expand Up @@ -203,7 +203,7 @@ var _ = Describe("CLI", func() {

When("having layout field", func() {
It("should succeed", func() {
projectConfig = cfgv3alpha.New()
projectConfig = cfgv3.New()
Expect(projectConfig.SetLayout("go.kubebuilder.io/v2")).To(Succeed())
projectVersion, plugins, err = getInfoFromConfig(projectConfig)
Expect(err).NotTo(HaveOccurred())
Expand Down
20 changes: 9 additions & 11 deletions pkg/config/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,17 @@ type Config interface {
SetRepository(repository string) error

// GetProjectName returns the project name
// This method was introduced in project version 3-alpha.
// This method was introduced in project version 3.
GetProjectName() string
// SetProjectName sets the project name
// This method was introduced in project version 3-alpha.
// This method was introduced in project version 3.
SetProjectName(name string) error

// GetLayout returns the config layout
// This method was introduced in project version 3-alpha.
// This method was introduced in project version 3.
GetLayout() string
// SetLayout sets the Config layout
// This method was introduced in project version 3-alpha.
// This method was introduced in project version 3.
SetLayout(layout string) error

/* Boolean fields */
Expand All @@ -63,13 +63,13 @@ type Config interface {
ClearMultiGroup() error

// IsComponentConfig checks if component config is enabled
// This method was introduced in project version 3-alpha.
// This method was introduced in project version 3.
IsComponentConfig() bool
// SetComponentConfig enables component config
// This method was introduced in project version 3-alpha.
// This method was introduced in project version 3.
SetComponentConfig() error
// ClearComponentConfig disables component config
// This method was introduced in project version 3-alpha.
// This method was introduced in project version 3.
ClearComponentConfig() error

/* Resources */
Expand Down Expand Up @@ -97,12 +97,10 @@ type Config interface {
/* Plugins */

// DecodePluginConfig decodes a plugin config stored in Config into configObj, which must be a pointer.
// This method is intended to be used for custom configuration objects, which were introduced in project version
// 3-alpha.
// This method is intended to be used for custom configuration objects, which were introduced in project version 3.
DecodePluginConfig(key string, configObj interface{}) error
// EncodePluginConfig encodes a config object into Config by overwriting the existing object stored under key.
// This method is intended to be used for custom configuration objects, which were introduced in project version
// 3-alpha.
// This method is intended to be used for custom configuration objects, which were introduced in project version 3.
EncodePluginConfig(key string, configObj interface{}) error

/* Persistence */
Expand Down
2 changes: 1 addition & 1 deletion pkg/config/v2/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ var _ = Describe("cfg", func() {
})
})

Context("Name", func() {
Context("ProjectName", func() {
Adirio marked this conversation as resolved.
Show resolved Hide resolved
It("GetProjectName should return an empty name", func() {
Expect(c.GetProjectName()).To(Equal(""))
})
Expand Down
54 changes: 27 additions & 27 deletions pkg/config/v3alpha/config.go → pkg/config/v3/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package v3alpha
package v3

import (
"fmt"
Expand All @@ -24,11 +24,10 @@ import (

"sigs.k8s.io/kubebuilder/v3/pkg/config"
"sigs.k8s.io/kubebuilder/v3/pkg/model/resource"
"sigs.k8s.io/kubebuilder/v3/pkg/model/stage"
)

// Version is the config.Version for project configuration 3-alpha
var Version = config.Version{Number: 3, Stage: stage.Alpha}
// Version is the config.Version for project configuration 3
var Version = config.Version{Number: 3}

type cfg struct {
// Version
Expand Down Expand Up @@ -157,8 +156,6 @@ func (c cfg) ResourcesLength() int {

// HasResource implements config.Config
func (c cfg) HasResource(gvk resource.GVK) bool {
gvk.Domain = "" // Version 3 alpha does not include domain per resource

for _, res := range c.Resources {
if gvk.IsEqualTo(res.GVK) {
return true
Expand All @@ -170,11 +167,16 @@ func (c cfg) HasResource(gvk resource.GVK) bool {

// GetResource implements config.Config
func (c cfg) GetResource(gvk resource.GVK) (resource.Resource, error) {
gvk.Domain = "" // Version 3 alpha does not include domain per resource

for _, res := range c.Resources {
if gvk.IsEqualTo(res.GVK) {
return res.Copy(), nil
r := res.Copy()

// Plural is only stored if irregular, so if it is empty recover the regular form
if r.Plural == "" {
r.Plural = resource.RegularPlural(r.Kind)
}

return r, nil
}
}

Expand All @@ -185,33 +187,28 @@ func (c cfg) GetResource(gvk resource.GVK) (resource.Resource, error) {
func (c cfg) GetResources() ([]resource.Resource, error) {
resources := make([]resource.Resource, 0, len(c.Resources))
for _, res := range c.Resources {
resources = append(resources, res.Copy())
}
r := res.Copy()

return resources, nil
}
// Plural is only stored if irregular, so if it is empty recover the regular form
if r.Plural == "" {
r.Plural = resource.RegularPlural(r.Kind)
}

func discardNonIncludedFields(res *resource.Resource) {
res.Domain = "" // Version 3 alpha does not include domain per resource
res.Plural = "" // Version 3 alpha does not include plural forms
res.Path = "" // Version 3 alpha does not include paths
if res.API != nil {
res.API.Namespaced = false // Version 3 alpha does not include if the api was namespaced
}
res.Controller = false // Version 3 alpha does not include if the controller was scaffolded
if res.Webhooks != nil {
res.Webhooks.Defaulting = false // Version 3 alpha does not include if the defaulting webhook was scaffolded
res.Webhooks.Validation = false // Version 3 alpha does not include if the validation webhook was scaffolded
res.Webhooks.Conversion = false // Version 3 alpha does not include if the conversion webhook was scaffolded
resources = append(resources, r)
}

return resources, nil
}

// AddResource implements config.Config
func (c *cfg) AddResource(res resource.Resource) error {
// As res is passed by value it is already a shallow copy, but we need to make a deep copy
res = res.Copy()

discardNonIncludedFields(&res) // Version 3 alpha does not include several fields from the Resource model
// Plural is only stored if irregular
if res.Plural == resource.RegularPlural(res.Kind) {
res.Plural = ""
}

if !c.HasResource(res.GVK) {
c.Resources = append(c.Resources, res)
Expand All @@ -224,7 +221,10 @@ func (c *cfg) UpdateResource(res resource.Resource) error {
// As res is passed by value it is already a shallow copy, but we need to make a deep copy
res = res.Copy()

discardNonIncludedFields(&res) // Version 3 alpha does not include several fields from the Resource model
// Plural is only stored if irregular
if res.Plural == resource.RegularPlural(res.Kind) {
res.Plural = ""
}

for i, r := range c.Resources {
if res.GVK.IsEqualTo(r.GVK) {
Expand Down
Loading