Skip to content

Commit 5b01057

Browse files
authored
VPC: Create v2 path for new Infrastructure implementation (#1858)
Create a v2 path that will be used for the new Infrastructure implementation for VPC Clusters. All new functionality will be placed in these new v2 paths, based on the new Network field, to prevent breaking existing implementation.
1 parent af008bd commit 5b01057

File tree

2 files changed

+232
-0
lines changed

2 files changed

+232
-0
lines changed

cloud/scope/vpc_cluster.go

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/*
2+
Copyright 2024 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+
"context"
21+
"errors"
22+
"fmt"
23+
24+
"github.com/go-logr/logr"
25+
26+
"github.com/IBM/go-sdk-core/v5/core"
27+
"github.com/IBM/platform-services-go-sdk/resourcecontrollerv2"
28+
29+
"k8s.io/klog/v2/textlogger"
30+
31+
"sigs.k8s.io/controller-runtime/pkg/client"
32+
33+
capiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
34+
"sigs.k8s.io/cluster-api/util/patch"
35+
36+
infrav1beta2 "sigs.k8s.io/cluster-api-provider-ibmcloud/api/v1beta2"
37+
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/authenticator"
38+
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/cos"
39+
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/resourcecontroller"
40+
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/resourcemanager"
41+
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/vpc"
42+
"sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/endpoints"
43+
)
44+
45+
const (
46+
// LOGDEBUGLEVEL indicates the debug level of the logs.
47+
LOGDEBUGLEVEL = 5
48+
)
49+
50+
// VPCClusterScopeParams defines the input parameters used to create a new VPCClusterScope.
51+
type VPCClusterScopeParams struct {
52+
Client client.Client
53+
Cluster *capiv1beta1.Cluster
54+
IBMVPCCluster *infrav1beta2.IBMVPCCluster
55+
Logger logr.Logger
56+
ServiceEndpoint []endpoints.ServiceEndpoint
57+
58+
IBMVPCClient vpc.Vpc
59+
}
60+
61+
// VPCClusterScope defines a scope defined around a VPC Cluster.
62+
type VPCClusterScope struct {
63+
logr.Logger
64+
Client client.Client
65+
patchHelper *patch.Helper
66+
67+
COSClient cos.Cos
68+
ResourceControllerClient resourcecontroller.ResourceController
69+
ResourceManagerClient resourcemanager.ResourceManager
70+
VPCClient vpc.Vpc
71+
72+
Cluster *capiv1beta1.Cluster
73+
IBMVPCCluster *infrav1beta2.IBMVPCCluster
74+
ServiceEndpoint []endpoints.ServiceEndpoint
75+
}
76+
77+
// NewVPCClusterScope creates a new VPCClusterScope from the supplied parameters.
78+
func NewVPCClusterScope(params VPCClusterScopeParams) (*VPCClusterScope, error) {
79+
if params.Client == nil {
80+
err := errors.New("error failed to generate new scope from nil Client")
81+
return nil, err
82+
}
83+
if params.Cluster == nil {
84+
err := errors.New("error failed to generate new scope from nil Cluster")
85+
return nil, err
86+
}
87+
if params.IBMVPCCluster == nil {
88+
err := errors.New("error failed to generate new scope from nil IBMVPCCluster")
89+
return nil, err
90+
}
91+
if params.Logger == (logr.Logger{}) {
92+
params.Logger = textlogger.NewLogger(textlogger.NewConfig())
93+
}
94+
95+
helper, err := patch.NewHelper(params.IBMVPCCluster, params.Client)
96+
if err != nil {
97+
return nil, fmt.Errorf("error failed to init patch helper: %w", err)
98+
}
99+
100+
vpcEndpoint := endpoints.FetchVPCEndpoint(params.IBMVPCCluster.Spec.Region, params.ServiceEndpoint)
101+
vpcClient, err := vpc.NewService(vpcEndpoint)
102+
if err != nil {
103+
return nil, fmt.Errorf("error failed to create IBM VPC client: %w", err)
104+
}
105+
106+
if params.IBMVPCCluster.Spec.Network == nil || params.IBMVPCCluster.Spec.Region == "" {
107+
return nil, fmt.Errorf("error failed to generate vpc client as Network or Region is nil")
108+
}
109+
110+
if params.Logger.V(LOGDEBUGLEVEL).Enabled() {
111+
core.SetLoggingLevel(core.LevelDebug)
112+
}
113+
114+
auth, err := authenticator.GetAuthenticator()
115+
if err != nil {
116+
return nil, fmt.Errorf("error failed to create authenticator: %w", err)
117+
}
118+
119+
// Create Global Tagging client.
120+
// TODO(cjschaef): need service support.
121+
122+
// Create Resource Controller client.
123+
rcOptions := resourcecontroller.ServiceOptions{
124+
ResourceControllerV2Options: &resourcecontrollerv2.ResourceControllerV2Options{
125+
Authenticator: auth,
126+
},
127+
}
128+
// Fetch the resource controller endpoint.
129+
rcEndpoint := endpoints.FetchEndpoints(string(endpoints.RC), params.ServiceEndpoint)
130+
if rcEndpoint != "" {
131+
rcOptions.URL = rcEndpoint
132+
params.Logger.V(3).Info("Overriding the default resource controller endpoint", "ResourceControllerEndpoint", rcEndpoint)
133+
}
134+
resourceControllerClient, err := resourcecontroller.NewService(rcOptions)
135+
if err != nil {
136+
return nil, fmt.Errorf("error failed to create resource controller client: %w", err)
137+
}
138+
139+
// Create Resource Manager client.
140+
// TODO(cjschaef): Need to extend ResourceManager service and endpoint support to add properly.
141+
142+
clusterScope := &VPCClusterScope{
143+
Logger: params.Logger,
144+
Client: params.Client,
145+
patchHelper: helper,
146+
Cluster: params.Cluster,
147+
IBMVPCCluster: params.IBMVPCCluster,
148+
ServiceEndpoint: params.ServiceEndpoint,
149+
ResourceControllerClient: resourceControllerClient,
150+
VPCClient: vpcClient,
151+
}
152+
return clusterScope, nil
153+
}
154+
155+
// PatchObject persists the cluster configuration and status.
156+
func (s *VPCClusterScope) PatchObject() error {
157+
return s.patchHelper.Patch(context.TODO(), s.IBMVPCCluster)
158+
}
159+
160+
// Close closes the current scope persisting the cluster configuration and status.
161+
func (s *VPCClusterScope) Close() error {
162+
return s.PatchObject()
163+
}
164+
165+
// Name returns the CAPI cluster name.
166+
func (s *VPCClusterScope) Name() string {
167+
return s.Cluster.Name
168+
}

controllers/ibmvpccluster_controller.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ func (r *IBMVPCClusterReconciler) Reconcile(ctx context.Context, req ctrl.Reques
7171
return ctrl.Result{}, err
7272
}
7373

74+
// Determine whether the Cluster is designed for extended Infrastructure support, implemented in a separate path.
75+
if ibmCluster.Spec.Network != nil {
76+
return r.reconcileV2(ctx, req)
77+
}
78+
7479
// Fetch the Cluster.
7580
cluster, err := util.GetOwnerCluster(ctx, r.Client, ibmCluster.ObjectMeta)
7681
if err != nil {
@@ -109,6 +114,57 @@ func (r *IBMVPCClusterReconciler) Reconcile(ctx context.Context, req ctrl.Reques
109114
return r.reconcile(clusterScope)
110115
}
111116

117+
func (r *IBMVPCClusterReconciler) reconcileV2(ctx context.Context, req ctrl.Request) (_ ctrl.Result, reterr error) {
118+
log := r.Log.WithValues("ibmvpccluster", req.NamespacedName)
119+
120+
// Fetch the IBMVPCCluster instance.
121+
ibmCluster := &infrav1beta2.IBMVPCCluster{}
122+
err := r.Get(ctx, req.NamespacedName, ibmCluster)
123+
if err != nil {
124+
if apierrors.IsNotFound(err) {
125+
return ctrl.Result{}, nil
126+
}
127+
return ctrl.Result{}, err
128+
}
129+
130+
// Fetch the Cluster.
131+
cluster, err := util.GetOwnerCluster(ctx, r.Client, ibmCluster.ObjectMeta)
132+
if err != nil {
133+
return ctrl.Result{}, err
134+
}
135+
if cluster == nil {
136+
log.Info("Cluster Controller has not yet set OwnerRef")
137+
return ctrl.Result{}, nil
138+
}
139+
140+
clusterScope, err := scope.NewVPCClusterScope(scope.VPCClusterScopeParams{
141+
Client: r.Client,
142+
Logger: log,
143+
Cluster: cluster,
144+
IBMVPCCluster: ibmCluster,
145+
ServiceEndpoint: r.ServiceEndpoint,
146+
})
147+
148+
// Always close the scope when exiting this function so we can persist any IBMVPCCluster changes.
149+
defer func() {
150+
if clusterScope != nil {
151+
if err := clusterScope.Close(); err != nil && reterr == nil {
152+
reterr = err
153+
}
154+
}
155+
}()
156+
157+
// Handle deleted clusters.
158+
if !ibmCluster.DeletionTimestamp.IsZero() {
159+
return r.reconcileDeleteV2(clusterScope)
160+
}
161+
162+
if err != nil {
163+
return reconcile.Result{}, fmt.Errorf("failed to create scope: %w", err)
164+
}
165+
return r.reconcileCluster(clusterScope)
166+
}
167+
112168
func (r *IBMVPCClusterReconciler) reconcile(clusterScope *scope.ClusterScope) (ctrl.Result, error) {
113169
// If the IBMVPCCluster doesn't have our finalizer, add it.
114170
if controllerutil.AddFinalizer(clusterScope.IBMVPCCluster, infrav1beta2.ClusterFinalizer) {
@@ -173,6 +229,10 @@ func (r *IBMVPCClusterReconciler) reconcile(clusterScope *scope.ClusterScope) (c
173229
return ctrl.Result{}, nil
174230
}
175231

232+
func (r *IBMVPCClusterReconciler) reconcileCluster(_ *scope.VPCClusterScope) (ctrl.Result, error) {
233+
return ctrl.Result{}, fmt.Errorf("not implemented")
234+
}
235+
176236
func (r *IBMVPCClusterReconciler) reconcileDelete(clusterScope *scope.ClusterScope) (ctrl.Result, error) {
177237
// check if still have existing VSIs.
178238
listVSIOpts := &vpcv1.ListInstancesOptions{
@@ -227,6 +287,10 @@ func (r *IBMVPCClusterReconciler) reconcileDelete(clusterScope *scope.ClusterSco
227287
return handleFinalizerRemoval(clusterScope)
228288
}
229289

290+
func (r *IBMVPCClusterReconciler) reconcileDeleteV2(_ *scope.VPCClusterScope) (ctrl.Result, error) {
291+
return ctrl.Result{}, fmt.Errorf("not implemented")
292+
}
293+
230294
func (r *IBMVPCClusterReconciler) getOrCreate(clusterScope *scope.ClusterScope) (*vpcv1.LoadBalancer, error) {
231295
loadBalancer, err := clusterScope.CreateLoadBalancer()
232296
return loadBalancer, err

0 commit comments

Comments
 (0)