Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ dist/

/kubeflex/

# Code generator tools (repo-local)
hack/tools/bin/

# Ignore generated CRDs for the chart
chart/crds/controlplanes.yaml
chart/crds/postcreatehooks.yaml
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,14 @@ manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and Cust
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."

.PHONY: generate-clients
generate-clients: ## Generate typed clientset, informers, and listers using Kubernetes code-generator.
./hack/update-codegen.sh

.PHONY: verify-codegen
verify-codegen: ## Verify that generated code is up-to-date.
./hack/verify-codegen.sh

.PHONY: fmt
fmt: ## Run go fmt against code.
go fmt ./...
Expand Down
2 changes: 2 additions & 0 deletions api/v1alpha1/controlplane_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ type ControlPlaneStatus struct {
}

// ControlPlane is the Schema for the controlplanes API
// +genclient
// +genclient:nonNamespaced
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="SYNCED",type="string",JSONPath=".status.conditions[?(@.type=='Synced')].status"
Expand Down
21 changes: 21 additions & 0 deletions api/v1alpha1/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
Copyright 2023 The KubeStellar 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.
*/

// +k8s:deepcopy-gen=package
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"fixed" means that the removal was undone, right? Why was the removal undone?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the confusion. Here's what happened:

  1. First commit: I removed both +k8s:deepcopy-gen=package AND +kubebuilder:object:generate=true
  2. This caused the CI build to fail with errors like "DeepCopyInto undefined"
  3. Second commit: I restored only +kubebuilder:object:generate=true because it's needed for controller-gen to generate deepcopy methods

Current state of doc.go:

// +kubebuilder:object:generate=true
// +groupName=tenancy.kflex.kubestellar.org

The +k8s:deepcopy-gen=package marker is removed as you requested. The +kubebuilder:object:generate=true marker remains because without it, controller-gen doesn't generate the DeepCopyInto() methods that the code depends on.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: Should I follow the kubestellar pattern exactly and remove the kubebuilder marker too? If so, how does kubestellar generate its deepcopy methods?

// +groupName=tenancy.kflex.kubestellar.org

// Package v1alpha1 contains API Schema definitions for the tenancy v1alpha1 API group
package v1alpha1
4 changes: 3 additions & 1 deletion api/v1alpha1/postcreatehook_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ type PostCreateHookStatus struct {
SecretRef *SecretReference `json:"secretRef,omitempty"`
}

// PostCreateHook is the Schema for the controlplanes API
// PostCreateHook is the Schema for the postcreatehooks API
// +genclient
// +genclient:nonNamespaced
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="SYNCED",type="string",JSONPath=".status.conditions[?(@.type=='Synced')].status"
Expand Down
51 changes: 51 additions & 0 deletions api/v1alpha1/register.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
Copyright 2023 The KubeStellar 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 v1alpha1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)

// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: "tenancy.kflex.kubestellar.org", Version: "v1alpha1"}

// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}

var (
// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
localSchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)

// AddToSchemeInCore is a common registration function for mapping types to the scheme
AddToSchemeInCore = localSchemeBuilder.AddToScheme
)

// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&ControlPlane{},
&ControlPlaneList{},
&PostCreateHook{},
&PostCreateHookList{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}
54 changes: 54 additions & 0 deletions docs/code-generation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Code Generation Guide

This document describes how to generate and maintain typed Kubernetes clients for the kubeflex CRDs.

## Overview

kubeflex uses the standard Kubernetes code-generator tools to generate:

- **Typed Clientsets**: Strongly-typed clients for interacting with CRDs via the Kubernetes API
- **Informers**: SharedInformerFactory for watching CRD resources with local caching
- **Listers**: Typed listers for reading CRD resources from informer caches

## Prerequisites

- Go 1.24+ installed
- Access to `k8s.io/code-generator` (automatically fetched during generation)

## Generating Code

To regenerate all typed clients, informers, and listers:

```bash
make generate-clients
```

This runs `hack/update-codegen.sh`, which invokes the Kubernetes code-generator tools.

## Verifying Generated Code

To verify that generated code is up-to-date:

```bash
make verify-codegen
```

This is useful in CI pipelines to ensure generated code is committed after API changes.

## When to Regenerate

Regenerate typed clients when API types in `api/v1alpha1/` are modified.

## Troubleshooting

### Code generation fails

Ensure you have the correct version of Go installed and that `k8s.io/code-generator` is accessible.

### Generated code doesn't compile

Check that:
1. API types have proper markers (`+k8s:deepcopy-gen=package`, `+groupName=...`, `+genclient`)
2. Types are registered with the scheme in `register.go`
3. All required `init()` functions are present

78 changes: 78 additions & 0 deletions hack/update-codegen.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/usr/bin/env bash

# Copyright 2023 The KubeStellar 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 script generates typed clients, informers, and listers for the
# kubeflex CRDs using the Kubernetes code-generator.

set -o errexit
set -o nounset
set -o pipefail

REPO_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
cd "${REPO_ROOT}"

# Module and package configuration
MODULE="github.com/kubestellar/kubeflex"
API_PKG="api"
OUTPUT_PKG="pkg/generated"

# Determine code-generator version from go.mod
CODEGEN_VERSION=$(go list -m -f '{{.Version}}' k8s.io/code-generator)

# Tools directory (repo-local, not GOPATH)
TOOLS_BIN_DIR="${REPO_ROOT}/hack/tools/bin"
mkdir -p "${TOOLS_BIN_DIR}"
TOOLS_BIN_DIR="$(cd "${TOOLS_BIN_DIR}" && pwd)"

# Install code generators to repo-local directory
echo "Installing code-generator tools to ${TOOLS_BIN_DIR}..."
GOBIN="${TOOLS_BIN_DIR}" go install "k8s.io/code-generator/cmd/client-gen@${CODEGEN_VERSION}"
GOBIN="${TOOLS_BIN_DIR}" go install "k8s.io/code-generator/cmd/lister-gen@${CODEGEN_VERSION}"
GOBIN="${TOOLS_BIN_DIR}" go install "k8s.io/code-generator/cmd/informer-gen@${CODEGEN_VERSION}"

# Header file for generated code
BOILERPLATE="${REPO_ROOT}/hack/boilerplate.go.txt"

# Delete entire generated code tree for reproducibility
echo "Clearing ${OUTPUT_PKG}..."
rm -rf "${REPO_ROOT}/${OUTPUT_PKG}"

echo "Generating clientset..."
"${TOOLS_BIN_DIR}/client-gen" \
--clientset-name "versioned" \
--input-base "" \
--input "${MODULE}/${API_PKG}/v1alpha1" \
--output-dir "${REPO_ROOT}/${OUTPUT_PKG}/clientset" \
--output-pkg "${MODULE}/${OUTPUT_PKG}/clientset" \
--go-header-file "${BOILERPLATE}"

echo "Generating listers..."
"${TOOLS_BIN_DIR}/lister-gen" \
--output-dir "${REPO_ROOT}/${OUTPUT_PKG}/listers" \
--output-pkg "${MODULE}/${OUTPUT_PKG}/listers" \
--go-header-file "${BOILERPLATE}" \
"${MODULE}/${API_PKG}/v1alpha1"

echo "Generating informers..."
"${TOOLS_BIN_DIR}/informer-gen" \
--versioned-clientset-package "${MODULE}/${OUTPUT_PKG}/clientset/versioned" \
--listers-package "${MODULE}/${OUTPUT_PKG}/listers" \
--output-dir "${REPO_ROOT}/${OUTPUT_PKG}/informers" \
--output-pkg "${MODULE}/${OUTPUT_PKG}/informers" \
--go-header-file "${BOILERPLATE}" \
"${MODULE}/${API_PKG}/v1alpha1"

echo "Code generation complete."
98 changes: 98 additions & 0 deletions hack/verify-codegen.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#!/usr/bin/env bash

# Copyright 2023 The KubeStellar 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 script verifies that the generated code is up-to-date.

set -o errexit
set -o nounset
set -o pipefail

REPO_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
cd "${REPO_ROOT}"

# Create temporary directory for generated code
DIFFROOT="${REPO_ROOT}/pkg/generated"
TMP_DIFFROOT="$(mktemp -d)"
trap 'rm -rf "${TMP_DIFFROOT}"' EXIT

# Copy current generated code to temp
if [[ -d "${DIFFROOT}" ]]; then
cp -a "${DIFFROOT}/." "${TMP_DIFFROOT}"
fi

# Module and package configuration
MODULE="github.com/kubestellar/kubeflex"
API_PKG="api"
OUTPUT_PKG="pkg/generated"

# Determine code-generator version from go.mod
CODEGEN_VERSION=$(go list -m -f '{{.Version}}' k8s.io/code-generator)

# Tools directory (repo-local, not GOPATH)
TOOLS_BIN_DIR="${REPO_ROOT}/hack/tools/bin"
mkdir -p "${TOOLS_BIN_DIR}"
TOOLS_BIN_DIR="$(cd "${TOOLS_BIN_DIR}" && pwd)"

# Install code generators to repo-local directory
echo "Installing code-generator tools to ${TOOLS_BIN_DIR}..."
GOBIN="${TOOLS_BIN_DIR}" go install "k8s.io/code-generator/cmd/client-gen@${CODEGEN_VERSION}"
GOBIN="${TOOLS_BIN_DIR}" go install "k8s.io/code-generator/cmd/lister-gen@${CODEGEN_VERSION}"
GOBIN="${TOOLS_BIN_DIR}" go install "k8s.io/code-generator/cmd/informer-gen@${CODEGEN_VERSION}"

# Header file for generated code
BOILERPLATE="${REPO_ROOT}/hack/boilerplate.go.txt"

# Delete entire generated code tree for reproducibility
echo "Clearing ${OUTPUT_PKG}..."
rm -rf "${REPO_ROOT}/${OUTPUT_PKG}"

echo "Generating clientset..."
"${TOOLS_BIN_DIR}/client-gen" \
--clientset-name "versioned" \
--input-base "" \
--input "${MODULE}/${API_PKG}/v1alpha1" \
--output-dir "${REPO_ROOT}/${OUTPUT_PKG}/clientset" \
--output-pkg "${MODULE}/${OUTPUT_PKG}/clientset" \
--go-header-file "${BOILERPLATE}"

echo "Generating listers..."
"${TOOLS_BIN_DIR}/lister-gen" \
--output-dir "${REPO_ROOT}/${OUTPUT_PKG}/listers" \
--output-pkg "${MODULE}/${OUTPUT_PKG}/listers" \
--go-header-file "${BOILERPLATE}" \
"${MODULE}/${API_PKG}/v1alpha1"

echo "Generating informers..."
"${TOOLS_BIN_DIR}/informer-gen" \
--versioned-clientset-package "${MODULE}/${OUTPUT_PKG}/clientset/versioned" \
--listers-package "${MODULE}/${OUTPUT_PKG}/listers" \
--output-dir "${REPO_ROOT}/${OUTPUT_PKG}/informers" \
--output-pkg "${MODULE}/${OUTPUT_PKG}/informers" \
--go-header-file "${BOILERPLATE}" \
"${MODULE}/${API_PKG}/v1alpha1"

echo "Verifying generated code is up-to-date..."

# Check for differences
if ! diff -Naupr "${TMP_DIFFROOT}" "${DIFFROOT}"; then
echo ""
echo "Generated code is out of date. Please run:"
echo " hack/update-codegen.sh"
echo ""
exit 1
fi

echo "Generated code is up-to-date."
Loading