Skip to content

Commit

Permalink
feat: commitment scaling strategy (#312)
Browse files Browse the repository at this point in the history
* feat: commitment scaling strategy

* update docs

* PRICE-195: update

* PRICE-195: generate sdk

* PRICE-195: update

* PRICE-195: update tests

* PRICE-195: update test

* PRICE-195: update tests
  • Loading branch information
ivanstankovcast authored May 17, 2024
1 parent 3e25bed commit 25c75f0
Show file tree
Hide file tree
Showing 7 changed files with 193 additions and 88 deletions.
12 changes: 12 additions & 0 deletions castai/resource_commitments.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ var (
Required: true,
Description: "Region in which the CUD is available.",
},
"scaling_strategy": {
Type: schema.TypeString,
Optional: true,
Description: "Scaling strategy of the commitment in CAST AI. One of: Default, CPUBased, RamBased",
ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"Default", "CPUBased", "RamBased"}, false)),
},
})

commitmentAssignmentsSchema = map[string]*schema.Schema{
Expand Down Expand Up @@ -176,6 +182,12 @@ func resourceCommitments() *schema.Resource {
Description: "Allowed usage of the commitment. The value is between 0 (0%) and 1 (100%).",
ValidateDiagFunc: validation.ToDiagFunc(validation.FloatBetween(0, 1)),
},
"scaling_strategy": {
Type: schema.TypeString,
Optional: true,
Description: "Scaling strategy of the commitment in CAST AI. One of: Default, CPUBased, RamBased",
ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"Default", "CPUBased", "RamBased"}, false)),
},
}),
},
},
Expand Down
56 changes: 36 additions & 20 deletions castai/resource_commitments_mapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ type (

// NOTE: This type needs to be exported for mapstructure's `squash` tag to work properly
CASTCommitmentFields struct {
ID *string `mapstructure:"id,omitempty"` // ID of the commitment
AllowedUsage *float64 `mapstructure:"allowed_usage,omitempty"`
Prioritization *bool `mapstructure:"prioritization,omitempty"`
Status *string `mapstructure:"status,omitempty"`
Assignments []*commitmentAssignmentResource `mapstructure:"assignments,omitempty"`
ID *string `mapstructure:"id,omitempty"` // ID of the commitment
AllowedUsage *float64 `mapstructure:"allowed_usage,omitempty"`
Prioritization *bool `mapstructure:"prioritization,omitempty"`
Status *string `mapstructure:"status,omitempty"`
Assignments []*commitmentAssignmentResource `mapstructure:"assignments,omitempty"`
ScalingStrategy *string `mapstructure:"scaling_strategy,omitempty"`
}

gcpCUDResource struct {
Expand Down Expand Up @@ -69,11 +70,12 @@ type (
}

commitmentConfigResource struct {
Matcher []*commitmentConfigMatcherResource `mapstructure:"matcher,omitempty"`
Prioritization *bool `mapstructure:"prioritization,omitempty"`
Status *string `mapstructure:"status,omitempty"`
AllowedUsage *float64 `mapstructure:"allowed_usage,omitempty"`
Assignments []*commitmentAssignmentResource `mapstructure:"assignments,omitempty"`
Matcher []*commitmentConfigMatcherResource `mapstructure:"matcher,omitempty"`
Prioritization *bool `mapstructure:"prioritization,omitempty"`
Status *string `mapstructure:"status,omitempty"`
AllowedUsage *float64 `mapstructure:"allowed_usage,omitempty"`
Assignments []*commitmentAssignmentResource `mapstructure:"assignments,omitempty"`
ScalingStrategy *string `mapstructure:"scaling_strategy,omitempty"`
}
commitmentConfigMatcherResource struct {
Name string `mapstructure:"name"`
Expand Down Expand Up @@ -183,11 +185,12 @@ func mapCommitmentToCUDResource(

return &gcpCUDResource{
CASTCommitmentFields: CASTCommitmentFields{
ID: c.Id,
AllowedUsage: float32PtrToFloat64Ptr(c.AllowedUsage, 2),
Prioritization: c.Prioritization,
Status: (*string)(c.Status),
Assignments: mapCommitmentAssignmentsToResources(as, lo.FromPtr(c.Prioritization)),
ID: c.Id,
AllowedUsage: float32PtrToFloat64Ptr(c.AllowedUsage, 2),
Prioritization: c.Prioritization,
Status: (*string)(c.Status),
Assignments: mapCommitmentAssignmentsToResources(as, lo.FromPtr(c.Prioritization)),
ScalingStrategy: (*string)(c.ScalingStrategy),
},
CUDID: lo.FromPtr(c.GcpResourceCudContext.CudId),
CUDStatus: lo.FromPtr(c.GcpResourceCudContext.Status),
Expand Down Expand Up @@ -219,11 +222,12 @@ func mapCommitmentToReservationResource(
}
return &azureReservationResource{
CASTCommitmentFields: CASTCommitmentFields{
ID: c.Id,
AllowedUsage: float32PtrToFloat64Ptr(c.AllowedUsage, 2),
Prioritization: c.Prioritization,
Status: (*string)(c.Status),
Assignments: mapCommitmentAssignmentsToResources(as, lo.FromPtr(c.Prioritization)),
ID: c.Id,
AllowedUsage: float32PtrToFloat64Ptr(c.AllowedUsage, 2),
Prioritization: c.Prioritization,
Status: (*string)(c.Status),
Assignments: mapCommitmentAssignmentsToResources(as, lo.FromPtr(c.Prioritization)),
ScalingStrategy: (*string)(c.ScalingStrategy),
},
Count: int(lo.FromPtr(c.AzureReservationContext.Count)),
ReservationID: lo.FromPtr(c.AzureReservationContext.Id),
Expand Down Expand Up @@ -294,6 +298,10 @@ func mapCUDImportToResource(
if lo.FromPtr(cudWithCfg.Config.Prioritization) {
assignPrioritiesToAssignments(res.Assignments)
}
res.ScalingStrategy = cudWithCfg.Config.ScalingStrategy
}
if res.ScalingStrategy == nil {
res.ScalingStrategy = lo.ToPtr("Default")
}
return res, nil
}
Expand Down Expand Up @@ -335,6 +343,10 @@ func mapReservationImportToResource(
if lo.FromPtr(cudWithCfg.Config.Prioritization) {
assignPrioritiesToAssignments(res.Assignments)
}
res.ScalingStrategy = cudWithCfg.Config.ScalingStrategy
}
if res.ScalingStrategy == nil {
res.ScalingStrategy = lo.ToPtr("Default")
}

return res, nil
Expand Down Expand Up @@ -505,6 +517,7 @@ func mapCommitmentImportWithConfigToUpdateRequest(
Region: c.Commitment.Region,
StartDate: c.Commitment.StartDate,
Status: c.Commitment.Status,
ScalingStrategy: c.Commitment.ScalingStrategy,
}
if c.Config != nil {
if c.Config.AllowedUsage != nil {
Expand All @@ -516,6 +529,9 @@ func mapCommitmentImportWithConfigToUpdateRequest(
if c.Config.Status != nil {
req.Status = (*sdk.CastaiInventoryV1beta1CommitmentStatus)(c.Config.Status)
}
if c.Config.ScalingStrategy != nil {
req.ScalingStrategy = (*sdk.CastaiInventoryV1beta1CommitmentScalingStrategy)(c.Config.ScalingStrategy)
}
}
return req
}
Expand Down
75 changes: 56 additions & 19 deletions castai/resource_commitments_mapping_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,14 @@ func TestMapCommitmentToCUDResource(t *testing.T) {
Status: lo.ToPtr("ACTIVE"),
Type: lo.ToPtr("COMPUTE_OPTIMIZED_C2D"),
},
Id: lo.ToPtr(id1.String()),
Name: lo.ToPtr("test-cud"),
Prioritization: lo.ToPtr(true),
Region: lo.ToPtr("us-central1"),
StartDate: lo.ToPtr(endTs),
Status: lo.ToPtr[sdk.CastaiInventoryV1beta1CommitmentStatus]("ACTIVE"),
UpdatedAt: lo.ToPtr(now),
Id: lo.ToPtr(id1.String()),
Name: lo.ToPtr("test-cud"),
Prioritization: lo.ToPtr(true),
Region: lo.ToPtr("us-central1"),
StartDate: lo.ToPtr(endTs),
Status: lo.ToPtr[sdk.CastaiInventoryV1beta1CommitmentStatus]("ACTIVE"),
UpdatedAt: lo.ToPtr(now),
ScalingStrategy: lo.ToPtr[sdk.CastaiInventoryV1beta1CommitmentScalingStrategy]("Default"),
}
}

Expand All @@ -61,6 +62,7 @@ func TestMapCommitmentToCUDResource(t *testing.T) {
{ClusterID: "cluster-id-1"},
{ClusterID: "cluster-id-2"},
},
ScalingStrategy: lo.ToPtr("Default"),
},
CUDID: "123456",
CUDStatus: "ACTIVE",
Expand Down Expand Up @@ -102,6 +104,7 @@ func TestMapCommitmentToCUDResource(t *testing.T) {
{ClusterID: "cluster-id-1"},
{ClusterID: "cluster-id-2"},
},
ScalingStrategy: lo.ToPtr("Default"),
},
CUDID: "123456",
CUDStatus: "ACTIVE",
Expand Down Expand Up @@ -134,6 +137,7 @@ func TestMapCommitmentToCUDResource(t *testing.T) {
{ClusterID: "cluster-id-1"},
{ClusterID: "cluster-id-2"},
},
ScalingStrategy: lo.ToPtr("Default"),
},
CUDID: "123456",
CUDStatus: "ACTIVE",
Expand Down Expand Up @@ -301,6 +305,9 @@ func TestMapCUDImportToResource(t *testing.T) {
MemoryMb: 20480,
Plan: "TWELVE_MONTHS",
Type: "COMPUTE_OPTIMIZED_C2D",
CASTCommitmentFields: CASTCommitmentFields{
ScalingStrategy: lo.ToPtr("Default"),
},
},
},
"should succeed, nil cud resources": {
Expand All @@ -318,6 +325,9 @@ func TestMapCUDImportToResource(t *testing.T) {
Region: "us-central1",
Plan: "TWELVE_MONTHS",
Type: "COMPUTE_OPTIMIZED_C2D",
CASTCommitmentFields: CASTCommitmentFields{
ScalingStrategy: lo.ToPtr("Default"),
},
},
},
"should succeed, with a config passed": {
Expand All @@ -331,9 +341,10 @@ func TestMapCUDImportToResource(t *testing.T) {
Region: lo.ToPtr("us-central1"),
},
},
Prioritization: lo.ToPtr(true),
Status: lo.ToPtr("ACTIVE"),
AllowedUsage: lo.ToPtr(0.7),
Prioritization: lo.ToPtr(true),
Status: lo.ToPtr("ACTIVE"),
AllowedUsage: lo.ToPtr(0.7),
ScalingStrategy: lo.ToPtr("CPUBased"),
}
return c
}(),
Expand All @@ -350,9 +361,10 @@ func TestMapCUDImportToResource(t *testing.T) {
Type: "COMPUTE_OPTIMIZED_C2D",
// Configured fields
CASTCommitmentFields: CASTCommitmentFields{
Prioritization: lo.ToPtr(true),
Status: lo.ToPtr("ACTIVE"),
AllowedUsage: lo.ToPtr(0.7),
Prioritization: lo.ToPtr(true),
Status: lo.ToPtr("ACTIVE"),
AllowedUsage: lo.ToPtr(0.7),
ScalingStrategy: lo.ToPtr("CPUBased"),
},
},
},
Expand Down Expand Up @@ -392,6 +404,9 @@ func TestMapCUDImportToResource(t *testing.T) {
MemoryMb: 20480,
Plan: "TWELVE_MONTHS",
Type: "COMPUTE_OPTIMIZED_C2D",
CASTCommitmentFields: CASTCommitmentFields{
ScalingStrategy: lo.ToPtr("Default"),
},
},
},
"should succeed with zeroed out memory as its resource is not contained by the resources": {
Expand All @@ -410,6 +425,9 @@ func TestMapCUDImportToResource(t *testing.T) {
CPU: 10,
Plan: "TWELVE_MONTHS",
Type: "COMPUTE_OPTIMIZED_C2D",
CASTCommitmentFields: CASTCommitmentFields{
ScalingStrategy: lo.ToPtr("Default"),
},
},
},
}
Expand Down Expand Up @@ -459,6 +477,9 @@ func TestMapReservationImportToResource(t *testing.T) {
Scope: lo.FromPtr(testAzureCommitmentImport.Scope),
ScopeResourceGroup: lo.FromPtr(testAzureCommitmentImport.ScopeResourceGroup),
ScopeSubscription: lo.FromPtr(testAzureCommitmentImport.ScopeSubscription),
CASTCommitmentFields: CASTCommitmentFields{
ScalingStrategy: lo.ToPtr("Default"),
},
},
},
"should succeed, with a config passed": {
Expand All @@ -472,17 +493,19 @@ func TestMapReservationImportToResource(t *testing.T) {
Region: testAzureCommitmentImport.Region,
},
},
Prioritization: lo.ToPtr(true),
Status: lo.ToPtr("ACTIVE"),
AllowedUsage: lo.ToPtr(0.7),
Prioritization: lo.ToPtr(true),
Status: lo.ToPtr("ACTIVE"),
AllowedUsage: lo.ToPtr(0.7),
ScalingStrategy: lo.ToPtr("CPUBased"),
}
return c
}(),
expected: &azureReservationResource{
CASTCommitmentFields: CASTCommitmentFields{
AllowedUsage: lo.ToPtr(0.7),
Prioritization: lo.ToPtr(true),
Status: lo.ToPtr("ACTIVE"),
AllowedUsage: lo.ToPtr(0.7),
Prioritization: lo.ToPtr(true),
Status: lo.ToPtr("ACTIVE"),
ScalingStrategy: lo.ToPtr("CPUBased"),
},
Count: 2,
ReservationID: lo.FromPtr(testAzureCommitmentImport.ReservationId),
Expand All @@ -508,6 +531,9 @@ func TestMapReservationImportToResource(t *testing.T) {
},
expected: &azureReservationResource{
Plan: "ONE_YEAR",
CASTCommitmentFields: CASTCommitmentFields{
ScalingStrategy: lo.ToPtr("Default"),
},
},
},
"should map P3Y term to THREE_YEAR plan": {
Expand All @@ -520,6 +546,9 @@ func TestMapReservationImportToResource(t *testing.T) {
},
expected: &azureReservationResource{
Plan: "THREE_YEAR",
CASTCommitmentFields: CASTCommitmentFields{
ScalingStrategy: lo.ToPtr("Default"),
},
},
},
"should map ONE_YEAR term to ONE_YEAR plan": {
Expand All @@ -532,6 +561,9 @@ func TestMapReservationImportToResource(t *testing.T) {
},
expected: &azureReservationResource{
Plan: "ONE_YEAR",
CASTCommitmentFields: CASTCommitmentFields{
ScalingStrategy: lo.ToPtr("Default"),
},
},
},
"should map ONE_YEAR term to THREE_YEAR plan": {
Expand All @@ -544,6 +576,9 @@ func TestMapReservationImportToResource(t *testing.T) {
},
expected: &azureReservationResource{
Plan: "THREE_YEAR",
CASTCommitmentFields: CASTCommitmentFields{
ScalingStrategy: lo.ToPtr("Default"),
},
},
},
"should fail when invalid term is passed": {
Expand Down Expand Up @@ -932,6 +967,7 @@ func TestMapConfiguredCUDImportsToResources(t *testing.T) {
{ClusterID: "cluster-1", Priority: lo.ToPtr(1)},
{ClusterID: "cluster-2", Priority: lo.ToPtr(2)},
},
ScalingStrategy: lo.ToPtr("Default"),
},
CUDID: lo.FromPtr(testGCPCommitmentImport.Id),
CUDStatus: lo.FromPtr(testGCPCommitmentImport.Status),
Expand Down Expand Up @@ -1037,6 +1073,7 @@ func TestMapConfiguredReservationImportsToResources(t *testing.T) {
{ClusterID: "cluster-1", Priority: lo.ToPtr(1)},
{ClusterID: "cluster-2", Priority: lo.ToPtr(2)},
},
ScalingStrategy: lo.ToPtr("Default"),
},
Count: int(lo.FromPtr(testAzureCommitmentImport.Quantity)),
ReservationID: lo.FromPtr(testAzureCommitmentImport.ReservationId),
Expand Down
Loading

0 comments on commit 25c75f0

Please sign in to comment.