Skip to content

Commit

Permalink
contract: add CRD naming requirements
Browse files Browse the repository at this point in the history
  • Loading branch information
sbueringer committed Sep 27, 2022
1 parent c7c0c59 commit ded9239
Show file tree
Hide file tree
Showing 10 changed files with 79 additions and 13 deletions.
4 changes: 2 additions & 2 deletions cmd/clusterctl/client/cluster/topology.go
Expand Up @@ -23,7 +23,6 @@ import (
"strings"

jsonpatch "github.com/evanphx/json-patch"
"github.com/gobuffalo/flect"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
Expand All @@ -44,6 +43,7 @@ import (
"sigs.k8s.io/cluster-api/feature"
clustertopologycontroller "sigs.k8s.io/cluster-api/internal/controllers/topology/cluster"
"sigs.k8s.io/cluster-api/internal/webhooks"
"sigs.k8s.io/cluster-api/util/contract"
)

const (
Expand Down Expand Up @@ -519,7 +519,7 @@ func (t *topologyClient) generateCRDs(objs []*unstructured.Unstructured) []*apie
Kind: "CustomResourceDefinition",
},
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s.%s", flect.Pluralize(strings.ToLower(gvk.Kind)), gvk.Group),
Name: contract.CalculateCRDName(gvk.Group, gvk.Kind),
Labels: map[string]string{
// Here we assume that all the versions are compatible with the Cluster API contract version.
clusterv1.GroupVersion.String(): gvk.Version,
Expand Down
Expand Up @@ -50,6 +50,9 @@ The `ImplementationControlPlane` *must* rely on the existence of

### CRD contracts

The CRD name must have the format produced by `sigs.k8s.io/cluster-api/util/contract.CalculateCRDName(Group, Kind)`.
The same applies for the name of the corresponding ControlPlane template CRD.

#### Required `spec` fields for implementations using replicas

* `replicas` - is an integer representing the number of desired
Expand Down Expand Up @@ -78,21 +81,21 @@ documentation][scale].

#### Required `spec` fields for implementations using Machines

* `machineTemplate` - is a struct containing details of the control plane
* `machineTemplate` - is a struct containing details of the control plane
machine template.

* `machineTemplate.metadata` - is a struct containing info about metadata for control plane
machines.

* `machineTemplate.metadata.labels` - is a map of string keys and values that can be used
* `machineTemplate.metadata.labels` - is a map of string keys and values that can be used
to organize and categorize control plane machines.

* `machineTemplate.metadata.annotations` - is a map of string keys and values containing
arbitrary metadata to be applied to control plane machines.

* `machineTemplate.infrastructureRef` - is a corev1.ObjectReference to a custom resource
offered by an infrastructure provider. The namespace in the ObjectReference must
be in the same namespace of the control plane object.
be in the same namespace of the control plane object.

* `machineTemplate.nodeDrainTimeout` - is a *metav1.Duration defining the total amount of time
that the controller will spend on draining a control plane node.
Expand Down Expand Up @@ -220,7 +223,7 @@ following fields defined:
version, will be used to determine when a control plane is fully upgraded
(`spec.version == status.version`) and for enforcing [Kubernetes version
skew policies](https://kubernetes.io/releases/version-skew-policy/) in managed topologies.

#### Optional `status` fields

The `status` object **may** define several fields:
Expand Down
Expand Up @@ -41,6 +41,8 @@ Cluster associations are made via labels.

The BootstrapConfig object **must** have a `status` object.

The CRD name must have the format produced by `sigs.k8s.io/cluster-api/util/contract.CalculateCRDName(Group, Kind)`.

To override the bootstrap provider, a user (or external system) can directly set the `MachinePool.Spec.Bootstrap.DataSecretName`
field. This will mark the machine as ready for bootstrapping and no bootstrap data secret name will be copied from the
BootstrapConfig object.
Expand Down Expand Up @@ -73,6 +75,8 @@ status:

The InfrastructureMachinePool object **must** have both `spec` and `status` objects.

The CRD name must have the format produced by `sigs.k8s.io/cluster-api/util/contract.CalculateCRDName(Group, Kind)`.

#### Required `spec` fields

The `spec` object **must** have at least one field defined:
Expand Down
6 changes: 5 additions & 1 deletion docs/book/src/developer/providers/bootstrap.md
Expand Up @@ -10,7 +10,8 @@ A bootstrap provider generates bootstrap data that is used to bootstrap a Kubern
A bootstrap provider must define an API type for bootstrap resources. The type:

1. Must belong to an API group served by the Kubernetes apiserver
2. May be implemented as a CustomResourceDefinition, or as part of an aggregated apiserver
2. Must be implemented as a CustomResourceDefinition.
1. The CRD name must have the format produced by `sigs.k8s.io/cluster-api/util/contract.CalculateCRDName(Group, Kind)`.
3. Must be namespace-scoped
4. Must have the standard Kubernetes "type metadata" and "object metadata"
5. Should have a `spec` field containing fields relevant to the bootstrap provider
Expand Down Expand Up @@ -54,6 +55,9 @@ type PhippyBootstrapConfigTemplateResource struct {
Spec PhippyBootstrapConfigSpec `json:"spec"`
}
```

The CRD name of the template must also have the format produced by `sigs.k8s.io/cluster-api/util/contract.CalculateCRDName(Group, Kind)`.

### List Resources

For any resource, also add list resources, e.g.
Expand Down
5 changes: 4 additions & 1 deletion docs/book/src/developer/providers/cluster-infrastructure.md
Expand Up @@ -12,7 +12,8 @@ Examples might include networking, load balancers, firewall rules, and so on.
A cluster infrastructure provider must define an API type for "infrastructure cluster" resources. The type:

1. Must belong to an API group served by the Kubernetes apiserver
2. May be implemented as a CustomResourceDefinition, or as part of an aggregated apiserver
2. Must be implemented as a CustomResourceDefinition.
1. The CRD name must have the format produced by `sigs.k8s.io/cluster-api/util/contract.CalculateCRDName(Group, Kind)`.
3. Must be namespace-scoped
4. Must have the standard Kubernetes "type metadata" and "object metadata"
5. Must have a `spec` field with the following:
Expand Down Expand Up @@ -66,6 +67,8 @@ type InfraClusterTemplateResource struct {
}
```

The CRD name of the template must also have the format produced by `sigs.k8s.io/cluster-api/util/contract.CalculateCRDName(Group, Kind)`.

### List Resources

For any resource, also add list resources, e.g.
Expand Down
6 changes: 5 additions & 1 deletion docs/book/src/developer/providers/machine-infrastructure.md
Expand Up @@ -10,7 +10,8 @@ These may be physical or virtual instances, and they represent the infrastructur
A machine infrastructure provider must define an API type for "infrastructure machine" resources. The type:

1. Must belong to an API group served by the Kubernetes apiserver
2. May be implemented as a CustomResourceDefinition, or as part of an aggregated apiserver
2. Must be implemented as a CustomResourceDefinition.
1. The CRD name must have the format produced by `sigs.k8s.io/cluster-api/util/contract.CalculateCRDName(Group, Kind)`.
3. Must be namespace-scoped
4. Must have the standard Kubernetes "type metadata" and "object metadata"
5. Must have a `spec` field with the following:
Expand Down Expand Up @@ -75,6 +76,9 @@ type InfraMachineTemplateResource struct {
Spec InfraMachineSpec `json:"spec"`
}
```

The CRD name of the template must also have the format produced by `sigs.k8s.io/cluster-api/util/contract.CalculateCRDName(Group, Kind)`.

### List Resources

For any resource, also add list resources, e.g.
Expand Down
4 changes: 2 additions & 2 deletions internal/test/builder/crds.go
Expand Up @@ -17,7 +17,6 @@ limitations under the License.
package builder

import (
"fmt"
"strings"

"github.com/gobuffalo/flect"
Expand All @@ -27,6 +26,7 @@ import (
"k8s.io/utils/pointer"

clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/util/contract"
)

func untypedCRD(gvk schema.GroupVersionKind) *apiextensionsv1.CustomResourceDefinition {
Expand All @@ -49,7 +49,7 @@ func generateCRD(gvk schema.GroupVersionKind, properties map[string]apiextension
Kind: "CustomResourceDefinition",
},
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s.%s", flect.Pluralize(strings.ToLower(gvk.Kind)), gvk.Group),
Name: contract.CalculateCRDName(gvk.Group, gvk.Kind),
Labels: map[string]string{
clusterv1.GroupVersion.String(): "v1beta1",
},
Expand Down
30 changes: 30 additions & 0 deletions util/contract/contract.go
@@ -0,0 +1,30 @@
/*
Copyright 2022 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 contract

import (
"fmt"
"strings"

"github.com/gobuffalo/flect"
)

// CalculateCRDName generates a CRD name based on group and kind according to
// the naming conventions in the contract.
func CalculateCRDName(group, kind string) string {
return fmt.Sprintf("%s.%s", flect.Pluralize(strings.ToLower(kind)), group)
}
18 changes: 18 additions & 0 deletions util/contract/doc.go
@@ -0,0 +1,18 @@
/*
Copyright 2022 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 contract contains utils related to the Cluster API contract.
package contract
4 changes: 2 additions & 2 deletions util/util.go
Expand Up @@ -28,7 +28,6 @@ import (
"time"

"github.com/blang/semver"
"github.com/gobuffalo/flect"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
Expand All @@ -48,6 +47,7 @@ import (

clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/util/annotations"
"sigs.k8s.io/cluster-api/util/contract"
)

const (
Expand Down Expand Up @@ -442,7 +442,7 @@ func HasOwner(refList []metav1.OwnerReference, apiVersion string, kinds []string
// This function is greatly more efficient than GetCRDWithContract and should be preferred in most cases.
func GetGVKMetadata(ctx context.Context, c client.Client, gvk schema.GroupVersionKind) (*metav1.PartialObjectMetadata, error) {
meta := &metav1.PartialObjectMetadata{}
meta.SetName(fmt.Sprintf("%s.%s", flect.Pluralize(strings.ToLower(gvk.Kind)), gvk.Group))
meta.SetName(contract.CalculateCRDName(gvk.Group, gvk.Kind))
meta.SetGroupVersionKind(apiextensionsv1.SchemeGroupVersion.WithKind("CustomResourceDefinition"))
if err := c.Get(ctx, client.ObjectKeyFromObject(meta), meta); err != nil {
return meta, errors.Wrap(err, "failed to retrieve metadata from GVK resource")
Expand Down

0 comments on commit ded9239

Please sign in to comment.