diff --git a/castai/resource_workload_scaling_policy.go b/castai/resource_workload_scaling_policy.go index fc5f6c1c..28cac43a 100644 --- a/castai/resource_workload_scaling_policy.go +++ b/castai/resource_workload_scaling_policy.go @@ -19,6 +19,14 @@ import ( "github.com/castai/terraform-provider-castai/castai/sdk" ) +const minResourceMultiplierValue = 1.0 + +const ( + FieldLimitStrategy = "limit" + FieldLimitStrategyType = "type" + FieldLimitStrategyMultiplier = "multiplier" +) + var ( k8sNameRegex = regexp.MustCompile("^[a-z0-9A-Z][a-z0-9A-Z._-]{0,61}[a-z0-9A-Z]$") ) @@ -51,7 +59,7 @@ func resourceWorkloadScalingPolicy() *schema.Resource { "apply_type": { Type: schema.TypeString, Required: true, - Description: `Recommendation apply type. + Description: `Recommendation apply type. - IMMEDIATE - pods are restarted immediately when new recommendation is generated. - DEFERRED - pods are not restarted and recommendation values are applied during natural restarts only (new deployment, etc.)`, ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"IMMEDIATE", "DEFERRED"}, false)), @@ -203,6 +211,34 @@ func workloadScalingPolicyResourceSchema(function string, overhead, minRecommend Optional: true, Description: "Max values for the recommendation, applies to every container. For memory - this is in MiB, for CPU - this is in cores.", }, + FieldLimitStrategy: { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: "Resource limit settings", + Elem: workloadScalingPolicyResourceLimitSchema(), + }, + }, + } +} + +func workloadScalingPolicyResourceLimitSchema() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + FieldLimitStrategyType: { + Type: schema.TypeString, + Required: true, + Description: fmt.Sprintf(`Defines limit strategy type. + - %s - removes the resource limit even if it was specified in the workload spec. + - %s - used to calculate the resource limit. The final value is determined by multiplying the resource request by the specified factor.`, sdk.NOLIMIT, sdk.MULTIPLIER), + ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{string(sdk.MULTIPLIER), string(sdk.NOLIMIT)}, false)), + }, + FieldLimitStrategyMultiplier: { + Type: schema.TypeFloat, + Optional: true, + Description: "Multiplier used to calculate the resource limit. It must be defined for the MULTIPLIER strategy.", + ValidateDiagFunc: validation.ToDiagFunc(validation.FloatAtLeast(minResourceMultiplierValue)), + }, }, } } @@ -375,19 +411,44 @@ func resourceWorkloadScalingPolicyDiff(_ context.Context, d *schema.ResourceDiff cpu := toWorkloadScalingPolicies(d.Get("cpu").([]interface{})[0].(map[string]interface{})) memory := toWorkloadScalingPolicies(d.Get("memory").([]interface{})[0].(map[string]interface{})) - if err := validateArgs(cpu, "cpu"); err != nil { + if err := validateResourcePolicy(cpu, "cpu"); err != nil { return err } - return validateArgs(memory, "memory") + return validateResourcePolicy(memory, "memory") } -func validateArgs(r sdk.WorkloadoptimizationV1ResourcePolicies, res string) error { +func validateResourcePolicy(r sdk.WorkloadoptimizationV1ResourcePolicies, res string) error { if r.Function == "QUANTILE" && len(r.Args) == 0 { return fmt.Errorf("field %q: QUANTILE function requires args to be provided", res) } if r.Function == "MAX" && len(r.Args) > 0 { return fmt.Errorf("field %q: MAX function doesn't accept any args", res) } + + err := validateResourceLimit(r) + if err != nil { + return fmt.Errorf("field %q: %w", res, err) + } + return nil +} + +func validateResourceLimit(r sdk.WorkloadoptimizationV1ResourcePolicies) error { + if r.Limit == nil { + return nil + } + + switch r.Limit.Type { + case sdk.NOLIMIT: + if r.Limit.Multiplier != nil { + return fmt.Errorf(`field %q: %q limit type doesn't accept multiplier value`, FieldLimitStrategy, sdk.NOLIMIT) + } + case sdk.MULTIPLIER: + if r.Limit.Multiplier == nil { + return fmt.Errorf(`field %q: %q limit type requires multiplier value to be provided`, FieldLimitStrategy, sdk.MULTIPLIER) + } + default: + return fmt.Errorf(`field %q: unknown limit type %q`, FieldLimitStrategy, r.Limit.Type) + } return nil } @@ -449,10 +510,28 @@ func toWorkloadScalingPolicies(obj map[string]interface{}) sdk.Workloadoptimizat if v, ok := obj["max"].(float64); ok && v > 0 { out.Max = lo.ToPtr(v) } + if v, ok := obj[FieldLimitStrategy].([]any); ok && len(v) > 0 { + out.Limit = toWorkloadResourceLimit(v[0].(map[string]any)) + } return out } +func toWorkloadResourceLimit(obj map[string]any) *sdk.WorkloadoptimizationV1ResourceLimitStrategy { + if len(obj) == 0 { + return nil + } + + out := &sdk.WorkloadoptimizationV1ResourceLimitStrategy{} + if v, ok := obj[FieldLimitStrategyType].(string); ok { + out.Type = sdk.WorkloadoptimizationV1ResourceLimitStrategyType(v) + } + if v, ok := obj[FieldLimitStrategyMultiplier].(float64); ok && v > 0 { + out.Multiplier = lo.ToPtr(v) + } + return out +} + func toWorkloadScalingPoliciesMap(p sdk.WorkloadoptimizationV1ResourcePolicies) []map[string]interface{} { m := map[string]interface{}{ "function": p.Function, @@ -467,6 +546,16 @@ func toWorkloadScalingPoliciesMap(p sdk.WorkloadoptimizationV1ResourcePolicies) m["look_back_period_seconds"] = int(*p.LookBackPeriodSeconds) } + if p.Limit != nil { + limit := map[string]any{} + + limit[FieldLimitStrategyType] = p.Limit.Type + if p.Limit.Multiplier != nil { + limit[FieldLimitStrategyMultiplier] = *p.Limit.Multiplier + } + m[FieldLimitStrategy] = []map[string]any{limit} + } + return []map[string]interface{}{m} } diff --git a/castai/resource_workload_scaling_policy_test.go b/castai/resource_workload_scaling_policy_test.go index 26e26be9..348cadfa 100644 --- a/castai/resource_workload_scaling_policy_test.go +++ b/castai/resource_workload_scaling_policy_test.go @@ -11,6 +11,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/samber/lo" + "github.com/stretchr/testify/require" "github.com/castai/terraform-provider-castai/castai/sdk" ) @@ -39,11 +41,15 @@ func TestAccResourceWorkloadScalingPolicy(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "cpu.0.look_back_period_seconds", "86401"), resource.TestCheckResourceAttr(resourceName, "cpu.0.min", "0.1"), resource.TestCheckResourceAttr(resourceName, "cpu.0.max", "1"), + resource.TestCheckResourceAttr(resourceName, "cpu.0.limit.0.type", "MULTIPLIER"), + resource.TestCheckResourceAttr(resourceName, "cpu.0.limit.0.multiplier", "1.2"), resource.TestCheckResourceAttr(resourceName, "memory.0.function", "MAX"), resource.TestCheckResourceAttr(resourceName, "memory.0.overhead", "0.25"), resource.TestCheckResourceAttr(resourceName, "memory.0.apply_threshold", "0.1"), resource.TestCheckResourceAttr(resourceName, "memory.0.args.#", "0"), resource.TestCheckResourceAttr(resourceName, "memory.0.min", "100"), + resource.TestCheckResourceAttr(resourceName, "memory.0.limit.0.type", "MULTIPLIER"), + resource.TestCheckResourceAttr(resourceName, "memory.0.limit.0.multiplier", "1.8"), ), }, { @@ -67,12 +73,14 @@ func TestAccResourceWorkloadScalingPolicy(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "cpu.0.args.0", "0.9"), resource.TestCheckResourceAttr(resourceName, "cpu.0.look_back_period_seconds", "86402"), resource.TestCheckResourceAttr(resourceName, "cpu.0.min", "0.1"), + resource.TestCheckResourceAttr(resourceName, "cpu.0.limit.0.type", "NO_LIMIT"), resource.TestCheckResourceAttr(resourceName, "memory.0.function", "QUANTILE"), resource.TestCheckResourceAttr(resourceName, "memory.0.overhead", "0.35"), resource.TestCheckResourceAttr(resourceName, "memory.0.apply_threshold", "0.2"), resource.TestCheckResourceAttr(resourceName, "memory.0.args.0", "0.9"), resource.TestCheckResourceAttr(resourceName, "memory.0.min", "100"), resource.TestCheckResourceAttr(resourceName, "memory.0.max", "512"), + resource.TestCheckResourceAttr(resourceName, "memory.0.limit.0.type", "NO_LIMIT"), resource.TestCheckResourceAttr(resourceName, "startup.0.period_seconds", "123"), resource.TestCheckResourceAttr(resourceName, "downscaling.0.apply_type", "DEFERRED"), resource.TestCheckResourceAttr(resourceName, "memory_event.0.apply_type", "DEFERRED"), @@ -108,12 +116,20 @@ func scalingPolicyConfig(clusterName, projectID, name string) string { min = 0.1 max = 1 look_back_period_seconds = 86401 + limit { + type = "MULTIPLIER" + multiplier = 1.2 + } } memory { function = "MAX" overhead = 0.25 apply_threshold = 0.1 min = 100 + limit { + type = "MULTIPLIER" + multiplier = 1.8 + } } }`, name) @@ -135,6 +151,9 @@ func scalingPolicyConfigUpdated(clusterName, projectID, name string) string { args = ["0.9"] look_back_period_seconds = 86402 min = 0.1 + limit { + type = "NO_LIMIT" + } } memory { function = "QUANTILE" @@ -143,6 +162,9 @@ func scalingPolicyConfigUpdated(clusterName, projectID, name string) string { args = ["0.9"] min = 100 max = 512 + limit { + type = "NO_LIMIT" + } } startup { period_seconds = 123 @@ -152,7 +174,7 @@ func scalingPolicyConfigUpdated(clusterName, projectID, name string) string { } memory_event { apply_type = "DEFERRED" - } + } anti_affinity { consider_anti_affinity = true } @@ -187,10 +209,10 @@ func testAccCheckScalingPolicyDestroy(s *terraform.State) error { return nil } -func Test_validateArgs(t *testing.T) { +func Test_validateResourcePolicy(t *testing.T) { tests := map[string]struct { - args sdk.WorkloadoptimizationV1ResourcePolicies - wantErr bool + args sdk.WorkloadoptimizationV1ResourcePolicies + errMsg string }{ "should not return error when QUANTILE has args provided": { args: sdk.WorkloadoptimizationV1ResourcePolicies{ @@ -202,20 +224,40 @@ func Test_validateArgs(t *testing.T) { args: sdk.WorkloadoptimizationV1ResourcePolicies{ Function: "QUANTILE", }, - wantErr: true, + errMsg: `field "cpu": QUANTILE function requires args to be provided`, }, "should return error when MAX has args provided": { args: sdk.WorkloadoptimizationV1ResourcePolicies{ Function: "MAX", Args: []string{"0.5"}, }, - wantErr: true, + errMsg: `field "cpu": MAX function doesn't accept any args`, + }, + "should return error when no value is specified for the multiplier strategy": { + args: sdk.WorkloadoptimizationV1ResourcePolicies{ + Limit: &sdk.WorkloadoptimizationV1ResourceLimitStrategy{ + Type: sdk.MULTIPLIER, + }, + }, + errMsg: `field "cpu": field "limit": "MULTIPLIER" limit type requires multiplier value to be provided`, + }, + "should return error when a value is specified for the no limit strategy": { + args: sdk.WorkloadoptimizationV1ResourcePolicies{ + Limit: &sdk.WorkloadoptimizationV1ResourceLimitStrategy{ + Type: sdk.NOLIMIT, + Multiplier: lo.ToPtr(4.2), + }, + }, + errMsg: `field "cpu": field "limit": "NO_LIMIT" limit type doesn't accept multiplier value`, }, } for name, tt := range tests { t.Run(name, func(t *testing.T) { - if err := validateArgs(tt.args, ""); (err != nil) != tt.wantErr { - t.Errorf("validateArgs() error = %v, wantErr %v", err, tt.wantErr) + err := validateResourcePolicy(tt.args, "cpu") + if tt.errMsg == "" { + require.NoError(t, err) + } else { + require.EqualError(t, err, tt.errMsg) } }) } diff --git a/castai/sdk/api.gen.go b/castai/sdk/api.gen.go index 6d8204dd..b80b1115 100644 --- a/castai/sdk/api.gen.go +++ b/castai/sdk/api.gen.go @@ -74,6 +74,7 @@ const ( // Defines values for CastaiInventoryV1beta1DiscountPricingType. const ( CastaiInventoryV1beta1DiscountPricingTypeTYPEFIXED CastaiInventoryV1beta1DiscountPricingType = "TYPE_FIXED" + CastaiInventoryV1beta1DiscountPricingTypeTYPEFLAT CastaiInventoryV1beta1DiscountPricingType = "TYPE_FLAT" CastaiInventoryV1beta1DiscountPricingTypeTYPEPERCENTAGE CastaiInventoryV1beta1DiscountPricingType = "TYPE_PERCENTAGE" CastaiInventoryV1beta1DiscountPricingTypeTYPEUNKNOWN CastaiInventoryV1beta1DiscountPricingType = "TYPE_UNKNOWN" ) @@ -363,10 +364,23 @@ const ( WorkloadoptimizationV1ResourceConfigFunctionQUANTILE WorkloadoptimizationV1ResourceConfigFunction = "QUANTILE" ) +// Defines values for WorkloadoptimizationV1ResourceConfigOverridesFunction. +const ( + WorkloadoptimizationV1ResourceConfigOverridesFunctionMAX WorkloadoptimizationV1ResourceConfigOverridesFunction = "MAX" + WorkloadoptimizationV1ResourceConfigOverridesFunctionQUANTILE WorkloadoptimizationV1ResourceConfigOverridesFunction = "QUANTILE" +) + +// Defines values for WorkloadoptimizationV1ResourceLimitStrategyType. +const ( + MULTIPLIER WorkloadoptimizationV1ResourceLimitStrategyType = "MULTIPLIER" + NOLIMIT WorkloadoptimizationV1ResourceLimitStrategyType = "NO_LIMIT" + UNKNOWN WorkloadoptimizationV1ResourceLimitStrategyType = "UNKNOWN" +) + // Defines values for WorkloadoptimizationV1ResourcePoliciesFunction. const ( - WorkloadoptimizationV1ResourcePoliciesFunctionMAX WorkloadoptimizationV1ResourcePoliciesFunction = "MAX" - WorkloadoptimizationV1ResourcePoliciesFunctionQUANTILE WorkloadoptimizationV1ResourcePoliciesFunction = "QUANTILE" + MAX WorkloadoptimizationV1ResourcePoliciesFunction = "MAX" + QUANTILE WorkloadoptimizationV1ResourcePoliciesFunction = "QUANTILE" ) // CommitmentsAPIBatchDeleteCommitmentsRequest defines model for CommitmentsAPI_BatchDeleteCommitments_request. @@ -417,12 +431,13 @@ type RoleBindingIsTheRoleBindingToBeUpdated struct { // CreateServiceAccountKeyRequest is the request for creating a service account key. type ServiceAccountsAPICreateServiceAccountKeyRequest struct { - // Key is the readable version of the service account key. + // Key is the key to create. Key CastaiServiceaccountsV1beta1CreateServiceAccountKeyRequestKey `json:"key"` } // UpdateServiceAccountRequest is the request for updating a service account. type ServiceAccountsAPIUpdateServiceAccountRequest struct { + // ServiceAccount is the service account to be updated. ServiceAccount CastaiServiceaccountsV1beta1UpdateServiceAccountRequestServiceAccount `json:"serviceAccount"` } @@ -800,6 +815,8 @@ type CastaiInventoryV1beta1DiscountPricing struct { // be $1. // - TYPE_PERCENTAGE: Specifies a percentage discount. If set, the price will be reduced by the percentage value. For example if the public price is $5 and the discount value is "0.1" (10%), the final price will be // $4. + // - TYPE_FLAT: Specifies a flat discount. If set, the price will be reduced by the specified value. For example if the public price is $5 and the discount value is "1", the final price will be + // $4. Same if discount value is "-1", the final price will be $6. Type *CastaiInventoryV1beta1DiscountPricingType `json:"type,omitempty"` Value *string `json:"value,omitempty"` } @@ -809,6 +826,9 @@ type CastaiInventoryV1beta1DiscountPricing struct { // - TYPE_PERCENTAGE: Specifies a percentage discount. If set, the price will be reduced by the percentage value. For example if the public price is $5 and the discount value is "0.1" (10%), the final price will be // // $4. +// - TYPE_FLAT: Specifies a flat discount. If set, the price will be reduced by the specified value. For example if the public price is $5 and the discount value is "1", the final price will be +// +// $4. Same if discount value is "-1", the final price will be $6. type CastaiInventoryV1beta1DiscountPricingType string // CastaiInventoryV1beta1GCPCommitmentImport defines model for castai.inventory.v1beta1.GCPCommitmentImport. @@ -1617,9 +1637,9 @@ type CastaiRbacV1beta1UserSubject struct { Name *string `json:"name,omitempty"` } -// Key is the readable version of the service account key. +// Key is the key to create. type CastaiServiceaccountsV1beta1CreateServiceAccountKeyRequestKey struct { - // Active is the active state of the key. + // Active is the active state of the key. If not provided, the default is true. Active *bool `json:"active,omitempty"` // ExpiresAt is the expiration time of the key. @@ -1651,7 +1671,7 @@ type CastaiServiceaccountsV1beta1CreateServiceAccountKeyResponse struct { Token *string `json:"token,omitempty"` } -// ServiceAccounts is the readable version of the service accounts. +// ServiceAccounts is the service account to be created. type CastaiServiceaccountsV1beta1CreateServiceAccountRequestServiceAccount struct { // Description is the description of the role binding. Description *string `json:"description,omitempty"` @@ -1662,6 +1682,7 @@ type CastaiServiceaccountsV1beta1CreateServiceAccountRequestServiceAccount struc // CreateServiceAccountResponse is the response for creating a service account. type CastaiServiceaccountsV1beta1CreateServiceAccountResponse struct { + // Author is the author of the service account. Author *CastaiServiceaccountsV1beta1CreateServiceAccountResponseAuthor `json:"author,omitempty"` CreatedAt *time.Time `json:"createdAt,omitempty"` Description *string `json:"description,omitempty"` @@ -1670,7 +1691,7 @@ type CastaiServiceaccountsV1beta1CreateServiceAccountResponse struct { Name *string `json:"name,omitempty"` } -// CastaiServiceaccountsV1beta1CreateServiceAccountResponseAuthor defines model for castai.serviceaccounts.v1beta1.CreateServiceAccountResponse.Author. +// Author is the author of the service account. type CastaiServiceaccountsV1beta1CreateServiceAccountResponseAuthor struct { Email *string `json:"email,omitempty"` Id *string `json:"id,omitempty"` @@ -1787,7 +1808,7 @@ type CastaiServiceaccountsV1beta1UpdateServiceAccountKeyResponse struct { Prefix *string `json:"prefix,omitempty"` } -// CastaiServiceaccountsV1beta1UpdateServiceAccountRequestServiceAccount defines model for castai.serviceaccounts.v1beta1.UpdateServiceAccountRequest.ServiceAccount. +// ServiceAccount is the service account to be updated. type CastaiServiceaccountsV1beta1UpdateServiceAccountRequestServiceAccount struct { Description *string `json:"description,omitempty"` Name string `json:"name"` @@ -4023,6 +4044,13 @@ type WorkloadoptimizationV1ApplyType string // WorkloadoptimizationV1AssignScalingPolicyWorkloadsResponse defines model for workloadoptimization.v1.AssignScalingPolicyWorkloadsResponse. type WorkloadoptimizationV1AssignScalingPolicyWorkloadsResponse = map[string]interface{} +// WorkloadoptimizationV1ConfidenceSettings defines model for workloadoptimization.v1.ConfidenceSettings. +type WorkloadoptimizationV1ConfidenceSettings struct { + // Defines the confidence threshold that's enough to automatically optimize a given workload vertically. Value must be [0:1]. + // When not defined on scaling policy level or workload level, defaults to 0.9 (90%) confidence. + Threshold *float64 `json:"threshold"` +} + // WorkloadoptimizationV1ConfigurationChangedEventV2 defines model for workloadoptimization.v1.ConfigurationChangedEventV2. type WorkloadoptimizationV1ConfigurationChangedEventV2 struct { Current WorkloadoptimizationV1ConfigurationChangedV2 `json:"current"` @@ -4035,6 +4063,15 @@ type WorkloadoptimizationV1ConfigurationChangedV2 struct { WorkloadConfig WorkloadoptimizationV1WorkloadConfigV2 `json:"workloadConfig"` } +// WorkloadoptimizationV1Constraints defines model for workloadoptimization.v1.Constraints. +type WorkloadoptimizationV1Constraints struct { + // Defines the maximum value. For memory - this is in MiB, for CPU - this is in cores. + Max *float64 `json:"max"` + + // Defines the minimum value. For memory - this is in MiB, for CPU - this is in cores. + Min *float64 `json:"min"` +} + // WorkloadoptimizationV1Container defines model for workloadoptimization.v1.Container. type WorkloadoptimizationV1Container struct { // Name of the container. @@ -4057,6 +4094,14 @@ type WorkloadoptimizationV1ContainerConstraints struct { Memory *WorkloadoptimizationV1ResourceConfig `json:"memory,omitempty"` } +// WorkloadoptimizationV1ContainerConstraintsV2 defines model for workloadoptimization.v1.ContainerConstraintsV2. +type WorkloadoptimizationV1ContainerConstraintsV2 struct { + // Defines the container name for which the constraints are for. + ContainerName string `json:"containerName"` + Cpu *WorkloadoptimizationV1Constraints `json:"cpu,omitempty"` + Memory *WorkloadoptimizationV1Constraints `json:"memory,omitempty"` +} + // WorkloadoptimizationV1CpuMetrics defines model for workloadoptimization.v1.CpuMetrics. type WorkloadoptimizationV1CpuMetrics struct { TotalCpuCores []WorkloadoptimizationV1TimeSeriesMetric `json:"totalCpuCores"` @@ -4120,6 +4165,11 @@ type WorkloadoptimizationV1GetInstallCmdResponse struct { Script string `json:"script"` } +// WorkloadoptimizationV1GetWorkloadEventResponse defines model for workloadoptimization.v1.GetWorkloadEventResponse. +type WorkloadoptimizationV1GetWorkloadEventResponse struct { + Event WorkloadoptimizationV1WorkloadEvent `json:"event"` +} + // WorkloadoptimizationV1GetWorkloadResponse defines model for workloadoptimization.v1.GetWorkloadResponse. type WorkloadoptimizationV1GetWorkloadResponse struct { Metrics *WorkloadoptimizationV1WorkloadMetrics `json:"metrics,omitempty"` @@ -4192,6 +4242,24 @@ type WorkloadoptimizationV1HPAConfigUpdate struct { MinReplicas *int32 `json:"minReplicas"` } +// WorkloadoptimizationV1HorizontalOverrides defines model for workloadoptimization.v1.HorizontalOverrides. +type WorkloadoptimizationV1HorizontalOverrides struct { + // Defines possible options for workload management. + // READ_ONLY - workload watched (metrics collected), but no actions may be performed by CAST AI. + // MANAGED - workload watched (metrics collected), CAST AI may perform actions on the workload. + ManagementOption *WorkloadoptimizationV1ManagementOption `json:"managementOption,omitempty"` + + // Max replicas a workload can have. + MaxReplicas int32 `json:"maxReplicas"` + + // Min replicas a workload can have. + MinReplicas int32 `json:"minReplicas"` + ScaleDown *WorkloadoptimizationV1ScalingBehaviour `json:"scaleDown,omitempty"` + + // Defines the window of time to make a horizontal scaling decision. + ShortAverageSeconds *int32 `json:"shortAverageSeconds"` +} + // WorkloadoptimizationV1InitiatedBy defines model for workloadoptimization.v1.InitiatedBy. type WorkloadoptimizationV1InitiatedBy struct { Email *string `json:"email"` @@ -4240,10 +4308,7 @@ type WorkloadoptimizationV1MemoryEventSettings struct { // WorkloadoptimizationV1NewWorkloadScalingPolicy defines model for workloadoptimization.v1.NewWorkloadScalingPolicy. type WorkloadoptimizationV1NewWorkloadScalingPolicy struct { - ApplyType WorkloadoptimizationV1ApplyType `json:"applyType"` - - // Confidence threshold used for evaluation if the recommendation should be applied. If not set, the default value(0.9) will be used. - ConfidenceThreshold *float64 `json:"confidenceThreshold"` + ApplyType WorkloadoptimizationV1ApplyType `json:"applyType"` Name string `json:"name"` RecommendationPolicies WorkloadoptimizationV1RecommendationPolicies `json:"recommendationPolicies"` } @@ -4276,6 +4341,8 @@ type WorkloadoptimizationV1RecommendationEventType string // WorkloadoptimizationV1RecommendationPolicies defines model for workloadoptimization.v1.RecommendationPolicies. type WorkloadoptimizationV1RecommendationPolicies struct { AntiAffinity *WorkloadoptimizationV1AntiAffinitySettings `json:"antiAffinity,omitempty"` + ApplyType WorkloadoptimizationV1ApplyType `json:"applyType"` + Confidence *WorkloadoptimizationV1ConfidenceSettings `json:"confidence,omitempty"` Cpu WorkloadoptimizationV1ResourcePolicies `json:"cpu"` Downscaling *WorkloadoptimizationV1DownscalingSettings `json:"downscaling,omitempty"` @@ -4341,6 +4408,38 @@ type WorkloadoptimizationV1ResourceConfig struct { // MAX - the max function. type WorkloadoptimizationV1ResourceConfigFunction string +// WorkloadoptimizationV1ResourceConfigOverrides defines model for workloadoptimization.v1.ResourceConfigOverrides. +type WorkloadoptimizationV1ResourceConfigOverrides struct { + // The threshold of when to apply the recommendation - when diff of current requests and recommendation is greater than this, apply the recommendation. + ApplyThreshold *float64 `json:"applyThreshold"` + + // The arguments for the function - i.e. for a quantile, this should be a [0, 1] float. + Args *[]string `json:"args,omitempty"` + + // The function which to use when calculating the resource recommendation. + // QUANTILE - the quantile function. + // MAX - the max function. + Function *WorkloadoptimizationV1ResourceConfigOverridesFunction `json:"function,omitempty"` + Limit *WorkloadoptimizationV1ResourceLimitStrategy `json:"limit,omitempty"` + + // Period of time over which the resource recommendation is calculated. + LookBackPeriodSeconds *int32 `json:"lookBackPeriodSeconds"` + + // Max values for the recommendation. For memory - this is in MiB, for CPU - this is in cores. + Max *float64 `json:"max"` + + // Min values for the recommendation. For memory - this is in MiB, for CPU - this is in cores. + Min *float64 `json:"min"` + + // The overhead for the recommendation, the formula is: (1 + overhead) * function(args). + Overhead *float64 `json:"overhead"` +} + +// The function which to use when calculating the resource recommendation. +// QUANTILE - the quantile function. +// MAX - the max function. +type WorkloadoptimizationV1ResourceConfigOverridesFunction string + // WorkloadoptimizationV1ResourceConfigUpdate defines model for workloadoptimization.v1.ResourceConfigUpdate. type WorkloadoptimizationV1ResourceConfigUpdate struct { // Max values for the recommendation. For memory - this is in MiB, for CPU - this is in cores. @@ -4355,9 +4454,20 @@ type WorkloadoptimizationV1ResourceConfigUpdate struct { // WorkloadoptimizationV1ResourceLimitStrategy defines model for workloadoptimization.v1.ResourceLimitStrategy. type WorkloadoptimizationV1ResourceLimitStrategy struct { Multiplier *float64 `json:"multiplier,omitempty"` - None *bool `json:"none,omitempty"` + + // Type is the type of the limit strategy. + // + // - NO_LIMIT: No limit removes the resource limit even if it was specified in the workload spec. + // - MULTIPLIER: Multiplier used to calculate the resource limit. The final value is determined by multiplying the resource request by the specified factor. + Type WorkloadoptimizationV1ResourceLimitStrategyType `json:"type"` } +// Type is the type of the limit strategy. +// +// - NO_LIMIT: No limit removes the resource limit even if it was specified in the workload spec. +// - MULTIPLIER: Multiplier used to calculate the resource limit. The final value is determined by multiplying the resource request by the specified factor. +type WorkloadoptimizationV1ResourceLimitStrategyType string + // WorkloadoptimizationV1ResourceMetrics defines model for workloadoptimization.v1.ResourceMetrics. type WorkloadoptimizationV1ResourceMetrics struct { Max float64 `json:"max"` @@ -4417,6 +4527,12 @@ type WorkloadoptimizationV1Resources struct { Requests *WorkloadoptimizationV1ResourceQuantity `json:"requests,omitempty"` } +// WorkloadoptimizationV1ScalingBehaviour defines model for workloadoptimization.v1.ScalingBehaviour. +type WorkloadoptimizationV1ScalingBehaviour struct { + // Defines the minimum time to make a scaling decision after decision has been made. + StabilizationWindowSeconds *int32 `json:"stabilizationWindowSeconds"` +} + // WorkloadoptimizationV1ScalingPolicyAssigned defines model for workloadoptimization.v1.ScalingPolicyAssigned. type WorkloadoptimizationV1ScalingPolicyAssigned struct { Policy WorkloadoptimizationV1WorkloadScalingPolicy `json:"policy"` @@ -4477,10 +4593,7 @@ type WorkloadoptimizationV1UpdateWorkloadResponseV2 struct { // WorkloadoptimizationV1UpdateWorkloadScalingPolicy defines model for workloadoptimization.v1.UpdateWorkloadScalingPolicy. type WorkloadoptimizationV1UpdateWorkloadScalingPolicy struct { - ApplyType WorkloadoptimizationV1ApplyType `json:"applyType"` - - // Confidence threshold used for evaluation if the recommendation should be applied. If not set, the default value(0.9) will be used. - ConfidenceThreshold *float64 `json:"confidenceThreshold"` + ApplyType WorkloadoptimizationV1ApplyType `json:"applyType"` Name string `json:"name"` RecommendationPolicies WorkloadoptimizationV1RecommendationPolicies `json:"recommendationPolicies"` } @@ -4521,6 +4634,26 @@ type WorkloadoptimizationV1VPAConfigUpdate struct { MemoryEvent *WorkloadoptimizationV1MemoryEventSettings `json:"memoryEvent,omitempty"` } +// WorkloadoptimizationV1VerticalOverrides defines model for workloadoptimization.v1.VerticalOverrides. +type WorkloadoptimizationV1VerticalOverrides struct { + AntiAffinity *WorkloadoptimizationV1AntiAffinitySettings `json:"antiAffinity,omitempty"` + ApplyType *WorkloadoptimizationV1ApplyType `json:"applyType,omitempty"` + Confidence *WorkloadoptimizationV1ConfidenceSettings `json:"confidence,omitempty"` + + // Defines container specific overrides. + ContainerConstraints *[]WorkloadoptimizationV1ContainerConstraintsV2 `json:"containerConstraints,omitempty"` + Cpu *WorkloadoptimizationV1ResourceConfigOverrides `json:"cpu,omitempty"` + Downscaling *WorkloadoptimizationV1DownscalingSettings `json:"downscaling,omitempty"` + + // Defines possible options for workload management. + // READ_ONLY - workload watched (metrics collected), but no actions may be performed by CAST AI. + // MANAGED - workload watched (metrics collected), CAST AI may perform actions on the workload. + ManagementOption *WorkloadoptimizationV1ManagementOption `json:"managementOption,omitempty"` + Memory *WorkloadoptimizationV1ResourceConfigOverrides `json:"memory,omitempty"` + MemoryEvent *WorkloadoptimizationV1MemoryEventSettings `json:"memoryEvent,omitempty"` + Startup *WorkloadoptimizationV1StartupSettings `json:"startup,omitempty"` +} + // WorkloadoptimizationV1Workload defines model for workloadoptimization.v1.Workload. type WorkloadoptimizationV1Workload struct { // Annotations as defined on the workload manifest. These are annotations from the controller meta, not the pod meta. @@ -4561,11 +4694,13 @@ type WorkloadoptimizationV1Workload struct { Recommendation *WorkloadoptimizationV1WorkloadRecommendation `json:"recommendation,omitempty"` // The number of replicas the workload should have, as defined on the workload spec. - Replicas int32 `json:"replicas"` - ScalingPolicyId string `json:"scalingPolicyId"` - UpdatedAt time.Time `json:"updatedAt"` - Version string `json:"version"` - WorkloadConfigV2 WorkloadoptimizationV1WorkloadConfigV2 `json:"workloadConfigV2"` + Replicas int32 `json:"replicas"` + ScalingPolicyId string `json:"scalingPolicyId"` + ScalingPolicyName string `json:"scalingPolicyName"` + UpdatedAt time.Time `json:"updatedAt"` + Version string `json:"version"` + WorkloadConfigV2 WorkloadoptimizationV1WorkloadConfigV2 `json:"workloadConfigV2"` + WorkloadOverrides *WorkloadoptimizationV1WorkloadOverrides `json:"workloadOverrides,omitempty"` } // WorkloadoptimizationV1WorkloadConfigUpdateV2 defines model for workloadoptimization.v1.WorkloadConfigUpdateV2. @@ -4619,6 +4754,12 @@ type WorkloadoptimizationV1WorkloadMetrics struct { Pods WorkloadoptimizationV1PodMetrics `json:"pods"` } +// WorkloadoptimizationV1WorkloadOverrides defines model for workloadoptimization.v1.WorkloadOverrides. +type WorkloadoptimizationV1WorkloadOverrides struct { + Horizontal *WorkloadoptimizationV1HorizontalOverrides `json:"horizontal,omitempty"` + Vertical *WorkloadoptimizationV1VerticalOverrides `json:"vertical,omitempty"` +} + // WorkloadoptimizationV1WorkloadRecommendation defines model for workloadoptimization.v1.WorkloadRecommendation. type WorkloadoptimizationV1WorkloadRecommendation struct { // Defines the confidence of the recommendation. Value between 0 and 1. 1 means max confidence, 0 means no confidence. @@ -4652,7 +4793,6 @@ type WorkloadoptimizationV1WorkloadResourceConfigUpdate struct { type WorkloadoptimizationV1WorkloadScalingPolicy struct { ApplyType WorkloadoptimizationV1ApplyType `json:"applyType"` ClusterId string `json:"clusterId"` - ConfidenceThreshold float64 `json:"confidenceThreshold"` CreatedAt time.Time `json:"createdAt"` HasWorkloadsConfiguredByAnnotations bool `json:"hasWorkloadsConfiguredByAnnotations"` Id string `json:"id"` @@ -5045,6 +5185,12 @@ type WorkloadOptimizationAPIListWorkloadEventsParams struct { // WorkloadOptimizationAPIListWorkloadEventsParamsType defines parameters for WorkloadOptimizationAPIListWorkloadEvents. type WorkloadOptimizationAPIListWorkloadEventsParamsType string +// WorkloadOptimizationAPIGetWorkloadEventParams defines parameters for WorkloadOptimizationAPIGetWorkloadEvent. +type WorkloadOptimizationAPIGetWorkloadEventParams struct { + // The creation time of the event. + CreatedAt time.Time `form:"createdAt" json:"createdAt"` +} + // WorkloadOptimizationAPIGetWorkloadParams defines parameters for WorkloadOptimizationAPIGetWorkload. type WorkloadOptimizationAPIGetWorkloadParams struct { IncludeMetrics *bool `form:"includeMetrics,omitempty" json:"includeMetrics,omitempty"` diff --git a/castai/sdk/client.gen.go b/castai/sdk/client.gen.go index 6b501406..271525c9 100644 --- a/castai/sdk/client.gen.go +++ b/castai/sdk/client.gen.go @@ -606,6 +606,9 @@ type ClientInterface interface { // WorkloadOptimizationAPIListWorkloadEvents request WorkloadOptimizationAPIListWorkloadEvents(ctx context.Context, clusterId string, params *WorkloadOptimizationAPIListWorkloadEventsParams, reqEditors ...RequestEditorFn) (*http.Response, error) + // WorkloadOptimizationAPIGetWorkloadEvent request + WorkloadOptimizationAPIGetWorkloadEvent(ctx context.Context, clusterId string, eventId string, params *WorkloadOptimizationAPIGetWorkloadEventParams, reqEditors ...RequestEditorFn) (*http.Response, error) + // WorkloadOptimizationAPIListWorkloads request WorkloadOptimizationAPIListWorkloads(ctx context.Context, clusterId string, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -2898,6 +2901,18 @@ func (c *Client) WorkloadOptimizationAPIListWorkloadEvents(ctx context.Context, return c.Client.Do(req) } +func (c *Client) WorkloadOptimizationAPIGetWorkloadEvent(ctx context.Context, clusterId string, eventId string, params *WorkloadOptimizationAPIGetWorkloadEventParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewWorkloadOptimizationAPIGetWorkloadEventRequest(c.Server, clusterId, eventId, params) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) WorkloadOptimizationAPIListWorkloads(ctx context.Context, clusterId string, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewWorkloadOptimizationAPIListWorkloadsRequest(c.Server, clusterId) if err != nil { @@ -9456,6 +9471,63 @@ func NewWorkloadOptimizationAPIListWorkloadEventsRequest(server string, clusterI return req, nil } +// NewWorkloadOptimizationAPIGetWorkloadEventRequest generates requests for WorkloadOptimizationAPIGetWorkloadEvent +func NewWorkloadOptimizationAPIGetWorkloadEventRequest(server string, clusterId string, eventId string, params *WorkloadOptimizationAPIGetWorkloadEventParams) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "clusterId", runtime.ParamLocationPath, clusterId) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "eventId", runtime.ParamLocationPath, eventId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/v1/workload-autoscaling/clusters/%s/workload-events/%s", pathParam0, pathParam1) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + queryValues := queryURL.Query() + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "createdAt", runtime.ParamLocationQuery, params.CreatedAt); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + queryURL.RawQuery = queryValues.Encode() + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + // NewWorkloadOptimizationAPIListWorkloadsRequest generates requests for WorkloadOptimizationAPIListWorkloads func NewWorkloadOptimizationAPIListWorkloadsRequest(server string, clusterId string) (*http.Request, error) { var err error @@ -10363,6 +10435,9 @@ type ClientWithResponsesInterface interface { // WorkloadOptimizationAPIListWorkloadEvents request WorkloadOptimizationAPIListWorkloadEventsWithResponse(ctx context.Context, clusterId string, params *WorkloadOptimizationAPIListWorkloadEventsParams) (*WorkloadOptimizationAPIListWorkloadEventsResponse, error) + // WorkloadOptimizationAPIGetWorkloadEvent request + WorkloadOptimizationAPIGetWorkloadEventWithResponse(ctx context.Context, clusterId string, eventId string, params *WorkloadOptimizationAPIGetWorkloadEventParams) (*WorkloadOptimizationAPIGetWorkloadEventResponse, error) + // WorkloadOptimizationAPIListWorkloads request WorkloadOptimizationAPIListWorkloadsWithResponse(ctx context.Context, clusterId string) (*WorkloadOptimizationAPIListWorkloadsResponse, error) @@ -14534,6 +14609,36 @@ func (r WorkloadOptimizationAPIListWorkloadEventsResponse) GetBody() []byte { // TODO: to have common interface. https://github.com/deepmap/oapi-codegen/issues/240 +type WorkloadOptimizationAPIGetWorkloadEventResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *WorkloadoptimizationV1GetWorkloadEventResponse +} + +// Status returns HTTPResponse.Status +func (r WorkloadOptimizationAPIGetWorkloadEventResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r WorkloadOptimizationAPIGetWorkloadEventResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +// TODO: to have common interface. https://github.com/deepmap/oapi-codegen/issues/240 +// Body returns body of byte array +func (r WorkloadOptimizationAPIGetWorkloadEventResponse) GetBody() []byte { + return r.Body +} + +// TODO: to have common interface. https://github.com/deepmap/oapi-codegen/issues/240 + type WorkloadOptimizationAPIListWorkloadsResponse struct { Body []byte HTTPResponse *http.Response @@ -16393,6 +16498,15 @@ func (c *ClientWithResponses) WorkloadOptimizationAPIListWorkloadEventsWithRespo return ParseWorkloadOptimizationAPIListWorkloadEventsResponse(rsp) } +// WorkloadOptimizationAPIGetWorkloadEventWithResponse request returning *WorkloadOptimizationAPIGetWorkloadEventResponse +func (c *ClientWithResponses) WorkloadOptimizationAPIGetWorkloadEventWithResponse(ctx context.Context, clusterId string, eventId string, params *WorkloadOptimizationAPIGetWorkloadEventParams) (*WorkloadOptimizationAPIGetWorkloadEventResponse, error) { + rsp, err := c.WorkloadOptimizationAPIGetWorkloadEvent(ctx, clusterId, eventId, params) + if err != nil { + return nil, err + } + return ParseWorkloadOptimizationAPIGetWorkloadEventResponse(rsp) +} + // WorkloadOptimizationAPIListWorkloadsWithResponse request returning *WorkloadOptimizationAPIListWorkloadsResponse func (c *ClientWithResponses) WorkloadOptimizationAPIListWorkloadsWithResponse(ctx context.Context, clusterId string) (*WorkloadOptimizationAPIListWorkloadsResponse, error) { rsp, err := c.WorkloadOptimizationAPIListWorkloads(ctx, clusterId) @@ -20026,6 +20140,32 @@ func ParseWorkloadOptimizationAPIListWorkloadEventsResponse(rsp *http.Response) return response, nil } +// ParseWorkloadOptimizationAPIGetWorkloadEventResponse parses an HTTP response from a WorkloadOptimizationAPIGetWorkloadEventWithResponse call +func ParseWorkloadOptimizationAPIGetWorkloadEventResponse(rsp *http.Response) (*WorkloadOptimizationAPIGetWorkloadEventResponse, error) { + bodyBytes, err := ioutil.ReadAll(rsp.Body) + defer rsp.Body.Close() + if err != nil { + return nil, err + } + + response := &WorkloadOptimizationAPIGetWorkloadEventResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest WorkloadoptimizationV1GetWorkloadEventResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} + // ParseWorkloadOptimizationAPIListWorkloadsResponse parses an HTTP response from a WorkloadOptimizationAPIListWorkloadsWithResponse call func ParseWorkloadOptimizationAPIListWorkloadsResponse(rsp *http.Response) (*WorkloadOptimizationAPIListWorkloadsResponse, error) { bodyBytes, err := ioutil.ReadAll(rsp.Body) diff --git a/castai/sdk/mock/client.go b/castai/sdk/mock/client.go index 02e52b5a..640d5762 100644 --- a/castai/sdk/mock/client.go +++ b/castai/sdk/mock/client.go @@ -3835,6 +3835,26 @@ func (mr *MockClientInterfaceMockRecorder) WorkloadOptimizationAPIGetWorkload(ct return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WorkloadOptimizationAPIGetWorkload", reflect.TypeOf((*MockClientInterface)(nil).WorkloadOptimizationAPIGetWorkload), varargs...) } +// WorkloadOptimizationAPIGetWorkloadEvent mocks base method. +func (m *MockClientInterface) WorkloadOptimizationAPIGetWorkloadEvent(ctx context.Context, clusterId, eventId string, params *sdk.WorkloadOptimizationAPIGetWorkloadEventParams, reqEditors ...sdk.RequestEditorFn) (*http.Response, error) { + m.ctrl.T.Helper() + varargs := []interface{}{ctx, clusterId, eventId, params} + for _, a := range reqEditors { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "WorkloadOptimizationAPIGetWorkloadEvent", varargs...) + ret0, _ := ret[0].(*http.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// WorkloadOptimizationAPIGetWorkloadEvent indicates an expected call of WorkloadOptimizationAPIGetWorkloadEvent. +func (mr *MockClientInterfaceMockRecorder) WorkloadOptimizationAPIGetWorkloadEvent(ctx, clusterId, eventId, params interface{}, reqEditors ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{ctx, clusterId, eventId, params}, reqEditors...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WorkloadOptimizationAPIGetWorkloadEvent", reflect.TypeOf((*MockClientInterface)(nil).WorkloadOptimizationAPIGetWorkloadEvent), varargs...) +} + // WorkloadOptimizationAPIGetWorkloadScalingPolicy mocks base method. func (m *MockClientInterface) WorkloadOptimizationAPIGetWorkloadScalingPolicy(ctx context.Context, clusterId, policyId string, reqEditors ...sdk.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() @@ -6843,6 +6863,21 @@ func (mr *MockClientWithResponsesInterfaceMockRecorder) WorkloadOptimizationAPIG return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WorkloadOptimizationAPIGetInstallScriptWithResponse", reflect.TypeOf((*MockClientWithResponsesInterface)(nil).WorkloadOptimizationAPIGetInstallScriptWithResponse), ctx) } +// WorkloadOptimizationAPIGetWorkloadEventWithResponse mocks base method. +func (m *MockClientWithResponsesInterface) WorkloadOptimizationAPIGetWorkloadEventWithResponse(ctx context.Context, clusterId, eventId string, params *sdk.WorkloadOptimizationAPIGetWorkloadEventParams) (*sdk.WorkloadOptimizationAPIGetWorkloadEventResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "WorkloadOptimizationAPIGetWorkloadEventWithResponse", ctx, clusterId, eventId, params) + ret0, _ := ret[0].(*sdk.WorkloadOptimizationAPIGetWorkloadEventResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// WorkloadOptimizationAPIGetWorkloadEventWithResponse indicates an expected call of WorkloadOptimizationAPIGetWorkloadEventWithResponse. +func (mr *MockClientWithResponsesInterfaceMockRecorder) WorkloadOptimizationAPIGetWorkloadEventWithResponse(ctx, clusterId, eventId, params interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WorkloadOptimizationAPIGetWorkloadEventWithResponse", reflect.TypeOf((*MockClientWithResponsesInterface)(nil).WorkloadOptimizationAPIGetWorkloadEventWithResponse), ctx, clusterId, eventId, params) +} + // WorkloadOptimizationAPIGetWorkloadScalingPolicyWithResponse mocks base method. func (m *MockClientWithResponsesInterface) WorkloadOptimizationAPIGetWorkloadScalingPolicyWithResponse(ctx context.Context, clusterId, policyId string) (*sdk.WorkloadOptimizationAPIGetWorkloadScalingPolicyResponse, error) { m.ctrl.T.Helper() diff --git a/docs/resources/workload_scaling_policy.md b/docs/resources/workload_scaling_policy.md index 1f348f2a..cfcbdfbd 100644 --- a/docs/resources/workload_scaling_policy.md +++ b/docs/resources/workload_scaling_policy.md @@ -33,6 +33,10 @@ resource "castai_workload_scaling_policy" "services" { function = "MAX" overhead = 0.35 apply_threshold = 0.2 + limit { + type = "MULTIPLIER" + multiplier = 1.5 + } } startup { period_seconds = 240 @@ -54,7 +58,7 @@ resource "castai_workload_scaling_policy" "services" { ### Required -- `apply_type` (String) Recommendation apply type. +- `apply_type` (String) Recommendation apply type. - IMMEDIATE - pods are restarted immediately when new recommendation is generated. - DEFERRED - pods are not restarted and recommendation values are applied during natural restarts only (new deployment, etc.) - `cluster_id` (String) CAST AI cluster id @@ -85,11 +89,26 @@ Optional: - `apply_threshold` (Number) The threshold of when to apply the recommendation. Recommendation will be applied when diff of current requests and new recommendation is greater than set value - `args` (List of String) The arguments for the function - i.e. for `QUANTILE` this should be a [0, 1] float. `MAX` doesn't accept any args - `function` (String) The function used to calculate the resource recommendation. Supported values: `QUANTILE`, `MAX` +- `limit` (Block List, Max: 1) Resource limit settings (see [below for nested schema](#nestedblock--cpu--limit)) - `look_back_period_seconds` (Number) The look back period in seconds for the recommendation. - `max` (Number) Max values for the recommendation, applies to every container. For memory - this is in MiB, for CPU - this is in cores. - `min` (Number) Min values for the recommendation, applies to every container. For memory - this is in MiB, for CPU - this is in cores. - `overhead` (Number) Overhead for the recommendation, e.g. `0.1` will result in 10% higher recommendation + +### Nested Schema for `cpu.limit` + +Required: + +- `type` (String) Defines limit strategy type. + - NO_LIMIT - removes the resource limit even if it was specified in the workload spec. + - MULTIPLIER - used to calculate the resource limit. The final value is determined by multiplying the resource request by the specified factor. + +Optional: + +- `multiplier` (Number) Multiplier used to calculate the resource limit. It must be defined for the MULTIPLIER strategy. + + ### Nested Schema for `memory` @@ -99,11 +118,26 @@ Optional: - `apply_threshold` (Number) The threshold of when to apply the recommendation. Recommendation will be applied when diff of current requests and new recommendation is greater than set value - `args` (List of String) The arguments for the function - i.e. for `QUANTILE` this should be a [0, 1] float. `MAX` doesn't accept any args - `function` (String) The function used to calculate the resource recommendation. Supported values: `QUANTILE`, `MAX` +- `limit` (Block List, Max: 1) Resource limit settings (see [below for nested schema](#nestedblock--memory--limit)) - `look_back_period_seconds` (Number) The look back period in seconds for the recommendation. - `max` (Number) Max values for the recommendation, applies to every container. For memory - this is in MiB, for CPU - this is in cores. - `min` (Number) Min values for the recommendation, applies to every container. For memory - this is in MiB, for CPU - this is in cores. - `overhead` (Number) Overhead for the recommendation, e.g. `0.1` will result in 10% higher recommendation + +### Nested Schema for `memory.limit` + +Required: + +- `type` (String) Defines limit strategy type. + - NO_LIMIT - removes the resource limit even if it was specified in the workload spec. + - MULTIPLIER - used to calculate the resource limit. The final value is determined by multiplying the resource request by the specified factor. + +Optional: + +- `multiplier` (Number) Multiplier used to calculate the resource limit. It must be defined for the MULTIPLIER strategy. + + ### Nested Schema for `anti_affinity` diff --git a/examples/resources/castai_workload_scaling_policy/resource.tf b/examples/resources/castai_workload_scaling_policy/resource.tf index 339b24ce..1c4146bb 100644 --- a/examples/resources/castai_workload_scaling_policy/resource.tf +++ b/examples/resources/castai_workload_scaling_policy/resource.tf @@ -16,6 +16,10 @@ resource "castai_workload_scaling_policy" "services" { function = "MAX" overhead = 0.35 apply_threshold = 0.2 + limit { + type = "MULTIPLIER" + multiplier = 1.5 + } } startup { period_seconds = 240 @@ -29,4 +33,4 @@ resource "castai_workload_scaling_policy" "services" { anti_affinity { consider_anti_affinity = false } -} \ No newline at end of file +}