Skip to content

Commit

Permalink
Merge pull request #5917 from fabriziopandini/move-controllers-to-int…
Browse files Browse the repository at this point in the history
…ernal-part3

🌱 Move controllers to internal - part3
  • Loading branch information
k8s-ci-robot authored Jan 7, 2022
2 parents 728619c + 626ab4d commit c337ecc
Show file tree
Hide file tree
Showing 71 changed files with 713 additions and 304 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ As of today there are following OWNERS files/Owner groups defining sub areas:
- [Clusterctl](cmd/clusterctl)
- [kubeadm Bootstrap Provider (CABPK)](bootstrap/kubeadm)
- [kubeadm Control Plane Provider (KCP)](controlplane/kubeadm)
- [Cluster Managed topologies, ClusterClass](controllers/topology)
- [Cluster Managed topologies, ClusterClass](internal/controllers/topology)
- [Infrastructure Provider Docker (CAPD)](test/infrastructure/docker)
- [Test](test)
- [Test Framework](test/framework)
Expand Down
1 change: 0 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ generate-manifests: $(addprefix generate-manifests-,$(ALL_GENERATE_MODULES)) ##
generate-manifests-core: $(CONTROLLER_GEN) $(KUSTOMIZE) ## Generate manifests e.g. CRD, RBAC etc. for core
$(CONTROLLER_GEN) \
paths=./api/... \
paths=./controllers/... \
paths=./internal/controllers/... \
paths=./internal/webhooks/... \
paths=./$(EXP_DIR)/api/... \
Expand Down
90 changes: 90 additions & 0 deletions controllers/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,14 @@ import (

"sigs.k8s.io/cluster-api/controllers/remote"
clustercontroller "sigs.k8s.io/cluster-api/internal/controllers/cluster"
clusterclasscontroller "sigs.k8s.io/cluster-api/internal/controllers/clusterclass"
machinecontroller "sigs.k8s.io/cluster-api/internal/controllers/machine"
machinedeploymentcontroller "sigs.k8s.io/cluster-api/internal/controllers/machinedeployment"
machinehealthcheckcontroller "sigs.k8s.io/cluster-api/internal/controllers/machinehealthcheck"
machinesetcontroller "sigs.k8s.io/cluster-api/internal/controllers/machineset"
clustertopologycontroller "sigs.k8s.io/cluster-api/internal/controllers/topology/cluster"
machinedeploymenttopologycontroller "sigs.k8s.io/cluster-api/internal/controllers/topology/machinedeployment"
machinesettopologycontroller "sigs.k8s.io/cluster-api/internal/controllers/topology/machineset"
)

// Following types provides access to reconcilers implemented in internal/controllers, thus
Expand Down Expand Up @@ -121,3 +125,89 @@ func (r *MachineHealthCheckReconciler) SetupWithManager(ctx context.Context, mgr
WatchFilterValue: r.WatchFilterValue,
}).SetupWithManager(ctx, mgr, options)
}

// ClusterTopologyReconciler reconciles a managed topology for a Cluster object.
type ClusterTopologyReconciler struct {
Client client.Client
// APIReader is used to list MachineSets directly via the API server to avoid
// race conditions caused by an outdated cache.
APIReader client.Reader

// WatchFilterValue is the label value used to filter events prior to reconciliation.
WatchFilterValue string

// UnstructuredCachingClient provides a client that forces caching of unstructured objects,
// thus allowing to optimize reads for templates or provider specific objects in a managed topology.
UnstructuredCachingClient client.Client
}

func (r *ClusterTopologyReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
return (&clustertopologycontroller.Reconciler{
Client: r.Client,
APIReader: r.APIReader,
UnstructuredCachingClient: r.UnstructuredCachingClient,
WatchFilterValue: r.WatchFilterValue,
}).SetupWithManager(ctx, mgr, options)
}

// MachineDeploymentTopologyReconciler deletes referenced templates during deletion of topology-owned MachineDeployments.
// The templates are only deleted, if they are not used in other MachineDeployments or MachineSets which are not in deleting state,
// i.e. the templates would otherwise be orphaned after the MachineDeployment deletion completes.
// Note: To achieve this the cluster topology controller sets a finalizer to hook into the MachineDeployment deletions.
type MachineDeploymentTopologyReconciler struct {
Client client.Client
// APIReader is used to list MachineSets directly via the API server to avoid
// race conditions caused by an outdated cache.
APIReader client.Reader
WatchFilterValue string
}

func (r *MachineDeploymentTopologyReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
return (&machinedeploymenttopologycontroller.Reconciler{
Client: r.Client,
APIReader: r.APIReader,
WatchFilterValue: r.WatchFilterValue,
}).SetupWithManager(ctx, mgr, options)
}

// MachineSetTopologyReconciler deletes referenced templates during deletion of topology-owned MachineSets.
// The templates are only deleted, if they are not used in other MachineDeployments or MachineSets which are not in deleting state,
// i.e. the templates would otherwise be orphaned after the MachineSet deletion completes.
// Note: To achieve this the reconciler sets a finalizer to hook into the MachineSet deletions.
type MachineSetTopologyReconciler struct {
Client client.Client
// APIReader is used to list MachineSets directly via the API server to avoid
// race conditions caused by an outdated cache.
APIReader client.Reader
WatchFilterValue string
}

func (r *MachineSetTopologyReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
return (&machinesettopologycontroller.Reconciler{
Client: r.Client,
APIReader: r.APIReader,
WatchFilterValue: r.WatchFilterValue,
}).SetupWithManager(ctx, mgr, options)
}

// ClusterClassReconciler reconciles the ClusterClass object.
type ClusterClassReconciler struct {
Client client.Client
APIReader client.Reader

// WatchFilterValue is the label value used to filter events prior to reconciliation.
WatchFilterValue string

// UnstructuredCachingClient provides a client that forces caching of unstructured objects,
// thus allowing to optimize reads for templates or provider specific objects.
UnstructuredCachingClient client.Client
}

func (r *ClusterClassReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
return (&clusterclasscontroller.Reconciler{
Client: r.Client,
APIReader: r.APIReader,
UnstructuredCachingClient: r.UnstructuredCachingClient,
WatchFilterValue: r.WatchFilterValue,
}).SetupWithManager(ctx, mgr, options)
}
2 changes: 1 addition & 1 deletion docs/book/src/developer/providers/v1.0-to-v1.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ are kept in sync with the versions used by `sigs.k8s.io/controller-runtime`.
* Some controllers have been moved to internal to reduce their API surface. We now only
surface what is necessary, e.g. the reconciler and the `SetupWithManager` func:
* [bootstrap/kubeadm/controllers](https://github.com/kubernetes-sigs/cluster-api/pull/5493)
* controllers [part1](https://github.com/kubernetes-sigs/cluster-api/pull/5899) [part2](https://github.com/kubernetes-sigs/cluster-api/pull/5913)
* controllers [part1](https://github.com/kubernetes-sigs/cluster-api/pull/5899) [part2](https://github.com/kubernetes-sigs/cluster-api/pull/5913) [part3](https://github.com/kubernetes-sigs/cluster-api/pull/5917)
* [exp/addons/controllers](https://github.com/kubernetes-sigs/cluster-api/pull/5639)
* [test/infrastructure/docker/controllers](https://github.com/kubernetes-sigs/cluster-api/pull/5595)
* [test/infrastructure/docker/exp/controllers](https://github.com/kubernetes-sigs/cluster-api/pull/5690)
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
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 topology
package clusterclass

import (
"context"
Expand All @@ -32,7 +32,7 @@ import (

clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/controllers/external"
tlog "sigs.k8s.io/cluster-api/controllers/topology/internal/log"
tlog "sigs.k8s.io/cluster-api/internal/log"
"sigs.k8s.io/cluster-api/util/annotations"
utilconversion "sigs.k8s.io/cluster-api/util/conversion"
"sigs.k8s.io/cluster-api/util/patch"
Expand All @@ -43,8 +43,8 @@ import (
// +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=clusterclasses,verbs=get;list;watch;update;patch
// +kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions,verbs=get;list;watch

// ClusterClassReconciler reconciles the ClusterClass object.
type ClusterClassReconciler struct {
// Reconciler reconciles the ClusterClass object.
type Reconciler struct {
Client client.Client
APIReader client.Reader

Expand All @@ -56,7 +56,7 @@ type ClusterClassReconciler struct {
UnstructuredCachingClient client.Client
}

func (r *ClusterClassReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
func (r *Reconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
err := ctrl.NewControllerManagedBy(mgr).
For(&clusterv1.ClusterClass{}).
Named("topology/clusterclass").
Expand All @@ -69,7 +69,7 @@ func (r *ClusterClassReconciler) SetupWithManager(ctx context.Context, mgr ctrl.
return nil
}

func (r *ClusterClassReconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Result, reterr error) {
func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Result, reterr error) {
log := ctrl.LoggerFrom(ctx)

clusterClass := &clusterv1.ClusterClass{}
Expand Down Expand Up @@ -109,7 +109,7 @@ func (r *ClusterClassReconciler) Reconcile(ctx context.Context, req ctrl.Request
return r.reconcile(ctx, clusterClass)
}

func (r *ClusterClassReconciler) reconcile(ctx context.Context, clusterClass *clusterv1.ClusterClass) (ctrl.Result, error) {
func (r *Reconciler) reconcile(ctx context.Context, clusterClass *clusterv1.ClusterClass) (ctrl.Result, error) {
// Collect all the reference from the ClusterClass to templates.
refs := []*corev1.ObjectReference{}

Expand Down Expand Up @@ -153,7 +153,7 @@ func (r *ClusterClassReconciler) reconcile(ctx context.Context, clusterClass *cl
return ctrl.Result{}, kerrors.NewAggregate(errs)
}

func (r *ClusterClassReconciler) reconcileExternal(ctx context.Context, clusterClass *clusterv1.ClusterClass, ref *corev1.ObjectReference, setOwnerRef bool) error {
func (r *Reconciler) reconcileExternal(ctx context.Context, clusterClass *clusterv1.ClusterClass, ref *corev1.ObjectReference, setOwnerRef bool) error {
log := ctrl.LoggerFrom(ctx)

if err := utilconversion.UpdateReferenceAPIContract(ctx, r.Client, r.APIReader, ref); err != nil {
Expand Down
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 topology
package clusterclass

import (
"context"
Expand All @@ -29,9 +29,9 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"

clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
tlog "sigs.k8s.io/cluster-api/controllers/topology/internal/log"
"sigs.k8s.io/cluster-api/feature"
"sigs.k8s.io/cluster-api/internal/builder"
tlog "sigs.k8s.io/cluster-api/internal/log"
)

func TestClusterClassReconciler_reconcile(t *testing.T) {
Expand Down
20 changes: 20 additions & 0 deletions internal/controllers/clusterclass/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
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 clusterclass implements the clusterclass controller.
// NOTE: It is required to enable the ClusterTopology
// feature gate flag to activate managed topologies support.
package clusterclass
113 changes: 113 additions & 0 deletions internal/controllers/clusterclass/suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
Copyright 2021 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 clusterclass

import (
"context"
"fmt"
"os"
"testing"
"time"

. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"

clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/api/v1beta1/index"
"sigs.k8s.io/cluster-api/internal/envtest"
)

var (
ctx = ctrl.SetupSignalHandler()
fakeScheme = runtime.NewScheme()
env *envtest.Environment
)

func init() {
_ = clientgoscheme.AddToScheme(fakeScheme)
_ = clusterv1.AddToScheme(fakeScheme)
_ = apiextensionsv1.AddToScheme(fakeScheme)
}
func TestMain(m *testing.M) {
setupIndexes := func(ctx context.Context, mgr ctrl.Manager) {
if err := index.AddDefaultIndexes(ctx, mgr); err != nil {
panic(fmt.Sprintf("unable to setup index: %v", err))
}
}
setupReconcilers := func(ctx context.Context, mgr ctrl.Manager) {
unstructuredCachingClient, err := client.NewDelegatingClient(
client.NewDelegatingClientInput{
// Use the default client for write operations.
Client: mgr.GetClient(),
// For read operations, use the same cache used by all the controllers but ensure
// unstructured objects will be also cached (this does not happen with the default client).
CacheReader: mgr.GetCache(),
CacheUnstructured: true,
},
)
if err != nil {
panic(fmt.Sprintf("unable to create unstructuredCachineClient: %v", err))
}
if err := (&Reconciler{
Client: mgr.GetClient(),
APIReader: mgr.GetAPIReader(),
UnstructuredCachingClient: unstructuredCachingClient,
}).SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: 5}); err != nil {
panic(fmt.Sprintf("unable to create clusterclass reconciler: %v", err))
}
}
SetDefaultEventuallyPollingInterval(100 * time.Millisecond)
SetDefaultEventuallyTimeout(30 * time.Second)
os.Exit(envtest.Run(ctx, envtest.RunInput{
M: m,
ManagerUncachedObjs: []client.Object{},
SetupEnv: func(e *envtest.Environment) { env = e },
SetupIndexes: setupIndexes,
SetupReconcilers: setupReconcilers,
}))
}

func ownerReferenceTo(obj client.Object) *metav1.OwnerReference {
return &metav1.OwnerReference{
Kind: obj.GetObjectKind().GroupVersionKind().Kind,
Name: obj.GetName(),
UID: obj.GetUID(),
APIVersion: obj.GetObjectKind().GroupVersionKind().GroupVersion().String(),
}
}

// referenceExistsWithCorrectKindAndAPIVersion asserts that the passed ObjectReference is not nil and that it has the correct kind and apiVersion.
func referenceExistsWithCorrectKindAndAPIVersion(reference *corev1.ObjectReference, kind string, apiVersion schema.GroupVersion) error {
if reference == nil {
return fmt.Errorf("object reference passed was nil")
}
if reference.Kind != kind {
return fmt.Errorf("object reference kind %v does not match expected %v", reference.Kind, kind)
}
if reference.APIVersion != apiVersion.String() {
return fmt.Errorf("apiVersion %v does not match expected %v", reference.APIVersion, apiVersion.String())
}
return nil
}
File renamed without changes.
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 topology
package cluster

import (
"context"
Expand All @@ -23,14 +23,14 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"

clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
tlog "sigs.k8s.io/cluster-api/controllers/topology/internal/log"
"sigs.k8s.io/cluster-api/controllers/topology/internal/scope"
"sigs.k8s.io/cluster-api/internal/controllers/topology/cluster/scope"
tlog "sigs.k8s.io/cluster-api/internal/log"
)

// getBlueprint gets a ClusterBlueprint with the ClusterClass and the referenced templates to be used for a managed Cluster topology.
// It also converts and patches all ObjectReferences in ClusterClass and ControlPlane to the latest apiVersion of the current contract.
// NOTE: This function assumes that cluster.Spec.Topology.Class is set.
func (r *ClusterReconciler) getBlueprint(ctx context.Context, cluster *clusterv1.Cluster) (_ *scope.ClusterBlueprint, reterr error) {
func (r *Reconciler) getBlueprint(ctx context.Context, cluster *clusterv1.Cluster) (_ *scope.ClusterBlueprint, reterr error) {
blueprint := &scope.ClusterBlueprint{
Topology: cluster.Spec.Topology,
ClusterClass: &clusterv1.ClusterClass{},
Expand Down
Loading

0 comments on commit c337ecc

Please sign in to comment.