Skip to content

Commit

Permalink
Expose Cluster Control Plane ref through cluster scope
Browse files Browse the repository at this point in the history
Signed-off-by: Vince Prignano <[email protected]>
  • Loading branch information
vincepri committed Feb 27, 2024
1 parent 9b8a4a7 commit 591e196
Show file tree
Hide file tree
Showing 14 changed files with 79 additions and 54 deletions.
28 changes: 1 addition & 27 deletions controllers/awsmachine_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import (
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
kerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/client-go/tools/record"
"k8s.io/klog/v2"
Expand Down Expand Up @@ -61,7 +60,6 @@ import (
"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud/services/userdata"
"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/logger"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/controllers/external"
capierrors "sigs.k8s.io/cluster-api/errors"
"sigs.k8s.io/cluster-api/util"
"sigs.k8s.io/cluster-api/util/annotations"
Expand Down Expand Up @@ -147,6 +145,7 @@ func (r *AWSMachineReconciler) getObjectStoreService(scope scope.S3Scope) servic

// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=awsmachines,verbs=get;list;watch;update;patch;delete
// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=awsmachines/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=controlplane.cluster.x-k8s.io,resources=*,verbs=get;list;watch
// +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=machines;machines/status,verbs=get;list;watch
// +kubebuilder:rbac:groups="",resources=secrets;,verbs=get;list;watch
// +kubebuilder:rbac:groups="",resources=namespaces,verbs=get;list;watch
Expand Down Expand Up @@ -202,16 +201,10 @@ func (r *AWSMachineReconciler) Reconcile(ctx context.Context, req ctrl.Request)

infrav1.SetDefaults_AWSMachineSpec(&awsMachine.Spec)

cp, err := r.getControlPlane(ctx, log, cluster)
if err != nil {
return ctrl.Result{}, err
}

// Create the machine scope
machineScope, err := scope.NewMachineScope(scope.MachineScopeParams{
Client: r.Client,
Cluster: cluster,
ControlPlane: cp,
Machine: machine,
InfraCluster: infraCluster,
AWSMachine: awsMachine,
Expand Down Expand Up @@ -1225,22 +1218,3 @@ func (r *AWSMachineReconciler) ensureInstanceMetadataOptions(ec2svc services.EC2

return ec2svc.ModifyInstanceMetadataOptions(instance.ID, machine.Spec.InstanceMetadataOptions)
}

// +kubebuilder:rbac:groups=controlplane.cluster.x-k8s.io,resources=*,verbs=get;list;watch

func (r *AWSMachineReconciler) getControlPlane(ctx context.Context, log *logger.Logger, cluster *clusterv1.Cluster) (*unstructured.Unstructured, error) {
var ns string

if ns = cluster.Spec.ControlPlaneRef.Namespace; ns == "" {
ns = cluster.Namespace
}

controlPlane, err := external.Get(ctx, r.Client, cluster.Spec.ControlPlaneRef, ns)
if err != nil {
log.Error(err, "unable to get ControlPlane referenced in the given cluster", "cluster", fmt.Sprintf("%s/%s", cluster.Namespace, cluster.Name))

return nil, err
}

return controlPlane, nil
}
2 changes: 0 additions & 2 deletions controllers/awsmachine_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import (
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/client-go/tools/record"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -418,7 +417,6 @@ func getMachineScope(cs *scope.ClusterScope, awsMachine *infrav1.AWSMachine) (*s
InfrastructureReady: true,
},
},
ControlPlane: &unstructured.Unstructured{},
Machine: &clusterv1.Machine{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Expand Down
3 changes: 0 additions & 3 deletions controllers/awsmachine_controller_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import (
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/record"
"k8s.io/klog/v2"
Expand Down Expand Up @@ -131,7 +130,6 @@ func TestAWSMachineReconciler(t *testing.T) {
},
},
InfraCluster: cs,
ControlPlane: &unstructured.Unstructured{},
AWSMachine: awsMachine,
},
)
Expand Down Expand Up @@ -160,7 +158,6 @@ func TestAWSMachineReconciler(t *testing.T) {
InfrastructureReady: true,
},
},
ControlPlane: &unstructured.Unstructured{},
Machine: &clusterv1.Machine{
Spec: clusterv1.MachineSpec{
ClusterName: "capi-test",
Expand Down
3 changes: 3 additions & 0 deletions pkg/cloud/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package cloud

import (
awsclient "github.com/aws/aws-sdk-go/aws/client"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"sigs.k8s.io/controller-runtime/pkg/client"

infrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
Expand Down Expand Up @@ -67,6 +68,8 @@ type ClusterScoper interface {

// Cluster returns the cluster object.
ClusterObj() ClusterObject
// UnstructuredControlPlane returns the unstructured control plane object.
UnstructuredControlPlane() (*unstructured.Unstructured, error)

// IdentityRef returns the AWS infrastructure cluster identityRef.
IdentityRef() *infrav1.AWSIdentityReference
Expand Down
7 changes: 7 additions & 0 deletions pkg/cloud/scope/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (

awsclient "github.com/aws/aws-sdk-go/aws/client"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/klog/v2"
"sigs.k8s.io/controller-runtime/pkg/client"

Expand Down Expand Up @@ -395,3 +396,9 @@ func (s *ClusterScope) Partition() string {
func (s *ClusterScope) AdditionalControlPlaneIngressRules() []infrav1.IngressRule {
return s.AWSCluster.Spec.NetworkSpec.DeepCopy().AdditionalControlPlaneIngressRules
}

// UnstructuredControlPlane returns the unstructured object for the control plane, if any.
// When the reference is not set, it returns an empty object.
func (s *ClusterScope) UnstructuredControlPlane() (*unstructured.Unstructured, error) {
return getUnstructuredControlPlane(context.TODO(), s.client, s.Cluster)
}
23 changes: 15 additions & 8 deletions pkg/cloud/scope/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (

"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog/v2"
"k8s.io/utils/ptr"
Expand All @@ -44,7 +43,6 @@ import (
type MachineScopeParams struct {
Client client.Client
Logger *logger.Logger
ControlPlane *unstructured.Unstructured
Cluster *clusterv1.Cluster
Machine *clusterv1.Machine
InfraCluster EC2Scope
Expand All @@ -69,9 +67,6 @@ func NewMachineScope(params MachineScopeParams) (*MachineScope, error) {
if params.InfraCluster == nil {
return nil, errors.New("aws cluster is required when creating a MachineScope")
}
if params.ControlPlane == nil {
return nil, errors.New("cluster control plane is required when creating a MachineScope")
}

if params.Logger == nil {
log := klog.Background()
Expand All @@ -86,7 +81,6 @@ func NewMachineScope(params MachineScopeParams) (*MachineScope, error) {
Logger: *params.Logger,
client: params.Client,
patchHelper: helper,
ControlPlane: params.ControlPlane,
Cluster: params.Cluster,
Machine: params.Machine,
InfraCluster: params.InfraCluster,
Expand All @@ -102,7 +96,6 @@ type MachineScope struct {

Cluster *clusterv1.Cluster
Machine *clusterv1.Machine
ControlPlane *unstructured.Unstructured
InfraCluster EC2Scope
AWSMachine *infrav1.AWSMachine
}
Expand Down Expand Up @@ -377,8 +370,22 @@ func (m *MachineScope) IsEKSManaged() bool {
return m.InfraCluster.InfraCluster().GetObjectKind().GroupVersionKind().Kind == ekscontrolplanev1.AWSManagedControlPlaneKind
}

// IsControlPlaneExternallyManaged checks if the control plane is externally managed.
//
// This is determined by the kind of the control plane object (EKS for example),
// or if the control plane referenced object is reporting as externally managed.
func (m *MachineScope) IsControlPlaneExternallyManaged() bool {
return util.IsExternalManagedControlPlane(m.ControlPlane)
if m.IsEKSManaged() {
return true
}

// Check if the control plane is externally managed.
u, err := m.InfraCluster.UnstructuredControlPlane()
if err != nil {
m.Error(err, "failed to get unstructured control plane")
return false
}
return util.IsExternalManagedControlPlane(u)
}

// IsExternallyManaged checks if the machine is externally managed.
Expand Down
11 changes: 4 additions & 7 deletions pkg/cloud/scope/machine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -133,8 +132,7 @@ func setupMachineScope() (*MachineScope, error) {
InfraCluster: &ClusterScope{
AWSCluster: awsCluster,
},
ControlPlane: &unstructured.Unstructured{},
AWSMachine: awsMachine,
AWSMachine: awsMachine,
},
)
}
Expand Down Expand Up @@ -225,10 +223,9 @@ func TestGetRawBootstrapDataWithFormat(t *testing.T) {

machineScope, err := NewMachineScope(
MachineScopeParams{
Client: client,
Machine: machine,
Cluster: cluster,
ControlPlane: &unstructured.Unstructured{},
Client: client,
Machine: machine,
Cluster: cluster,
InfraCluster: &ClusterScope{
AWSCluster: awsCluster,
},
Expand Down
7 changes: 7 additions & 0 deletions pkg/cloud/scope/managedcontrolplane.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog/v2"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -440,3 +441,9 @@ func (s *ManagedControlPlaneScope) Partition() string {
func (s *ManagedControlPlaneScope) AdditionalControlPlaneIngressRules() []infrav1.IngressRule {
return nil
}

// UnstructuredControlPlane returns the unstructured object for the control plane, if any.
// When the reference is not set, it returns an empty object.
func (s *ManagedControlPlaneScope) UnstructuredControlPlane() (*unstructured.Unstructured, error) {
return getUnstructuredControlPlane(context.TODO(), s.Client, s.Cluster)
}
26 changes: 26 additions & 0 deletions pkg/cloud/scope/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,18 @@ limitations under the License.
package scope

import (
"context"
"fmt"

"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"sigs.k8s.io/controller-runtime/pkg/client"

infrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
expinfrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/exp/api/v1beta2"
"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/logger"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/controllers/external"
)

var (
Expand Down Expand Up @@ -127,3 +132,24 @@ func (p *defaultSubnetPlacementStrategy) getSubnetsForAZs(azs []string, controlP

return subnetIDs, nil
}

// getUnstructuredControlPlane returns the unstructured object for the control plane, if any.
// When the reference is not set, it returns an empty object.
func getUnstructuredControlPlane(ctx context.Context, client client.Client, cluster *clusterv1.Cluster) (*unstructured.Unstructured, error) {
if cluster.Spec.ControlPlaneRef == nil {
// If the control plane ref is not set, return an empty object.
// Not having a control plane ref is valid given API contracts.
return &unstructured.Unstructured{}, nil
}

namespace := cluster.Spec.ControlPlaneRef.Namespace
if namespace == "" {
namespace = cluster.Namespace
}

u, err := external.Get(ctx, client, cluster.Spec.ControlPlaneRef, namespace)
if err != nil {
return nil, errors.Wrapf(err, "failed to retrieve control plane object %s/%s", cluster.Spec.ControlPlaneRef.Namespace, cluster.Spec.ControlPlaneRef.Name)
}
return u, nil
}
1 change: 0 additions & 1 deletion pkg/cloud/services/ec2/instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ func (s *Service) CreateInstance(scope *scope.MachineScope, userData []byte, use

if !scope.IsControlPlaneExternallyManaged() && !scope.IsExternallyManaged() && !scope.IsEKSManaged() && s.scope.Network().APIServerELB.DNSName == "" {
record.Eventf(s.scope.InfraCluster(), "FailedCreateInstance", "Failed to run controlplane, APIServer ELB not available")

return nil, awserrors.NewFailedDependency("failed to run controlplane, APIServer ELB not available")
}

Expand Down
2 changes: 0 additions & 2 deletions pkg/cloud/services/ec2/instances_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import (
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
Expand Down Expand Up @@ -4036,7 +4035,6 @@ func TestCreateInstance(t *testing.T) {
machineScope, err := scope.NewMachineScope(scope.MachineScopeParams{
Client: client,
Cluster: cluster,
ControlPlane: &unstructured.Unstructured{},
Machine: machine,
AWSMachine: awsMachine,
InfraCluster: clusterScope,
Expand Down
2 changes: 0 additions & 2 deletions pkg/cloud/services/secretsmanager/secret_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"github.com/golang/mock/gomock"
. "github.com/onsi/gomega"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
Expand Down Expand Up @@ -281,7 +280,6 @@ func getClusterScope(client client.Client) (*scope.ClusterScope, error) {
func getMachineScope(client client.Client, clusterScope *scope.ClusterScope) (*scope.MachineScope, error) {
return scope.NewMachineScope(scope.MachineScopeParams{
Client: client,
ControlPlane: &unstructured.Unstructured{},
Cluster: clusterScope.Cluster,
Machine: &clusterv1.Machine{},
InfraCluster: clusterScope,
Expand Down
2 changes: 0 additions & 2 deletions pkg/cloud/services/ssm/secret_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
"github.com/google/go-cmp/cmp"
. "github.com/onsi/gomega"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
Expand Down Expand Up @@ -274,7 +273,6 @@ func getClusterScope(client client.Client) (*scope.ClusterScope, error) {
func getMachineScope(client client.Client, clusterScope *scope.ClusterScope) (*scope.MachineScope, error) {
return scope.NewMachineScope(scope.MachineScopeParams{
Client: client,
ControlPlane: &unstructured.Unstructured{},
Cluster: clusterScope.Cluster,
Machine: &clusterv1.Machine{},
InfraCluster: clusterScope,
Expand Down
16 changes: 16 additions & 0 deletions test/mocks/capa_clusterscoper_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 591e196

Please sign in to comment.