generated from kyma-project/template-repository
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into support-fractional-cpu
- Loading branch information
Showing
6 changed files
with
354 additions
and
196 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
package process | ||
|
||
import ( | ||
"sort" | ||
"time" | ||
|
||
kebruntime "github.com/kyma-project/kyma-environment-broker/common/runtime" | ||
) | ||
|
||
type runtimeState int | ||
|
||
const ( | ||
provisioning runtimeState = iota | ||
deprovisioning | ||
upgradingkyma | ||
upgradingcluster | ||
update | ||
suspension | ||
unsuspension | ||
) | ||
|
||
type simpleOperation struct { | ||
state runtimeState | ||
time time.Time | ||
succeeded bool | ||
} | ||
|
||
// isRuntimeTrackable determines if a runtime is trackable based on its operations. | ||
// A runtime is considered trackable if: | ||
// - It has a successful provisioning or unsuspension operation. | ||
// - It does not have a suspension or deprovisioning operation as the last operation. | ||
// - It has any other operation assuming the cluster was successfully provisioned and is billable. | ||
func isRuntimeTrackable(runtime kebruntime.RuntimeDTO) bool { | ||
// Sort operations by time | ||
operations := sortOperations(runtime) | ||
|
||
// If a cluster does not have any operations, it is not trackable | ||
if len(operations) == 0 { | ||
return false | ||
} | ||
|
||
// Get the last operation | ||
lastOperation := operations[len(operations)-1] | ||
|
||
// Determine trackability based on the last operation state | ||
//nolint:exhaustive // we only care about the four states, not the others | ||
switch lastOperation.state { | ||
case provisioning, unsuspension: | ||
return lastOperation.succeeded | ||
case suspension, deprovisioning: | ||
return false | ||
default: | ||
return true | ||
} | ||
} | ||
|
||
func newSimpleOperation(state runtimeState, operation kebruntime.Operation) simpleOperation { | ||
return simpleOperation{ | ||
state: state, | ||
time: operation.CreatedAt, | ||
succeeded: operationSucceeded(operation), | ||
} | ||
} | ||
|
||
func operationSucceeded(operation kebruntime.Operation) bool { | ||
return operation.State == string(kebruntime.StateSucceeded) | ||
} | ||
|
||
func sortOperations(runtime kebruntime.RuntimeDTO) []simpleOperation { | ||
var operations []simpleOperation | ||
if runtime.Status.Provisioning != nil { | ||
operations = append(operations, newSimpleOperation(provisioning, *runtime.Status.Provisioning)) | ||
} | ||
|
||
if runtime.Status.Deprovisioning != nil { | ||
operations = append(operations, newSimpleOperation(deprovisioning, *runtime.Status.Deprovisioning)) | ||
} | ||
|
||
if runtime.Status.UpgradingKyma != nil { | ||
for _, op := range runtime.Status.UpgradingKyma.Data { | ||
operations = append(operations, newSimpleOperation(upgradingkyma, op)) | ||
} | ||
} | ||
|
||
if runtime.Status.UpgradingCluster != nil { | ||
for _, op := range runtime.Status.UpgradingCluster.Data { | ||
operations = append(operations, newSimpleOperation(upgradingcluster, op)) | ||
} | ||
} | ||
|
||
if runtime.Status.Update != nil { | ||
for _, op := range runtime.Status.Update.Data { | ||
operations = append(operations, newSimpleOperation(update, op)) | ||
} | ||
} | ||
|
||
if runtime.Status.Suspension != nil { | ||
for _, op := range runtime.Status.Suspension.Data { | ||
operations = append(operations, newSimpleOperation(suspension, op)) | ||
} | ||
} | ||
|
||
if runtime.Status.Unsuspension != nil { | ||
for _, op := range runtime.Status.Unsuspension.Data { | ||
operations = append(operations, newSimpleOperation(unsuspension, op)) | ||
} | ||
} | ||
|
||
// sort operations by time | ||
sort.Slice(operations, func(i, j int) bool { | ||
return operations[i].time.Before(operations[j].time) | ||
}) | ||
|
||
return operations | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
package process | ||
|
||
import ( | ||
"testing" | ||
"time" | ||
|
||
kebruntime "github.com/kyma-project/kyma-environment-broker/common/runtime" | ||
"github.com/onsi/gomega" | ||
) | ||
|
||
// TestSortOperations tests the sortOperations function. | ||
func TestSortOperations(t *testing.T) { | ||
g := gomega.NewGomegaWithT(t) | ||
|
||
testCases := []struct { | ||
name string | ||
runtime kebruntime.RuntimeDTO | ||
expected []runtimeState | ||
expectedLen int | ||
}{ | ||
{ | ||
name: "should sort operations by time", | ||
runtime: kebruntime.RuntimeDTO{ | ||
Status: kebruntime.RuntimeStatus{ | ||
Provisioning: &kebruntime.Operation{ | ||
CreatedAt: time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC), | ||
}, | ||
Deprovisioning: &kebruntime.Operation{ | ||
CreatedAt: time.Date(2023, 1, 2, 0, 0, 0, 0, time.UTC), | ||
}, | ||
UpgradingKyma: &kebruntime.OperationsData{Data: []kebruntime.Operation{ | ||
{CreatedAt: time.Date(2023, 1, 3, 0, 0, 0, 0, time.UTC)}, | ||
}}, | ||
UpgradingCluster: &kebruntime.OperationsData{Data: []kebruntime.Operation{ | ||
{CreatedAt: time.Date(2023, 1, 4, 0, 0, 0, 0, time.UTC)}, | ||
}}, | ||
Update: &kebruntime.OperationsData{Data: []kebruntime.Operation{ | ||
{CreatedAt: time.Date(2023, 1, 5, 0, 0, 0, 0, time.UTC)}, | ||
}}, | ||
Suspension: &kebruntime.OperationsData{Data: []kebruntime.Operation{ | ||
{CreatedAt: time.Date(2023, 1, 6, 0, 0, 0, 0, time.UTC)}, | ||
}}, | ||
Unsuspension: &kebruntime.OperationsData{Data: []kebruntime.Operation{ | ||
{CreatedAt: time.Date(2023, 1, 7, 0, 0, 0, 0, time.UTC)}, | ||
}}, | ||
}, | ||
}, | ||
expected: []runtimeState{provisioning, deprovisioning, upgradingkyma, upgradingcluster, update, suspension, unsuspension}, | ||
expectedLen: 7, | ||
}, | ||
{ | ||
name: "should handle multiple suspensions and following unsuspensions", | ||
runtime: kebruntime.RuntimeDTO{ | ||
Status: kebruntime.RuntimeStatus{ | ||
Suspension: &kebruntime.OperationsData{Data: []kebruntime.Operation{ | ||
{CreatedAt: time.Date(2023, 1, 6, 0, 0, 0, 0, time.UTC)}, | ||
{CreatedAt: time.Date(2023, 1, 8, 0, 0, 0, 0, time.UTC)}, | ||
}}, | ||
Unsuspension: &kebruntime.OperationsData{Data: []kebruntime.Operation{ | ||
{CreatedAt: time.Date(2023, 1, 7, 0, 0, 0, 0, time.UTC)}, | ||
{CreatedAt: time.Date(2023, 1, 9, 0, 0, 0, 0, time.UTC)}, | ||
}}, | ||
}, | ||
}, | ||
expected: []runtimeState{suspension, unsuspension, suspension, unsuspension}, | ||
expectedLen: 4, | ||
}, | ||
{ | ||
name: "should handle empty operations", | ||
runtime: kebruntime.RuntimeDTO{ | ||
Status: kebruntime.RuntimeStatus{}, | ||
}, | ||
expected: []runtimeState{}, | ||
expectedLen: 0, | ||
}, | ||
{ | ||
name: "should handle nil operation times", | ||
runtime: kebruntime.RuntimeDTO{ | ||
Status: kebruntime.RuntimeStatus{ | ||
Provisioning: &kebruntime.Operation{}, | ||
Deprovisioning: &kebruntime.Operation{}, | ||
}, | ||
}, | ||
expected: []runtimeState{provisioning, deprovisioning}, | ||
expectedLen: 2, | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
operations := sortOperations(tc.runtime) | ||
|
||
g.Expect(operations).To(gomega.HaveLen(tc.expectedLen)) | ||
|
||
for i, op := range operations { | ||
g.Expect(op.state).To(gomega.Equal(tc.expected[i])) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestIsRuntimeTrackable(t *testing.T) { | ||
g := gomega.NewGomegaWithT(t) | ||
|
||
testCases := []struct { | ||
name string | ||
runtime kebruntime.RuntimeDTO | ||
expected bool | ||
}{ | ||
{ | ||
name: "should return true for successful provisioning", | ||
runtime: kebruntime.RuntimeDTO{ | ||
Status: kebruntime.RuntimeStatus{ | ||
Provisioning: &kebruntime.Operation{ | ||
CreatedAt: time.Now(), | ||
State: string(kebruntime.StateSucceeded), | ||
}, | ||
}, | ||
}, | ||
expected: true, | ||
}, | ||
{ | ||
name: "should return false for suspension", | ||
runtime: kebruntime.RuntimeDTO{ | ||
Status: kebruntime.RuntimeStatus{ | ||
Suspension: &kebruntime.OperationsData{Data: []kebruntime.Operation{ | ||
{CreatedAt: time.Now()}, | ||
}}, | ||
}, | ||
}, | ||
expected: false, | ||
}, | ||
{ | ||
name: "should return false for failing provisioning", | ||
runtime: kebruntime.RuntimeDTO{ | ||
Status: kebruntime.RuntimeStatus{ | ||
Provisioning: &kebruntime.Operation{ | ||
CreatedAt: time.Now(), | ||
State: string(kebruntime.StateFailed), | ||
}, | ||
}, | ||
}, | ||
expected: false, | ||
}, | ||
{ | ||
name: "should return false for failing unsuspension", | ||
runtime: kebruntime.RuntimeDTO{ | ||
Status: kebruntime.RuntimeStatus{ | ||
Unsuspension: &kebruntime.OperationsData{Data: []kebruntime.Operation{ | ||
{CreatedAt: time.Now(), State: string(kebruntime.StateFailed)}, | ||
}}, | ||
}, | ||
}, | ||
expected: false, | ||
}, | ||
{ | ||
name: "should return true for successful unsuspension", | ||
runtime: kebruntime.RuntimeDTO{ | ||
Status: kebruntime.RuntimeStatus{ | ||
Unsuspension: &kebruntime.OperationsData{Data: []kebruntime.Operation{ | ||
{CreatedAt: time.Now(), State: string(kebruntime.StateSucceeded)}, | ||
}}, | ||
}, | ||
}, | ||
expected: true, | ||
}, | ||
{ | ||
name: "should return false for deprovisioning", | ||
runtime: kebruntime.RuntimeDTO{ | ||
Status: kebruntime.RuntimeStatus{ | ||
Deprovisioning: &kebruntime.Operation{CreatedAt: time.Now()}, | ||
}, | ||
}, | ||
expected: false, | ||
}, | ||
{ | ||
name: "should return false for empty operations", | ||
runtime: kebruntime.RuntimeDTO{ | ||
Status: kebruntime.RuntimeStatus{}, | ||
}, | ||
expected: false, | ||
}, | ||
{ | ||
name: "should return true for other operations", | ||
runtime: kebruntime.RuntimeDTO{ | ||
Status: kebruntime.RuntimeStatus{ | ||
Update: &kebruntime.OperationsData{Data: []kebruntime.Operation{ | ||
{CreatedAt: time.Now()}, | ||
}}, | ||
}, | ||
}, | ||
expected: true, | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
result := isRuntimeTrackable(tc.runtime) | ||
g.Expect(result).To(gomega.Equal(tc.expected)) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.