Skip to content

Commit 971d49c

Browse files
feat: add createService test case command (#60)
* feat(runner): add createService command Signed-off-by: Maximilian Techritz <maximilian.techritz@sap.com> * fix(runner): set apiVersion and kind on unstructured object in createService cleanup Signed-off-by: Maximilian Techritz <maximilian.techritz@sap.com> * fix(runner): skip cleanup for already-cleaned-up test cases Signed-off-by: Maximilian Techritz <maximilian.techritz@sap.com> * fix(runner): use manifest kind as discriminator for duplicate createService status names Signed-off-by: Maximilian Techritz <maximilian.techritz@sap.com> * todo: temporarily grant full access for all service resources Signed-off-by: Maximilian Techritz <maximilian.techritz@sap.com> * fix(runner): address review comments on createService cleanup Signed-off-by: Maximilian Techritz <maximilian.techritz@sap.com> --------- Signed-off-by: Maximilian Techritz <maximilian.techritz@sap.com>
1 parent fbd9f41 commit 971d49c

9 files changed

Lines changed: 511 additions & 33 deletions

File tree

cmd/platform-service-test-runner/app/run.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,12 @@ func (o *RunOptions) Run(ctx context.Context) error {
218218
Resources: []string{"namespaces", "secrets", "configmaps"},
219219
Verbs: []string{"*"},
220220
},
221+
// TODO: temporarily grant full access for *.services.open-control-plane.io
222+
{
223+
APIGroups: []string{"*"},
224+
Resources: []string{"*"},
225+
Verbs: []string{"*"},
226+
},
221227
},
222228
},
223229
})
@@ -267,6 +273,7 @@ func (o *RunOptions) Run(ctx context.Context) error {
267273
testRegistry.RegisterTestCase("createProject", &runner.CreateProjectTest{OnboardingClient: onboardingCluster.Client()})
268274
testRegistry.RegisterTestCase("createWorkspace", &runner.CreateWorkspaceTest{OnboardingClient: onboardingCluster.Client()})
269275
testRegistry.RegisterTestCase("createControlPlane", &runner.CreateControlPlaneTest{OnboardingClient: onboardingCluster.Client()})
276+
testRegistry.RegisterTestCase("createService", &runner.CreateServiceTest{OnboardingClient: onboardingCluster.Client()})
270277

271278
// setup TestRun reconciler
272279
if err := e2etestrun.NewE2ETestRunReconciler(o.PlatformCluster, mgr.GetEventRecorder(e2etestrun.ControllerName), identity, testRegistry).SetupWithManager(mgr); err != nil {

internal/controller/e2etestrun/e2etestrun_controller.go

Lines changed: 45 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -78,39 +78,41 @@ func (r *E2ETestRunReconciler) runTestCases(ctx context.Context, log logging.Log
7878
return fmt.Errorf("test not found in registry, testName %s", testCaseSpec.Name)
7979
}
8080

81-
existingStatus, found := runner.GetStatus(testCaseSpec.Name, run.Status.TestCases)
82-
// if already passed -> skip
83-
if found && isTestCasePassed(*existingStatus) {
84-
log.Info("Skipping already passed test", "testName", testCaseSpec.Name)
85-
continue
86-
}
87-
// if already failed -> skip the rest of the tests
88-
if found && isTestCaseFailed(*existingStatus) {
89-
log.Info("Skipping test and the rest of the tests due to previous failure", "testName", testCaseSpec.Name)
90-
return nil
91-
}
92-
9381
config, err := readConfig(testCaseSpec.Config)
9482
if err != nil {
9583
log.Error(err, "error reading test case config", "testName", testCaseSpec.Name)
96-
if statusErr := r.updateStatusAfterRun(ctx, log, run, testCaseSpec, TestStatusFailed, nil, nil, err); statusErr != nil {
84+
if statusErr := r.updateStatusAfterRun(ctx, log, run, testCaseSpec.Name, TestStatusFailed, nil, nil, err); statusErr != nil {
9785
return statusErr
9886
}
9987
return err
10088
}
10189
config["identity"] = r.identity
10290

103-
log.Info("Running test", "testName", testCaseSpec.Name)
91+
statusName := testCase.StatusName(config)
92+
93+
existingStatus, found := runner.GetStatus(statusName, run.Status.TestCases)
94+
// if already passed -> skip
95+
if found && isTestCasePassed(*existingStatus) {
96+
log.Info("Skipping already passed test", "testName", statusName)
97+
continue
98+
}
99+
// if already failed -> skip the rest of the tests
100+
if found && isTestCaseFailed(*existingStatus) {
101+
log.Info("Skipping test and the rest of the tests due to previous failure", "testName", statusName)
102+
return nil
103+
}
104+
105+
log.Info("Running test", "testName", statusName)
104106
testExports, debugInfo, err := testCase.Run(ctx, run, config)
105107
if err != nil {
106-
log.Error(err, "error running test", "testName", testCaseSpec.Name)
107-
if statusErr := r.updateStatusAfterRun(ctx, log, run, testCaseSpec, TestStatusFailed, testExports, debugInfo, err); statusErr != nil {
108+
log.Error(err, "error running test", "testName", statusName)
109+
if statusErr := r.updateStatusAfterRun(ctx, log, run, statusName, TestStatusFailed, testExports, debugInfo, err); statusErr != nil {
108110
return statusErr
109111
}
110112
return err
111113
}
112114

113-
if statusErr := r.updateStatusAfterRun(ctx, log, run, testCaseSpec, TestStatusPassed, testExports, debugInfo, err); statusErr != nil {
115+
if statusErr := r.updateStatusAfterRun(ctx, log, run, statusName, TestStatusPassed, testExports, debugInfo, err); statusErr != nil {
114116
return statusErr
115117
}
116118
}
@@ -127,28 +129,32 @@ func (r *E2ETestRunReconciler) cleanupTestCases(ctx context.Context, log logging
127129
continue
128130
}
129131

130-
existingStatus, found := runner.GetStatus(testCaseSpec.Name, run.Status.TestCases)
131-
// if test case did not pass -> abort cleanup
132-
if !found || !isTestCasePassed(*existingStatus) {
133-
log.Info("Skipping cleanup", "testName", testCaseSpec.Name)
134-
break
135-
}
136-
137132
config, err := readConfig(testCaseSpec.Config)
138133
if err != nil {
139-
log.Error(err, "error reading test case config", "testName", testCaseSpec.Name)
140-
if statusErr := r.updateStatusAfterRun(ctx, log, run, testCaseSpec, TestStatusFailed, nil, nil, err); statusErr != nil {
141-
return statusErr
142-
}
134+
log.Error(err, "error reading test case config during cleanup", "testName", testCaseSpec.Name)
143135
return err
144136
}
145137
config["identity"] = r.identity
146138

147-
log.Info("Running cleanup for test", "testName", testCaseSpec.Name)
139+
statusName := test.StatusName(config)
140+
141+
existingStatus, found := runner.GetStatus(statusName, run.Status.TestCases)
142+
// if test case did not pass -> abort cleanup
143+
if !found || !isTestCasePassed(*existingStatus) {
144+
log.Info("Skipping cleanup", "testName", statusName)
145+
break
146+
}
147+
// if already cleaned up successfully -> skip
148+
if isTestCaseCleanupSucceeded(*existingStatus) {
149+
log.Info("Cleanup already completed, skipping", "testName", statusName)
150+
continue
151+
}
152+
153+
log.Info("Running cleanup for test", "testName", statusName)
148154
cleanupErr := test.Cleanup(ctx, run, config)
149155

150156
// Update test case status condition based on cleanup result
151-
if err := r.updateStatusAfterCleanup(ctx, log, run, testCaseSpec.Name, cleanupErr); err != nil {
157+
if err := r.updateStatusAfterCleanup(ctx, log, run, statusName, cleanupErr); err != nil {
152158
return err
153159
}
154160

@@ -204,14 +210,14 @@ func (r *E2ETestRunReconciler) updateStatusAfterRun(
204210
ctx context.Context,
205211
log logging.Logger,
206212
run *testingopenmcpcloudv1alpha1.E2ETestRun,
207-
testCase testingopenmcpcloudv1alpha1.TestCase,
213+
statusName string,
208214
status string,
209215
exports runner.Exports,
210216
debugIngo runner.DebugInfo,
211217
err error) error {
212-
tcStatus, statusErr := r.toApiTestCaseStatus(testCase.Name, status, exports, debugIngo, err)
218+
tcStatus, statusErr := r.toApiTestCaseStatus(statusName, status, exports, debugIngo, err)
213219
if statusErr != nil {
214-
log.Error(err, "error creating test case status", "testName", testCase.Name)
220+
log.Error(err, "error creating test case status", "testName", statusName)
215221
return statusErr
216222
}
217223
run.Status.TestCases = append(run.Status.TestCases, tcStatus)
@@ -282,6 +288,12 @@ func isTestCaseCleanupFailed(status testingopenmcpcloudv1alpha1.TestCaseStatus)
282288
return cond != nil && cond.Status == metav1.ConditionFalse
283289
}
284290

291+
// isTestCaseCleanupSucceeded checks if a test case cleanup has already completed successfully.
292+
func isTestCaseCleanupSucceeded(status testingopenmcpcloudv1alpha1.TestCaseStatus) bool {
293+
cond := conditions.GetCondition(status.Conditions, testingopenmcpcloudv1alpha1.TestCaseConditionCleanupCompleted)
294+
return cond != nil && cond.Status == metav1.ConditionTrue
295+
}
296+
285297
// setTestCaseCondition updates or adds a condition to a test case status using the conditions updater
286298
func setTestCaseCondition(status *testingopenmcpcloudv1alpha1.TestCaseStatus, conditionType string, conditionStatus metav1.ConditionStatus, reason, message string) {
287299
updatedConditions, _ := conditions.ConditionUpdater(status.Conditions, false).

internal/controller/e2etestrun/faketest.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ type fakeTest struct {
1616
cleanupCalled bool
1717
}
1818

19+
func (ft *fakeTest) StatusName(_ runner.Config) string { return "fakeTest" }
20+
1921
func (ft *fakeTest) Run(_ context.Context, run *v1alpha1.E2ETestRun, config runner.Config) (runner.Exports, runner.DebugInfo, error) {
2022
ft.runCalled = true
2123
ft.receivedRun = run

internal/runner/createcontrolplane.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ type CreateControlPlaneTest struct {
2727
OnboardingClient client.Client
2828
}
2929

30+
func (c *CreateControlPlaneTest) StatusName(_ Config) string { return createControlPlane }
31+
3032
// Run creates a ControlPlane in the workspace created by the createWorkspace test case, with the given configuration, and waits until it's ready.
3133
// It returns the ControlPlane name and namespace as exports for other test cases to use.
3234
func (c *CreateControlPlaneTest) Run(ctx context.Context, run *v1alpha1.E2ETestRun, config Config) (Exports, DebugInfo, error) {

internal/runner/createproject.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ type CreateProjectTest struct {
3131
OnboardingClient client.Client
3232
}
3333

34+
func (c *CreateProjectTest) StatusName(_ Config) string { return createProject }
35+
3436
// Run creates a project with the given configuration and waits until it's ready.
3537
// It returns the project name and status namespace as exports for other test cases to use.
3638
// It reads chargingTarget and chargingTargetType from the config to set labels for cost allocation, if provided.

0 commit comments

Comments
 (0)