Skip to content

Commit 576f0cd

Browse files
authored
Merge pull request #2124 from enxebre/decouple-external-infra
Add externalInfraCluster
2 parents 14282e4 + 5437038 commit 576f0cd

File tree

4 files changed

+323
-20
lines changed

4 files changed

+323
-20
lines changed

controllers/awsmachine_controller.go

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package controllers
1818

1919
import (
2020
"context"
21+
"fmt"
2122
"reflect"
2223

2324
"github.com/go-logr/logr"
@@ -26,7 +27,18 @@ import (
2627
apierrors "k8s.io/apimachinery/pkg/api/errors"
2728
"k8s.io/client-go/tools/record"
2829
"k8s.io/utils/pointer"
30+
infrav1 "sigs.k8s.io/cluster-api-provider-aws/api/v1alpha3"
31+
ekscontrolplanev1 "sigs.k8s.io/cluster-api-provider-aws/controlplane/eks/api/v1alpha3"
32+
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud"
33+
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/scope"
34+
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services"
35+
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/ec2"
36+
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/elb"
37+
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/secretsmanager"
38+
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/ssm"
39+
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/userdata"
2940
clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha3"
41+
"sigs.k8s.io/cluster-api/controllers/external"
3042
"sigs.k8s.io/cluster-api/controllers/noderefutil"
3143
capierrors "sigs.k8s.io/cluster-api/errors"
3244
"sigs.k8s.io/cluster-api/util"
@@ -39,17 +51,6 @@ import (
3951
"sigs.k8s.io/controller-runtime/pkg/handler"
4052
"sigs.k8s.io/controller-runtime/pkg/predicate"
4153
"sigs.k8s.io/controller-runtime/pkg/source"
42-
43-
infrav1 "sigs.k8s.io/cluster-api-provider-aws/api/v1alpha3"
44-
ekscontrolplanev1 "sigs.k8s.io/cluster-api-provider-aws/controlplane/eks/api/v1alpha3"
45-
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud"
46-
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/scope"
47-
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services"
48-
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/ec2"
49-
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/elb"
50-
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/secretsmanager"
51-
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/ssm"
52-
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/userdata"
5354
)
5455

5556
// AWSMachineReconciler reconciles a AwsMachine object
@@ -65,7 +66,8 @@ type AWSMachineReconciler struct {
6566

6667
const (
6768
// AWSManagedControlPlaneRefKind is the string value indicating that a cluster is AWS managed
68-
AWSManagedControlPlaneRefKind = "AWSManagedControlPlane"
69+
AWSManagedControlPlaneRefKind = "AWSManagedControlPlane"
70+
AWSClusterInfrastructureRefKind = "AWSCluster"
6971
)
7072

7173
func (r *AWSMachineReconciler) getEC2Service(scope scope.EC2Scope) services.EC2MachineInterface {
@@ -190,7 +192,10 @@ func (r *AWSMachineReconciler) Reconcile(req ctrl.Request) (_ ctrl.Result, reter
190192

191193
return r.reconcileNormal(ctx, machineScope, infraScope, infraScope, infraScope)
192194
default:
193-
return ctrl.Result{}, errors.New("infraCluster has unknown type")
195+
if !awsMachine.ObjectMeta.DeletionTimestamp.IsZero() {
196+
return r.reconcileDelete(machineScope, infraScope, infraScope, nil)
197+
}
198+
return r.reconcileNormal(ctx, machineScope, infraScope, infraScope, nil)
194199
}
195200
}
196201

@@ -796,6 +801,31 @@ func (r *AWSMachineReconciler) getInfraCluster(ctx context.Context, log logr.Log
796801
return managedControlPlaneScope, nil
797802
}
798803

804+
if cluster.Spec.InfrastructureRef != nil &&
805+
cluster.Spec.InfrastructureRef.Kind != AWSClusterInfrastructureRefKind {
806+
externalInfraCluster, err := external.Get(ctx, r.Client, cluster.Spec.InfrastructureRef, cluster.Spec.InfrastructureRef.Namespace)
807+
if err != nil {
808+
log.Error(err, "error fetching externalInfraCluster")
809+
return nil, fmt.Errorf("error fetching externalInfraCluster: %w", err)
810+
}
811+
812+
// Create the cluster scope
813+
extenalInfraClusterScope, err := scope.NewExternalInfraClusterScope(scope.ExternalInfraClusterScopeParams{
814+
Client: r.Client,
815+
Logger: log,
816+
Cluster: cluster,
817+
ExternalInfraCluster: externalInfraCluster,
818+
ControllerName: "externalInfraCluster",
819+
})
820+
if err != nil {
821+
log.Error(err, "unable to create external cluster scope")
822+
return nil, fmt.Errorf("unable to create external cluster scope: %w", err)
823+
}
824+
825+
r.Log.Info("Using externalInfraCluster")
826+
return extenalInfraClusterScope, nil
827+
}
828+
799829
awsCluster := &infrav1.AWSCluster{}
800830

801831
infraClusterName := client.ObjectKey{
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
/*
2+
Copyright 2020 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package scope
18+
19+
import (
20+
"fmt"
21+
22+
awsclient "github.com/aws/aws-sdk-go/aws/client"
23+
"github.com/go-logr/logr"
24+
"github.com/pkg/errors"
25+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
26+
"k8s.io/klog/klogr"
27+
infrav1 "sigs.k8s.io/cluster-api-provider-aws/api/v1alpha3"
28+
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud"
29+
clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha3"
30+
"sigs.k8s.io/cluster-api/util/patch"
31+
"sigs.k8s.io/controller-runtime/pkg/client"
32+
)
33+
34+
// ExternalInfraClusterScopeParams defines the input parameters used to create a new Scope.
35+
type ExternalInfraClusterScopeParams struct {
36+
Client client.Client
37+
Logger logr.Logger
38+
Cluster *clusterv1.Cluster
39+
ExternalInfraCluster *unstructured.Unstructured
40+
ControllerName string
41+
Endpoints []ServiceEndpoint
42+
Session awsclient.ConfigProvider
43+
}
44+
45+
// NewExternalInfraClusterScope creates a new Scope from the supplied parameters.
46+
// This is meant to be called for each reconcile iteration.
47+
func NewExternalInfraClusterScope(params ExternalInfraClusterScopeParams) (*ExternalInfraClusterScope, error) {
48+
if params.Cluster == nil {
49+
return nil, errors.New("failed to generate new scope from nil Cluster")
50+
}
51+
if params.ExternalInfraCluster == nil {
52+
return nil, errors.New("failed to generate new scope from nil ExternalInfraCluster")
53+
}
54+
55+
if params.Logger == nil {
56+
params.Logger = klogr.New()
57+
}
58+
59+
region, found, err := unstructured.NestedString(params.ExternalInfraCluster.Object, "spec", "region")
60+
if err != nil || !found {
61+
return nil, fmt.Errorf("error getting region: %w", err)
62+
}
63+
session, err := sessionForRegion(region, params.Endpoints)
64+
if err != nil {
65+
return nil, errors.Errorf("failed to create aws session: %v", err)
66+
}
67+
68+
helper, err := patch.NewHelper(params.ExternalInfraCluster, params.Client)
69+
if err != nil {
70+
return nil, errors.Wrap(err, "failed to init patch helper")
71+
}
72+
return &ExternalInfraClusterScope{
73+
Logger: params.Logger,
74+
client: params.Client,
75+
Cluster: params.Cluster,
76+
ExternalInfraCluster: &ExternalInfraClusterObject{params.ExternalInfraCluster},
77+
patchHelper: helper,
78+
session: session,
79+
controllerName: params.ControllerName,
80+
}, nil
81+
}
82+
83+
// ExternalInfraClusterScope defines the basic context for an actuator to operate upon.
84+
type ExternalInfraClusterScope struct {
85+
logr.Logger
86+
client client.Client
87+
patchHelper *patch.Helper
88+
89+
Cluster *clusterv1.Cluster
90+
ExternalInfraCluster *ExternalInfraClusterObject
91+
92+
session awsclient.ConfigProvider
93+
controllerName string
94+
}
95+
96+
// Network returns the cluster network object.
97+
func (s *ExternalInfraClusterScope) Network() *infrav1.Network {
98+
return nil
99+
}
100+
101+
// VPC returns the cluster VPC.
102+
func (s *ExternalInfraClusterScope) VPC() *infrav1.VPCSpec {
103+
return &infrav1.VPCSpec{}
104+
}
105+
106+
// Subnets returns the cluster subnets.
107+
func (s *ExternalInfraClusterScope) Subnets() infrav1.Subnets {
108+
return nil
109+
}
110+
111+
// SetSubnets updates the clusters subnets.
112+
func (s *ExternalInfraClusterScope) SetSubnets(subnets infrav1.Subnets) {
113+
}
114+
115+
// CNIIngressRules returns the CNI spec ingress rules.
116+
func (s *ExternalInfraClusterScope) CNIIngressRules() infrav1.CNIIngressRules {
117+
return infrav1.CNIIngressRules{}
118+
}
119+
120+
// SecurityGroups returns the cluster security groups as a map, it creates the map if empty.
121+
func (s *ExternalInfraClusterScope) SecurityGroups() map[infrav1.SecurityGroupRole]infrav1.SecurityGroup {
122+
return nil
123+
}
124+
125+
// Name returns the CAPI cluster name.
126+
func (s *ExternalInfraClusterScope) Name() string {
127+
return s.Cluster.Name
128+
}
129+
130+
// Namespace returns the cluster namespace.
131+
func (s *ExternalInfraClusterScope) Namespace() string {
132+
return s.Cluster.Namespace
133+
}
134+
135+
// Region returns the cluster region.
136+
func (s *ExternalInfraClusterScope) Region() string {
137+
region, found, err := unstructured.NestedString(s.ExternalInfraCluster.Object, "spec", "region")
138+
if err != nil || !found {
139+
s.Error(err, "error getting region")
140+
return ""
141+
}
142+
return region
143+
}
144+
145+
// KubernetesClusterName is the name of the Kubernetes cluster. For the cluster
146+
// scope this is the same as the CAPI cluster name
147+
func (s *ExternalInfraClusterScope) KubernetesClusterName() string {
148+
return s.Cluster.Name
149+
}
150+
151+
// ControlPlaneLoadBalancer returns the AWSLoadBalancerSpec
152+
func (s *ExternalInfraClusterScope) ControlPlaneLoadBalancer() *infrav1.AWSLoadBalancerSpec {
153+
return nil
154+
}
155+
156+
// ControlPlaneLoadBalancerScheme returns the Classic ELB scheme (public or internal facing)
157+
func (s *ExternalInfraClusterScope) ControlPlaneLoadBalancerScheme() infrav1.ClassicELBScheme {
158+
if s.ControlPlaneLoadBalancer() != nil && s.ControlPlaneLoadBalancer().Scheme != nil {
159+
return *s.ControlPlaneLoadBalancer().Scheme
160+
}
161+
return infrav1.ClassicELBSchemeInternetFacing
162+
}
163+
164+
// ControlPlaneConfigMapName returns the name of the ConfigMap used to
165+
// coordinate the bootstrapping of control plane nodes.
166+
func (s *ExternalInfraClusterScope) ControlPlaneConfigMapName() string {
167+
return fmt.Sprintf("%s-controlplane", s.Cluster.UID)
168+
}
169+
170+
// ListOptionsLabelSelector returns a ListOptions with a label selector for clusterName.
171+
func (s *ExternalInfraClusterScope) ListOptionsLabelSelector() client.ListOption {
172+
return client.MatchingLabels(map[string]string{
173+
clusterv1.ClusterLabelName: s.Cluster.Name,
174+
})
175+
}
176+
177+
// PatchObject persists the cluster configuration and status.
178+
func (s *ExternalInfraClusterScope) PatchObject() error {
179+
return nil
180+
}
181+
182+
// Close closes the current scope persisting the cluster configuration and status.
183+
func (s *ExternalInfraClusterScope) Close() error {
184+
return s.PatchObject()
185+
}
186+
187+
// AdditionalTags returns AdditionalTags from the scope's ExternalInfraCluster. The returned value will never be nil.
188+
func (s *ExternalInfraClusterScope) AdditionalTags() infrav1.Tags {
189+
return nil
190+
}
191+
192+
// APIServerPort returns the APIServerPort to use when creating the load balancer.
193+
func (s *ExternalInfraClusterScope) APIServerPort() int32 {
194+
if s.Cluster.Spec.ClusterNetwork != nil && s.Cluster.Spec.ClusterNetwork.APIServerPort != nil {
195+
return *s.Cluster.Spec.ClusterNetwork.APIServerPort
196+
}
197+
return 6443
198+
}
199+
200+
// SetFailureDomain sets the infrastructure provider failure domain key to the spec given as input.
201+
func (s *ExternalInfraClusterScope) SetFailureDomain(id string, spec clusterv1.FailureDomainSpec) {
202+
}
203+
204+
type ExternalInfraClusterObject struct {
205+
*unstructured.Unstructured
206+
}
207+
208+
// InfraCluster returns the AWS infrastructure cluster or control plane object.
209+
func (s *ExternalInfraClusterScope) InfraCluster() cloud.ClusterObject {
210+
return s.ExternalInfraCluster
211+
}
212+
213+
func (r *ExternalInfraClusterObject) GetConditions() clusterv1.Conditions {
214+
return nil
215+
}
216+
217+
func (r *ExternalInfraClusterObject) SetConditions(conditions clusterv1.Conditions) {
218+
}
219+
220+
// Session returns the AWS SDK session. Used for creating clients
221+
func (s *ExternalInfraClusterScope) Session() awsclient.ConfigProvider {
222+
return s.session
223+
}
224+
225+
// Bastion returns the bastion details.
226+
func (s *ExternalInfraClusterScope) Bastion() *infrav1.Bastion {
227+
return nil
228+
}
229+
230+
// SetBastionInstance sets the bastion instance in the status of the cluster.
231+
func (s *ExternalInfraClusterScope) SetBastionInstance(instance *infrav1.Instance) {
232+
}
233+
234+
// SSHKeyName returns the SSH key name to use for instances.
235+
func (s *ExternalInfraClusterScope) SSHKeyName() *string {
236+
return nil
237+
}
238+
239+
// ControllerName returns the name of the controller that
240+
// created the ExternalInfraClusterScope.
241+
func (s *ExternalInfraClusterScope) ControllerName() string {
242+
return s.controllerName
243+
}
244+
245+
// ImageLookupFormat returns the format string to use when looking up AMIs
246+
func (s *ExternalInfraClusterScope) ImageLookupFormat() string {
247+
return ""
248+
}
249+
250+
// ImageLookupOrg returns the organization name to use when looking up AMIs
251+
func (s *ExternalInfraClusterScope) ImageLookupOrg() string {
252+
return ""
253+
}
254+
255+
// ImageLookupBaseOS returns the base operating system name to use when looking up AMIs
256+
func (s *ExternalInfraClusterScope) ImageLookupBaseOS() string {
257+
return ""
258+
}

pkg/cloud/scope/machine.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,3 +344,7 @@ func (m *MachineScope) SetInterruptible() {
344344
m.AWSMachine.Status.Interruptible = true
345345
}
346346
}
347+
348+
func (m *MachineScope) IsExternalInfraCluster() bool {
349+
return m.InfraCluster.InfraCluster().GetObjectKind().GroupVersionKind().Kind == "ExternalInfraCluster"
350+
}

0 commit comments

Comments
 (0)