From 8e8aed56a511eb0d2b137de08bcd26bf2655c266 Mon Sep 17 00:00:00 2001 From: Laimonas Rastenis Date: Mon, 24 Jul 2023 14:40:29 +0300 Subject: [PATCH] feat: add support for GPU only node template field (#195) Co-authored-by: Laimonas Rastenis --- castai/resource_autoscaler.go | 8 +- castai/resource_node_template.go | 22 +++++- castai/resource_node_template_test.go | 14 +++- castai/sdk/api.gen.go | 77 ++++++++++++------- castai/sdk/client.gen.go | 34 ++++++-- castai/sdk/mock/client.go | 16 ++-- docs/resources/node_template.md | 1 + .../eks_cluster_autoscaler_polices/castai.tf | 1 + 8 files changed, 120 insertions(+), 53 deletions(-) diff --git a/castai/resource_autoscaler.go b/castai/resource_autoscaler.go index 57662950..f014a08c 100644 --- a/castai/resource_autoscaler.go +++ b/castai/resource_autoscaler.go @@ -109,7 +109,7 @@ func resourceCastaiAutoscalerUpdate(ctx context.Context, data *schema.ResourceDa return nil } -func getCurrentPolicies(ctx context.Context, client *sdk.ClientWithResponses, clusterId sdk.ClusterId) ([]byte, error) { +func getCurrentPolicies(ctx context.Context, client *sdk.ClientWithResponses, clusterId string) ([]byte, error) { log.Printf("[INFO] Getting cluster autoscaler information.") resp, err := client.PoliciesAPIGetClusterPolicies(ctx, clusterId) @@ -157,7 +157,7 @@ func updateAutoscalerPolicies(ctx context.Context, data *schema.ResourceData, me return upsertPolicies(ctx, meta, clusterId, changedPoliciesJSON) } -func upsertPolicies(ctx context.Context, meta interface{}, clusterId sdk.ClusterId, changedPoliciesJSON string) error { +func upsertPolicies(ctx context.Context, meta interface{}, clusterId string, changedPoliciesJSON string) error { client := meta.(*ProviderConfig).api resp, err := client.PoliciesAPIUpsertClusterPoliciesWithBodyWithResponse(ctx, clusterId, "application/json", bytes.NewReader([]byte(changedPoliciesJSON))) @@ -192,7 +192,7 @@ func readAutoscalerPolicies(ctx context.Context, data *schema.ResourceData, meta return nil } -func getChangedPolicies(ctx context.Context, data *schema.ResourceData, meta interface{}, clusterId sdk.ClusterId) ([]byte, error) { +func getChangedPolicies(ctx context.Context, data *schema.ResourceData, meta interface{}, clusterId string) ([]byte, error) { policyChangesJSON, found := data.GetOk(FieldAutoscalerPoliciesJSON) if !found { log.Printf("[DEBUG] policies json not provided. Skipping autoscaler policies changes") @@ -222,7 +222,7 @@ func getChangedPolicies(ctx context.Context, data *schema.ResourceData, meta int return policies, nil } -func getClusterId(data *schema.ResourceData) sdk.ClusterId { +func getClusterId(data *schema.ResourceData) string { value, found := data.GetOk(FieldClusterId) if !found { return "" diff --git a/castai/resource_node_template.go b/castai/resource_node_template.go index bca20758..385019d1 100644 --- a/castai/resource_node_template.go +++ b/castai/resource_node_template.go @@ -133,6 +133,12 @@ func resourceNodeTemplate() *schema.Resource { Default: false, Description: "Compute optimized instance constraint - will only pick compute optimized nodes if true.", }, + "is_gpu_only": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "GPU instance constraint - will only pick nodes with GPU if true", + }, "instance_families": { Type: schema.TypeList, MaxItems: 1, @@ -381,6 +387,9 @@ func flattenConstraints(c *sdk.NodetemplatesV1TemplateConstraints) ([]map[string if c.Spot != nil { out["spot"] = c.Spot } + if c.IsGpuOnly != nil { + out["is_gpu_only"] = c.IsGpuOnly + } if c.UseSpotFallbacks != nil { out["use_spot_fallbacks"] = c.UseSpotFallbacks @@ -600,12 +609,14 @@ func resourceNodeTemplateCreate(ctx context.Context, d *schema.ResourceData, met return resourceNodeTemplateRead(ctx, d, meta) } -func getNodeTemplateByName(ctx context.Context, data *schema.ResourceData, meta any, clusterID sdk.ClusterId) (*sdk.NodetemplatesV1NodeTemplate, error) { +func getNodeTemplateByName(ctx context.Context, data *schema.ResourceData, meta any, clusterID string) (*sdk.NodetemplatesV1NodeTemplate, error) { client := meta.(*ProviderConfig).api nodeTemplateName := data.Id() log.Printf("[INFO] Getting current node templates") - resp, err := client.NodeTemplatesAPIListNodeTemplatesWithResponse(ctx, clusterID) + resp, err := client.NodeTemplatesAPIListNodeTemplatesWithResponse(ctx, clusterID, &sdk.NodeTemplatesAPIListNodeTemplatesParams{ + IncludeDefault: lo.ToPtr(false), + }) notFound := fmt.Errorf("node templates for cluster %q not found at CAST AI", clusterID) if err != nil { return nil, err @@ -657,7 +668,9 @@ func nodeTemplateStateImporter(ctx context.Context, d *schema.ResourceData, meta // Find node templates client := meta.(*ProviderConfig).api - resp, err := client.NodeTemplatesAPIListNodeTemplatesWithResponse(ctx, clusterID) + resp, err := client.NodeTemplatesAPIListNodeTemplatesWithResponse(ctx, clusterID, &sdk.NodeTemplatesAPIListNodeTemplatesParams{ + IncludeDefault: lo.ToPtr(false), + }) if err != nil { return nil, err } @@ -795,6 +808,9 @@ func toTemplateConstraints(obj map[string]any) *sdk.NodetemplatesV1TemplateConst if v, ok := obj["architectures"].([]any); ok { out.Architectures = toPtr(toStringList(v)) } + if v, ok := obj["is_gpu_only"].(bool); ok { + out.IsGpuOnly = toPtr(v) + } return out } diff --git a/castai/resource_node_template_test.go b/castai/resource_node_template_test.go index d19319ae..268d745a 100644 --- a/castai/resource_node_template_test.go +++ b/castai/resource_node_template_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "fmt" + "github.com/samber/lo" "io" "net/http" "testing" @@ -98,7 +99,9 @@ func TestNodeTemplateResourceReadContext(t *testing.T) { } `))) mockClient.EXPECT(). - NodeTemplatesAPIListNodeTemplates(gomock.Any(), clusterId). + NodeTemplatesAPIListNodeTemplates(gomock.Any(), clusterId, gomock.Eq(&sdk.NodeTemplatesAPIListNodeTemplatesParams{ + IncludeDefault: lo.ToPtr(false), + })). Return(&http.Response{StatusCode: 200, Body: body, Header: map[string][]string{"Content-Type": {"json"}}}, nil) resource := resourceNodeTemplate() @@ -139,6 +142,7 @@ constraints.0.instance_families.0.exclude.4 = g5g constraints.0.instance_families.0.exclude.5 = g5 constraints.0.instance_families.0.exclude.6 = g3 constraints.0.instance_families.0.include.# = 0 +constraints.0.is_gpu_only = false constraints.0.max_cpu = 10000 constraints.0.max_memory = 0 constraints.0.min_cpu = 10 @@ -180,7 +184,9 @@ func TestNodeTemplateResourceReadContextEmptyList(t *testing.T) { clusterId := "b6bfc074-a267-400f-b8f1-db0850c369b1" body := io.NopCloser(bytes.NewReader([]byte(`{"items": []}`))) mockClient.EXPECT(). - NodeTemplatesAPIListNodeTemplates(gomock.Any(), clusterId). + NodeTemplatesAPIListNodeTemplates(gomock.Any(), clusterId, gomock.Eq(&sdk.NodeTemplatesAPIListNodeTemplatesParams{ + IncludeDefault: lo.ToPtr(false), + })). Return(&http.Response{StatusCode: 200, Body: body, Header: map[string][]string{"Content-Type": {"json"}}}, nil) resource := resourceNodeTemplate() @@ -370,7 +376,9 @@ func testAccCheckNodeTemplateDestroy(s *terraform.State) error { id := rs.Primary.ID clusterID := rs.Primary.Attributes["cluster_id"] - response, err := client.NodeTemplatesAPIListNodeTemplatesWithResponse(ctx, clusterID) + response, err := client.NodeTemplatesAPIListNodeTemplatesWithResponse(ctx, clusterID, &sdk.NodeTemplatesAPIListNodeTemplatesParams{ + IncludeDefault: lo.ToPtr(false), + }) if err != nil { return err } diff --git a/castai/sdk/api.gen.go b/castai/sdk/api.gen.go index 24457b8b..0f8b6896 100644 --- a/castai/sdk/api.gen.go +++ b/castai/sdk/api.gen.go @@ -467,14 +467,12 @@ type ExternalclusterV1Node struct { // Deprecated. Use node_info architecture field. InstanceArchitecture *string `json:"instanceArchitecture"` + InstanceId *string `json:"instanceId"` - // Will be populated only with GetNode request. - InstanceId *string `json:"instanceId"` - - // Will be populated only with GetNode request. + // Output only. Cloud provider instance tags/labels. InstanceLabels *ExternalclusterV1Node_InstanceLabels `json:"instanceLabels,omitempty"` - // Will be populated only with GetNode request. + // Output only. Cloud provider instance name. InstanceName *string `json:"instanceName"` InstancePrice *string `json:"instancePrice"` InstanceType *string `json:"instanceType,omitempty"` @@ -488,12 +486,10 @@ type ExternalclusterV1Node struct { Network *ExternalclusterV1NodeNetwork `json:"network,omitempty"` NodeConfigurationId *string `json:"nodeConfigurationId"` NodeInfo *ExternalclusterV1NodeInfo `json:"nodeInfo,omitempty"` - Region *string `json:"region,omitempty"` Resources *ExternalclusterV1Resources `json:"resources,omitempty"` // NodeType defines the role of the VM when joining the Kubernetes cluster. Default value is not allowed. - Role *ExternalclusterV1NodeType `json:"role,omitempty"` - Shape *string `json:"shape,omitempty"` + Role *ExternalclusterV1NodeType `json:"role,omitempty"` // NodeSpotConfig defines if node should be created as spot instance, and params for creation. SpotConfig *ExternalclusterV1NodeSpotConfig `json:"spotConfig,omitempty"` @@ -510,7 +506,7 @@ type ExternalclusterV1Node_Annotations struct { AdditionalProperties map[string]string `json:"-"` } -// Will be populated only with GetNode request. +// Output only. Cloud provider instance tags/labels. type ExternalclusterV1Node_InstanceLabels struct { AdditionalProperties map[string]string `json:"-"` } @@ -1021,6 +1017,9 @@ type NodetemplatesV1NewNodeTemplate struct { // Custom taints for the template. CustomTaints *[]NodetemplatesV1TaintWithoutEffect `json:"customTaints,omitempty"` + // Flag whether this template is the default template for the cluster. + IsDefault *bool `json:"isDefault,omitempty"` + // This field is used to enable/disable autoscaling for the template. IsEnabled *bool `json:"isEnabled"` Name *string `json:"name,omitempty"` @@ -1052,6 +1051,9 @@ type NodetemplatesV1NodeTemplate struct { // Custom taints for the template. CustomTaints *[]NodetemplatesV1Taint `json:"customTaints,omitempty"` + // Flag whether this template is the default template for the cluster. + IsDefault *bool `json:"isDefault,omitempty"` + // This field is used to enable/disable autoscaling for the template. IsEnabled *bool `json:"isEnabled,omitempty"` Name *string `json:"name,omitempty"` @@ -1106,14 +1108,21 @@ type NodetemplatesV1TemplateConstraints struct { Architectures *[]string `json:"architectures,omitempty"` ComputeOptimized *bool `json:"computeOptimized"` + // Enable/disable spot diversity policy. When enabled, autoscaler will try to balance between diverse and cost optimal instance types. + EnableSpotDiversity *bool `json:"enableSpotDiversity"` + // Fallback restore rate in seconds: defines how much time should pass before spot fallback should be attempted to be restored to real spot. FallbackRestoreRateSeconds *int32 `json:"fallbackRestoreRateSeconds"` Gpu *NodetemplatesV1TemplateConstraintsGPUConstraints `json:"gpu,omitempty"` InstanceFamilies *NodetemplatesV1TemplateConstraintsInstanceFamilyConstraints `json:"instanceFamilies,omitempty"` - MaxCpu *int32 `json:"maxCpu"` - MaxMemory *int32 `json:"maxMemory"` - MinCpu *int32 `json:"minCpu"` - MinMemory *int32 `json:"minMemory"` + + // This template is gpu only. Setting this to true, will result in only instances with GPUs being considered. + // In addition, this ensures that all of the added instances for this template won't have any nvidia taints. + IsGpuOnly *bool `json:"isGpuOnly"` + MaxCpu *int32 `json:"maxCpu"` + MaxMemory *int32 `json:"maxMemory"` + MinCpu *int32 `json:"minCpu"` + MinMemory *int32 `json:"minMemory"` // Should include on-demand instances in the considered pool. OnDemand *bool `json:"onDemand"` @@ -1128,8 +1137,17 @@ type NodetemplatesV1TemplateConstraints struct { // - key: scheduling.cast.ai/spot // operator: Exists // toleration. - Spot *bool `json:"spot"` - StorageOptimized *bool `json:"storageOptimized"` + Spot *bool `json:"spot"` + + // Allowed node configuration price increase when diversifying instance types. E.g. if the value is 10%, then the overall price of diversified instance types can be 10% higher than the price of the optimal configuration. + SpotDiversityPriceIncreaseLimitPercent *int32 `json:"spotDiversityPriceIncreaseLimitPercent"` + + // Enable/disable spot interruption predictions. + SpotInterruptionPredictionsEnabled *bool `json:"spotInterruptionPredictionsEnabled"` + + // Spot interruption predictions type. Can be either "aws-rebalance-recommendations" or "interruption-predictions". + SpotInterruptionPredictionsType *string `json:"spotInterruptionPredictionsType"` + StorageOptimized *bool `json:"storageOptimized"` // Spot instance fallback constraint - when true, on-demand instances will be created, when spots are unavailable. UseSpotFallbacks *bool `json:"useSpotFallbacks"` @@ -1137,12 +1155,8 @@ type NodetemplatesV1TemplateConstraints struct { // NodetemplatesV1TemplateConstraintsGPUConstraints defines model for nodetemplates.v1.TemplateConstraints.GPUConstraints. type NodetemplatesV1TemplateConstraintsGPUConstraints struct { - ExcludeNames *[]string `json:"excludeNames,omitempty"` - IncludeNames *[]string `json:"includeNames,omitempty"` - - // This template is gpu only. Setting this to true, will result in only instances with GPUs being considered. - // In addition, this ensures that all of the added instances for this template won't have any nvidia taints. - IsGpuOnly *bool `json:"isGpuOnly"` + ExcludeNames *[]string `json:"excludeNames,omitempty"` + IncludeNames *[]string `json:"includeNames,omitempty"` Manufacturers *[]string `json:"manufacturers,omitempty"` MaxCount *int32 `json:"maxCount"` MinCount *int32 `json:"minCount"` @@ -1168,6 +1182,9 @@ type NodetemplatesV1UpdateNodeTemplate struct { // Custom taints for the template. CustomTaints *[]NodetemplatesV1TaintWithoutEffect `json:"customTaints,omitempty"` + // Flag whether this template is the default template for the cluster. + IsDefault *bool `json:"isDefault,omitempty"` + // This field is used to enable/disable autoscaling for the template. IsEnabled *bool `json:"isEnabled"` RebalancingConfig *NodetemplatesV1RebalancingConfiguration `json:"rebalancingConfig,omitempty"` @@ -1503,12 +1520,13 @@ type ScheduledrebalancingV1RebalancingJob struct { // ScheduledrebalancingV1RebalancingOptions defines model for scheduledrebalancing.v1.RebalancingOptions. type ScheduledrebalancingV1RebalancingOptions struct { - // Defines the conditions which must be met in order to fully execute the plan. - ExecutionConditions *ScheduledrebalancingV1ExecutionConditions `json:"executionConditions,omitempty"` - // Defines whether the nodes that failed to get drained until a predefined timeout, will be kept with a // rebalancing.cast.ai/status=drain-failed annotation instead of forcefully drained. - KeepDrainTimeoutNodes *bool `json:"keepDrainTimeoutNodes"` + EvictGracefully *bool `json:"evictGracefully"` + + // Defines the conditions which must be met in order to fully execute the plan. + ExecutionConditions *ScheduledrebalancingV1ExecutionConditions `json:"executionConditions,omitempty"` + KeepDrainTimeoutNodes *bool `json:"keepDrainTimeoutNodes"` // Minimum number of nodes that should be kept in the cluster after rebalancing. MinNodes *int32 `json:"minNodes,omitempty"` @@ -1550,9 +1568,6 @@ type ScheduledrebalancingV1TriggerConditions struct { SavingsPercentage *float32 `json:"savingsPercentage,omitempty"` } -// ClusterId defines model for clusterId. -type ClusterId = string - // HeaderOrganizationId defines model for headerOrganizationId. type HeaderOrganizationId = openapi_types.UUID @@ -1576,6 +1591,12 @@ type NodeConfigurationAPICreateConfigurationJSONBody = NodeconfigV1NewNodeConfig // NodeConfigurationAPIUpdateConfigurationJSONBody defines parameters for NodeConfigurationAPIUpdateConfiguration. type NodeConfigurationAPIUpdateConfigurationJSONBody = NodeconfigV1NodeConfigurationUpdate +// NodeTemplatesAPIListNodeTemplatesParams defines parameters for NodeTemplatesAPIListNodeTemplates. +type NodeTemplatesAPIListNodeTemplatesParams struct { + // Flag whether to include the default template + IncludeDefault *bool `form:"includeDefault,omitempty" json:"includeDefault,omitempty"` +} + // NodeTemplatesAPICreateNodeTemplateJSONBody defines parameters for NodeTemplatesAPICreateNodeTemplate. type NodeTemplatesAPICreateNodeTemplateJSONBody = NodetemplatesV1NewNodeTemplate diff --git a/castai/sdk/client.gen.go b/castai/sdk/client.gen.go index 908427db..b515594c 100644 --- a/castai/sdk/client.gen.go +++ b/castai/sdk/client.gen.go @@ -143,7 +143,7 @@ type ClientInterface interface { PoliciesAPIGetClusterNodeConstraints(ctx context.Context, clusterId string, reqEditors ...RequestEditorFn) (*http.Response, error) // NodeTemplatesAPIListNodeTemplates request - NodeTemplatesAPIListNodeTemplates(ctx context.Context, clusterId string, reqEditors ...RequestEditorFn) (*http.Response, error) + NodeTemplatesAPIListNodeTemplates(ctx context.Context, clusterId string, params *NodeTemplatesAPIListNodeTemplatesParams, reqEditors ...RequestEditorFn) (*http.Response, error) // NodeTemplatesAPICreateNodeTemplate request with any body NodeTemplatesAPICreateNodeTemplateWithBody(ctx context.Context, clusterId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -528,8 +528,8 @@ func (c *Client) PoliciesAPIGetClusterNodeConstraints(ctx context.Context, clust return c.Client.Do(req) } -func (c *Client) NodeTemplatesAPIListNodeTemplates(ctx context.Context, clusterId string, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewNodeTemplatesAPIListNodeTemplatesRequest(c.Server, clusterId) +func (c *Client) NodeTemplatesAPIListNodeTemplates(ctx context.Context, clusterId string, params *NodeTemplatesAPIListNodeTemplatesParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewNodeTemplatesAPIListNodeTemplatesRequest(c.Server, clusterId, params) if err != nil { return nil, err } @@ -1788,7 +1788,7 @@ func NewPoliciesAPIGetClusterNodeConstraintsRequest(server string, clusterId str } // NewNodeTemplatesAPIListNodeTemplatesRequest generates requests for NodeTemplatesAPIListNodeTemplates -func NewNodeTemplatesAPIListNodeTemplatesRequest(server string, clusterId string) (*http.Request, error) { +func NewNodeTemplatesAPIListNodeTemplatesRequest(server string, clusterId string, params *NodeTemplatesAPIListNodeTemplatesParams) (*http.Request, error) { var err error var pathParam0 string @@ -1813,6 +1813,26 @@ func NewNodeTemplatesAPIListNodeTemplatesRequest(server string, clusterId string return nil, err } + queryValues := queryURL.Query() + + if params.IncludeDefault != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "includeDefault", runtime.ParamLocationQuery, *params.IncludeDefault); 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 @@ -3725,7 +3745,7 @@ type ClientWithResponsesInterface interface { PoliciesAPIGetClusterNodeConstraintsWithResponse(ctx context.Context, clusterId string) (*PoliciesAPIGetClusterNodeConstraintsResponse, error) // NodeTemplatesAPIListNodeTemplates request - NodeTemplatesAPIListNodeTemplatesWithResponse(ctx context.Context, clusterId string) (*NodeTemplatesAPIListNodeTemplatesResponse, error) + NodeTemplatesAPIListNodeTemplatesWithResponse(ctx context.Context, clusterId string, params *NodeTemplatesAPIListNodeTemplatesParams) (*NodeTemplatesAPIListNodeTemplatesResponse, error) // NodeTemplatesAPICreateNodeTemplate request with any body NodeTemplatesAPICreateNodeTemplateWithBodyWithResponse(ctx context.Context, clusterId string, contentType string, body io.Reader) (*NodeTemplatesAPICreateNodeTemplateResponse, error) @@ -5765,8 +5785,8 @@ func (c *ClientWithResponses) PoliciesAPIGetClusterNodeConstraintsWithResponse(c } // NodeTemplatesAPIListNodeTemplatesWithResponse request returning *NodeTemplatesAPIListNodeTemplatesResponse -func (c *ClientWithResponses) NodeTemplatesAPIListNodeTemplatesWithResponse(ctx context.Context, clusterId string) (*NodeTemplatesAPIListNodeTemplatesResponse, error) { - rsp, err := c.NodeTemplatesAPIListNodeTemplates(ctx, clusterId) +func (c *ClientWithResponses) NodeTemplatesAPIListNodeTemplatesWithResponse(ctx context.Context, clusterId string, params *NodeTemplatesAPIListNodeTemplatesParams) (*NodeTemplatesAPIListNodeTemplatesResponse, error) { + rsp, err := c.NodeTemplatesAPIListNodeTemplates(ctx, clusterId, params) if err != nil { return nil, err } diff --git a/castai/sdk/mock/client.go b/castai/sdk/mock/client.go index d095560e..82d0a792 100644 --- a/castai/sdk/mock/client.go +++ b/castai/sdk/mock/client.go @@ -1116,9 +1116,9 @@ func (mr *MockClientInterfaceMockRecorder) NodeTemplatesAPIFilterInstanceTypesWi } // NodeTemplatesAPIListNodeTemplates mocks base method. -func (m *MockClientInterface) NodeTemplatesAPIListNodeTemplates(ctx context.Context, clusterId string, reqEditors ...sdk.RequestEditorFn) (*http.Response, error) { +func (m *MockClientInterface) NodeTemplatesAPIListNodeTemplates(ctx context.Context, clusterId string, params *sdk.NodeTemplatesAPIListNodeTemplatesParams, reqEditors ...sdk.RequestEditorFn) (*http.Response, error) { m.ctrl.T.Helper() - varargs := []interface{}{ctx, clusterId} + varargs := []interface{}{ctx, clusterId, params} for _, a := range reqEditors { varargs = append(varargs, a) } @@ -1129,9 +1129,9 @@ func (m *MockClientInterface) NodeTemplatesAPIListNodeTemplates(ctx context.Cont } // NodeTemplatesAPIListNodeTemplates indicates an expected call of NodeTemplatesAPIListNodeTemplates. -func (mr *MockClientInterfaceMockRecorder) NodeTemplatesAPIListNodeTemplates(ctx, clusterId interface{}, reqEditors ...interface{}) *gomock.Call { +func (mr *MockClientInterfaceMockRecorder) NodeTemplatesAPIListNodeTemplates(ctx, clusterId, params interface{}, reqEditors ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{ctx, clusterId}, reqEditors...) + varargs := append([]interface{}{ctx, clusterId, params}, reqEditors...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NodeTemplatesAPIListNodeTemplates", reflect.TypeOf((*MockClientInterface)(nil).NodeTemplatesAPIListNodeTemplates), varargs...) } @@ -2399,18 +2399,18 @@ func (mr *MockClientWithResponsesInterfaceMockRecorder) NodeTemplatesAPIFilterIn } // NodeTemplatesAPIListNodeTemplatesWithResponse mocks base method. -func (m *MockClientWithResponsesInterface) NodeTemplatesAPIListNodeTemplatesWithResponse(ctx context.Context, clusterId string) (*sdk.NodeTemplatesAPIListNodeTemplatesResponse, error) { +func (m *MockClientWithResponsesInterface) NodeTemplatesAPIListNodeTemplatesWithResponse(ctx context.Context, clusterId string, params *sdk.NodeTemplatesAPIListNodeTemplatesParams) (*sdk.NodeTemplatesAPIListNodeTemplatesResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "NodeTemplatesAPIListNodeTemplatesWithResponse", ctx, clusterId) + ret := m.ctrl.Call(m, "NodeTemplatesAPIListNodeTemplatesWithResponse", ctx, clusterId, params) ret0, _ := ret[0].(*sdk.NodeTemplatesAPIListNodeTemplatesResponse) ret1, _ := ret[1].(error) return ret0, ret1 } // NodeTemplatesAPIListNodeTemplatesWithResponse indicates an expected call of NodeTemplatesAPIListNodeTemplatesWithResponse. -func (mr *MockClientWithResponsesInterfaceMockRecorder) NodeTemplatesAPIListNodeTemplatesWithResponse(ctx, clusterId interface{}) *gomock.Call { +func (mr *MockClientWithResponsesInterfaceMockRecorder) NodeTemplatesAPIListNodeTemplatesWithResponse(ctx, clusterId, params interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NodeTemplatesAPIListNodeTemplatesWithResponse", reflect.TypeOf((*MockClientWithResponsesInterface)(nil).NodeTemplatesAPIListNodeTemplatesWithResponse), ctx, clusterId) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NodeTemplatesAPIListNodeTemplatesWithResponse", reflect.TypeOf((*MockClientWithResponsesInterface)(nil).NodeTemplatesAPIListNodeTemplatesWithResponse), ctx, clusterId, params) } // NodeTemplatesAPIUpdateNodeTemplateWithBodyWithResponse mocks base method. diff --git a/docs/resources/node_template.md b/docs/resources/node_template.md index c34ce7a1..ace80a31 100644 --- a/docs/resources/node_template.md +++ b/docs/resources/node_template.md @@ -46,6 +46,7 @@ Optional: - `fallback_restore_rate_seconds` (Number) Fallback restore rate in seconds: defines how much time should pass before spot fallback should be attempted to be restored to real spot. - `gpu` (Block List, Max: 1) (see [below for nested schema](#nestedblock--constraints--gpu)) - `instance_families` (Block List, Max: 1) (see [below for nested schema](#nestedblock--constraints--instance_families)) +- `is_gpu_only` (Boolean) GPU instance constraint - will only pick nodes with GPU if true - `max_cpu` (Number) Max CPU cores per node. - `max_memory` (Number) Max Memory (Mib) per node. - `min_cpu` (Number) Min CPU cores per node. diff --git a/examples/eks/eks_cluster_autoscaler_polices/castai.tf b/examples/eks/eks_cluster_autoscaler_polices/castai.tf index 8c630b00..5f6d9794 100644 --- a/examples/eks/eks_cluster_autoscaler_polices/castai.tf +++ b/examples/eks/eks_cluster_autoscaler_polices/castai.tf @@ -130,6 +130,7 @@ module "castai-eks-cluster" { } compute_optimized = false storage_optimized = false + is_gpu_only = false } } }