Skip to content

Commit b4349fe

Browse files
committed
replace exec with client create
1 parent f57b8c8 commit b4349fe

File tree

11 files changed

+91
-177
lines changed

11 files changed

+91
-177
lines changed

hack/ensure-kubectl.sh

Lines changed: 0 additions & 65 deletions
This file was deleted.

scripts/ci-e2e.sh

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ source "${REPO_ROOT}/scripts/ci-e2e-lib.sh"
2626

2727
# shellcheck source=./hack/ensure-go.sh
2828
source "${REPO_ROOT}/hack/ensure-go.sh"
29-
# shellcheck source=./hack/ensure-kubectl.sh
30-
source "${REPO_ROOT}/hack/ensure-kubectl.sh"
3129
# shellcheck source=./hack/ensure-kind.sh
3230
source "${REPO_ROOT}/hack/ensure-kind.sh"
3331

test/e2e/clusterclass_rollout.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ func assertControlPlane(g Gomega, clusterClassObjects clusterClassObjects, clust
418418
clusterv1.TemplateClonedFromNameAnnotation: clusterClass.Spec.ControlPlane.MachineInfrastructure.Ref.Name,
419419
},
420420
clusterClassObjects.ControlPlaneInfrastructureMachineTemplate.GetAnnotations(),
421-
).without(g, corev1.LastAppliedConfigAnnotation),
421+
),
422422
))
423423

424424
// ControlPlane InfrastructureMachineTemplate.spec.template.metadata
@@ -590,7 +590,7 @@ func assertMachineDeployments(g Gomega, clusterClassObjects clusterClassObjects,
590590
clusterv1.TemplateClonedFromNameAnnotation: mdClass.Template.Infrastructure.Ref.Name,
591591
},
592592
ccInfrastructureMachineTemplate.GetAnnotations(),
593-
).without(g, corev1.LastAppliedConfigAnnotation),
593+
),
594594
))
595595
// MachineDeployment InfrastructureMachineTemplate.spec.template.metadata
596596
g.Expect(infrastructureMachineTemplateTemplateMetadata.Labels).To(BeEquivalentTo(
@@ -622,7 +622,7 @@ func assertMachineDeployments(g Gomega, clusterClassObjects clusterClassObjects,
622622
clusterv1.TemplateClonedFromNameAnnotation: mdClass.Template.Bootstrap.Ref.Name,
623623
},
624624
ccBootstrapConfigTemplate.GetAnnotations(),
625-
).without(g, corev1.LastAppliedConfigAnnotation),
625+
),
626626
))
627627
// MachineDeployment BootstrapConfigTemplate.spec.template.metadata
628628
g.Expect(bootstrapConfigTemplateTemplateMetadata.Labels).To(BeEquivalentTo(

test/e2e/clusterctl_upgrade.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ func ClusterctlUpgradeSpec(ctx context.Context, inputGetter func() ClusterctlUpg
448448
Expect(workloadClusterTemplate).ToNot(BeNil(), "Failed to get the cluster template")
449449

450450
log.Logf("Applying the cluster template yaml to the cluster")
451-
Expect(managementClusterProxy.Apply(ctx, workloadClusterTemplate)).To(Succeed())
451+
Expect(managementClusterProxy.CreateOrUpdate(ctx, workloadClusterTemplate)).To(Succeed())
452452

453453
if input.PreWaitForCluster != nil {
454454
By("Running PreWaitForCluster steps against the management cluster")

test/e2e/kcp_adoption.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,12 @@ func KCPAdoptionSpec(ctx context.Context, inputGetter func() KCPAdoptionSpecInpu
117117
if input.InfrastructureProvider != nil {
118118
infrastructureProvider = *input.InfrastructureProvider
119119
}
120-
120+
must := func(r *labels.Requirement, err error) labels.Requirement {
121+
if err != nil {
122+
panic(err)
123+
}
124+
return *r
125+
}
121126
workloadClusterTemplate := clusterctl.ConfigCluster(ctx, clusterctl.ConfigClusterInput{
122127
// pass reference to the management cluster hosting this test
123128
KubeconfigPath: input.BootstrapClusterProxy.GetKubeconfigPath(),
@@ -138,7 +143,8 @@ func KCPAdoptionSpec(ctx context.Context, inputGetter func() KCPAdoptionSpecInpu
138143
Expect(workloadClusterTemplate).ToNot(BeNil(), "Failed to get the cluster template")
139144

140145
By("Applying the cluster template yaml to the cluster with the 'initial' selector")
141-
Expect(input.BootstrapClusterProxy.Apply(ctx, workloadClusterTemplate, "--selector", "kcp-adoption.step1")).ShouldNot(HaveOccurred())
146+
selector := labels.NewSelector().Add(must(labels.NewRequirement("kcp-adoption.step1", selection.Exists, nil)))
147+
Expect(input.BootstrapClusterProxy.CreateOrUpdate(ctx, workloadClusterTemplate, framework.WithLabelSelector(selector))).ShouldNot(HaveOccurred())
142148

143149
cluster = framework.DiscoveryAndWaitForCluster(ctx, framework.DiscoveryAndWaitForClusterInput{
144150
Getter: client,
@@ -159,7 +165,8 @@ func KCPAdoptionSpec(ctx context.Context, inputGetter func() KCPAdoptionSpecInpu
159165
}, WaitForControlPlaneIntervals...)
160166

161167
By("Applying the cluster template yaml to the cluster with the 'kcp' selector")
162-
Expect(input.BootstrapClusterProxy.Apply(ctx, workloadClusterTemplate, "--selector", "kcp-adoption.step2")).ShouldNot(HaveOccurred())
168+
selector = labels.NewSelector().Add(must(labels.NewRequirement("kcp-adoption.step2", selection.Exists, nil)))
169+
Expect(input.BootstrapClusterProxy.CreateOrUpdate(ctx, workloadClusterTemplate, framework.WithLabelSelector(selector))).ShouldNot(HaveOccurred())
163170

164171
var controlPlane *controlplanev1.KubeadmControlPlane
165172
Eventually(func() *controlplanev1.KubeadmControlPlane {
@@ -177,12 +184,6 @@ func KCPAdoptionSpec(ctx context.Context, inputGetter func() KCPAdoptionSpecInpu
177184
})
178185

179186
By("Taking stable ownership of the Machines")
180-
must := func(r *labels.Requirement, err error) labels.Requirement {
181-
if err != nil {
182-
panic(err)
183-
}
184-
return *r
185-
}
186187
machines := clusterv1.MachineList{}
187188
Expect(client.List(ctx, &machines,
188189
ctrlclient.InNamespace(namespace.Name),

test/e2e/kcp_remediations.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ func createWorkloadClusterAndWait(ctx context.Context, input createWorkloadClust
489489
Expect(workloadClusterTemplate).ToNot(BeNil(), "Failed to get the cluster template")
490490

491491
Eventually(func() error {
492-
return input.Proxy.Apply(ctx, workloadClusterTemplate)
492+
return input.Proxy.CreateOrUpdate(ctx, workloadClusterTemplate)
493493
}, 10*time.Second).Should(Succeed(), "Failed to apply the cluster template")
494494

495495
log.Logf("Waiting for the cluster infrastructure to be provisioned")

test/e2e/scale.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ func scaleSpec(ctx context.Context, inputGetter func() scaleSpecInput) {
290290
clusterClassYAML := bytes.Replace(baseClusterClassYAML, []byte(scaleClusterNamespacePlaceholder), []byte(namespace.Name), -1)
291291
log.Logf("Apply ClusterClass")
292292
Eventually(func() error {
293-
return input.BootstrapClusterProxy.Apply(ctx, clusterClassYAML)
293+
return input.BootstrapClusterProxy.CreateOrUpdate(ctx, clusterClassYAML)
294294
}, 1*time.Minute).Should(Succeed())
295295
} else {
296296
log.Logf("ClusterClass already exists. Skipping creation.")
@@ -551,7 +551,7 @@ func getClusterCreateAndWaitFn(input clusterctl.ApplyCustomClusterTemplateAndWai
551551
WaitForClusterIntervals: input.WaitForClusterIntervals,
552552
WaitForControlPlaneIntervals: input.WaitForControlPlaneIntervals,
553553
WaitForMachineDeployments: input.WaitForMachineDeployments,
554-
Args: input.Args,
554+
CreateOrUpdateOpts: input.CreateOrUpdateOpts,
555555
PreWaitForCluster: input.PreWaitForCluster,
556556
PostMachinesProvisioned: input.PostMachinesProvisioned,
557557
ControlPlaneWaiters: input.ControlPlaneWaiters,
@@ -563,7 +563,7 @@ func getClusterCreateFn(clusterProxy framework.ClusterProxy) clusterCreator {
563563
return func(ctx context.Context, namespace, clusterName string, clusterTemplateYAML []byte) {
564564
log.Logf("Applying the cluster template yaml of cluster %s", klog.KRef(namespace, clusterName))
565565
Eventually(func() error {
566-
return clusterProxy.Apply(ctx, clusterTemplateYAML)
566+
return clusterProxy.CreateOrUpdate(ctx, clusterTemplateYAML)
567567
}, 1*time.Minute).Should(Succeed(), "Failed to apply the cluster template of cluster %s", klog.KRef(namespace, clusterName))
568568
}
569569
}
@@ -616,7 +616,7 @@ func createClusterWorker(ctx context.Context, clusterProxy framework.ClusterProx
616616
log.Logf("Apply ClusterClass in namespace %", namespaceName)
617617
clusterClassYAML := bytes.Replace(baseClusterClassYAML, []byte(scaleClusterNamespacePlaceholder), []byte(namespaceName), -1)
618618
Eventually(func() error {
619-
return clusterProxy.Apply(ctx, clusterClassYAML)
619+
return clusterProxy.CreateOrUpdate(ctx, clusterClassYAML)
620620
}, 1*time.Minute).Should(Succeed())
621621
}
622622

test/framework/autoscaler_helpers.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func ApplyAutoscalerToWorkloadCluster(ctx context.Context, input ApplyAutoscaler
107107
},
108108
})
109109
Expect(err).ToNot(HaveOccurred(), "failed to parse %s", workloadYamlTemplate)
110-
Expect(input.WorkloadClusterProxy.Apply(ctx, workloadYaml)).To(Succeed(), "failed to apply %s", workloadYamlTemplate)
110+
Expect(input.WorkloadClusterProxy.CreateOrUpdate(ctx, workloadYaml)).To(Succeed(), "failed to apply %s", workloadYamlTemplate)
111111

112112
By("Wait for the autoscaler deployment and collect logs")
113113
deployment := &appsv1.Deployment{

test/framework/cluster_proxy.go

Lines changed: 66 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,20 @@ import (
2222
"fmt"
2323
"net/url"
2424
"os"
25-
"os/exec"
2625
"path"
2726
goruntime "runtime"
2827
"sync"
2928
"time"
3029

3130
. "github.com/onsi/ginkgo/v2"
3231
. "github.com/onsi/gomega"
33-
pkgerrors "github.com/pkg/errors"
3432
corev1 "k8s.io/api/core/v1"
33+
apierrors "k8s.io/apimachinery/pkg/api/errors"
34+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
35+
"k8s.io/apimachinery/pkg/labels"
3536
"k8s.io/apimachinery/pkg/runtime"
37+
"k8s.io/apimachinery/pkg/types"
38+
kerrors "k8s.io/apimachinery/pkg/util/errors"
3639
"k8s.io/apimachinery/pkg/util/wait"
3740
"k8s.io/client-go/kubernetes"
3841
"k8s.io/client-go/rest"
@@ -44,9 +47,9 @@ import (
4447

4548
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
4649
expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1"
47-
testexec "sigs.k8s.io/cluster-api/test/framework/exec"
4850
"sigs.k8s.io/cluster-api/test/framework/internal/log"
4951
"sigs.k8s.io/cluster-api/test/infrastructure/container"
52+
"sigs.k8s.io/cluster-api/util/yaml"
5053
)
5154

5255
const (
@@ -89,8 +92,8 @@ type ClusterProxy interface {
8992
// GetLogCollector returns the machine log collector for the Kubernetes cluster.
9093
GetLogCollector() ClusterLogCollector
9194

92-
// Apply to apply YAML to the Kubernetes cluster, `kubectl apply`.
93-
Apply(ctx context.Context, resources []byte, args ...string) error
95+
// CreateOrUpdate creates or updates objects using the clusterProxy client
96+
CreateOrUpdate(ctx context.Context, resources []byte, options ...CreateOrUpdateOption) error
9497

9598
// GetWorkloadCluster returns a proxy to a workload cluster defined in the Kubernetes cluster.
9699
GetWorkloadCluster(ctx context.Context, namespace, name string, options ...Option) ClusterProxy
@@ -103,6 +106,21 @@ type ClusterProxy interface {
103106
Dispose(context.Context)
104107
}
105108

109+
// createOrUpdateConfig contains options for use with CreateOrUpdate.
110+
type createOrUpdateConfig struct {
111+
labelSelector labels.Selector
112+
}
113+
114+
// CreateOrUpdateOption is a configuration option supplied to CreateOrUpdate.
115+
type CreateOrUpdateOption func(*createOrUpdateConfig)
116+
117+
// WithLabelSelector allows definition of the LabelSelector to be used in CreateOrUpdate.
118+
func WithLabelSelector(labelSelector labels.Selector) CreateOrUpdateOption {
119+
return func(c *createOrUpdateConfig) {
120+
c.labelSelector = labelSelector
121+
}
122+
}
123+
106124
// ClusterLogCollector defines an object that can collect logs from a machine.
107125
type ClusterLogCollector interface {
108126
// CollectMachineLog collects log from a machine.
@@ -247,20 +265,52 @@ func (p *clusterProxy) GetCache(ctx context.Context) cache.Cache {
247265
return p.cache
248266
}
249267

250-
// Apply wraps `kubectl apply ...` and prints the output so we can see what gets applied to the cluster.
251-
func (p *clusterProxy) Apply(ctx context.Context, resources []byte, args ...string) error {
252-
Expect(ctx).NotTo(BeNil(), "ctx is required for Apply")
253-
Expect(resources).NotTo(BeNil(), "resources is required for Apply")
254-
255-
if err := testexec.KubectlApply(ctx, p.kubeconfigPath, resources, args...); err != nil {
256-
var exitErr *exec.ExitError
257-
if errors.As(err, &exitErr) {
258-
return pkgerrors.New(fmt.Sprintf("%s: stderr: %s", err.Error(), exitErr.Stderr))
259-
}
268+
// CreateOrUpdate creates or updates objects using the clusterProxy client.
269+
func (p *clusterProxy) CreateOrUpdate(ctx context.Context, resources []byte, opts ...CreateOrUpdateOption) error {
270+
Expect(ctx).NotTo(BeNil(), "ctx is required for CreateOrUpdate")
271+
Expect(resources).NotTo(BeNil(), "resources is required for CreateOrUpdate")
272+
labelSelector := labels.Everything()
273+
config := &createOrUpdateConfig{}
274+
for _, opt := range opts {
275+
opt(config)
276+
}
277+
if config.labelSelector != nil {
278+
labelSelector = config.labelSelector
279+
}
280+
objs, err := yaml.ToUnstructured(resources)
281+
if err != nil {
260282
return err
261283
}
262284

263-
return nil
285+
existingObject := &unstructured.Unstructured{}
286+
var retErrs []error
287+
for _, o := range objs {
288+
objectKey := types.NamespacedName{
289+
Name: o.GetName(),
290+
Namespace: o.GetNamespace(),
291+
}
292+
existingObject.SetAPIVersion(o.GetAPIVersion())
293+
existingObject.SetKind(o.GetKind())
294+
labels := labels.Set(o.GetLabels())
295+
if labelSelector.Matches(labels) {
296+
if err := p.GetClient().Get(ctx, objectKey, existingObject); err != nil {
297+
// Expected error -- if the object does not exist, create it
298+
if apierrors.IsNotFound(err) {
299+
if err := p.GetClient().Create(ctx, &o); err != nil {
300+
retErrs = append(retErrs, err)
301+
}
302+
} else {
303+
retErrs = append(retErrs, err)
304+
}
305+
} else {
306+
o.SetResourceVersion(existingObject.GetResourceVersion())
307+
if err := p.GetClient().Update(ctx, &o); err != nil {
308+
retErrs = append(retErrs, err)
309+
}
310+
}
311+
}
312+
}
313+
return kerrors.NewAggregate(retErrs)
264314
}
265315

266316
func (p *clusterProxy) GetRESTConfig() *rest.Config {

test/framework/clusterctl/clusterctl_helpers.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ type ApplyClusterTemplateAndWaitInput struct {
246246
WaitForControlPlaneIntervals []interface{}
247247
WaitForMachineDeployments []interface{}
248248
WaitForMachinePools []interface{}
249-
Args []string // extra args to be used during `kubectl apply`
249+
CreateOrUpdateOpts []framework.CreateOrUpdateOption // options to be passed to CreateOrUpdate function config
250250
PreWaitForCluster func()
251251
PostMachinesProvisioned func()
252252
ControlPlaneWaiters
@@ -358,7 +358,7 @@ func ApplyClusterTemplateAndWait(ctx context.Context, input ApplyClusterTemplate
358358
WaitForControlPlaneIntervals: input.WaitForControlPlaneIntervals,
359359
WaitForMachineDeployments: input.WaitForMachineDeployments,
360360
WaitForMachinePools: input.WaitForMachinePools,
361-
Args: input.Args,
361+
CreateOrUpdateOpts: input.CreateOrUpdateOpts,
362362
PreWaitForCluster: input.PreWaitForCluster,
363363
PostMachinesProvisioned: input.PostMachinesProvisioned,
364364
ControlPlaneWaiters: input.ControlPlaneWaiters,
@@ -377,7 +377,7 @@ type ApplyCustomClusterTemplateAndWaitInput struct {
377377
WaitForControlPlaneIntervals []interface{}
378378
WaitForMachineDeployments []interface{}
379379
WaitForMachinePools []interface{}
380-
Args []string // extra args to be used during `kubectl apply`
380+
CreateOrUpdateOpts []framework.CreateOrUpdateOption // options to be passed to CreateOrUpdate function config
381381
PreWaitForCluster func()
382382
PostMachinesProvisioned func()
383383
ControlPlaneWaiters
@@ -412,7 +412,7 @@ func ApplyCustomClusterTemplateAndWait(ctx context.Context, input ApplyCustomClu
412412

413413
log.Logf("Applying the cluster template yaml of cluster %s", klog.KRef(input.Namespace, input.ClusterName))
414414
Eventually(func() error {
415-
return input.ClusterProxy.Apply(ctx, input.CustomTemplateYAML, input.Args...)
415+
return input.ClusterProxy.CreateOrUpdate(ctx, input.CustomTemplateYAML, input.CreateOrUpdateOpts...)
416416
}, 1*time.Minute).Should(Succeed(), "Failed to apply the cluster template")
417417

418418
// Once we applied the cluster template we can run PreWaitForCluster.
@@ -448,7 +448,7 @@ func ApplyCustomClusterTemplateAndWait(ctx context.Context, input ApplyCustomClu
448448
cniYaml, err := os.ReadFile(input.CNIManifestPath)
449449
Expect(err).ShouldNot(HaveOccurred())
450450

451-
Expect(workloadCluster.Apply(ctx, cniYaml)).ShouldNot(HaveOccurred())
451+
Expect(workloadCluster.CreateOrUpdate(ctx, cniYaml)).ShouldNot(HaveOccurred())
452452
}
453453

454454
log.Logf("Waiting for control plane of cluster %s to be ready", klog.KRef(input.Namespace, input.ClusterName))

0 commit comments

Comments
 (0)