Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Data Source for Rebalancing Schedule #409

Merged
merged 11 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ test:
.PHONY: testacc
testacc:
@echo "==> Running acceptance tests"
TF_ACC=1 go test ./castai/... '-run=^TestAcc' -v -timeout 30m
TF_ACC=1 go test ./castai/... '-run=^TestAcc' -v -timeout 40m

.PHONY: validate-terraform-examples
validate-terraform-examples:
Expand Down
45 changes: 45 additions & 0 deletions castai/data_source_resource_rebalancing_schedule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package castai

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func dataSourceRebalancingSchedule() *schema.Resource {
dataSourceRebalancingSchedule := &schema.Resource{
Description: "Retrieve Rebalancing Schedule ",
ReadContext: dataSourceRebalancingScheduleRead,
Schema: map[string]*schema.Schema{},
}

resourceRebalancingSchedule := resourceRebalancingSchedule()
for key, value := range resourceRebalancingSchedule.Schema {
dataSourceRebalancingSchedule.Schema[key] = value
if key != "name" {
// only name is provided in terraform configuration by user
// other parameters are "computed" from existing rebalancing schedule
dataSourceRebalancingSchedule.Schema[key].Computed = true
dataSourceRebalancingSchedule.Schema[key].Required = false
// MaxItems is for configurable attributes, there's nothing to configure on computed-only field
dataSourceRebalancingSchedule.Schema[key].MaxItems = 0
}
}
return dataSourceRebalancingSchedule
}

func dataSourceRebalancingScheduleRead(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics {
rebalancingScheduleName := data.Get("name").(string)
client := meta.(*ProviderConfig).api
schedule, err := getRebalancingScheduleByName(ctx, client, rebalancingScheduleName)
if err != nil {
return diag.FromErr(fmt.Errorf("error retrieving rebalancing schedule: %w", err))
}

if err := scheduleToState(schedule, data); err != nil {
return diag.FromErr(fmt.Errorf("error converting schdeure to terraform state: %w", err))
}
return nil
}
147 changes: 147 additions & 0 deletions castai/data_source_resource_rebalancing_schedule_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package castai

import (
"bytes"
"context"
"io"
"net/http"
"testing"

"github.com/golang/mock/gomock"
"github.com/hashicorp/go-cty/cty"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"github.com/stretchr/testify/require"

"github.com/castai/terraform-provider-castai/castai/sdk"
mock_sdk "github.com/castai/terraform-provider-castai/castai/sdk/mock"
)

func TestRebalancingScheduleDataSourceRead(t *testing.T) {
t.Parallel()

r := require.New(t)
mockClient := mock_sdk.NewMockClientInterface(gomock.NewController(t))

ctx := context.Background()
provider := &ProviderConfig{
api: &sdk.ClientWithResponses{
ClientInterface: mockClient,
},
}

body := io.NopCloser(bytes.NewReader([]byte(`{
"schedules": [
{
"id": "9302fdac-4922-4b09-afa6-0a12be99f112",
"schedule": {
"cron": "5 * * * * *"
},
"launchConfiguration": {
"selector": {
"nodeSelectorTerms": []
},
"rebalancingOptions": {
"minNodes": 2,
"executionConditions": {
"enabled": true,
"achievedSavingsPercentage": 15
},
"keepDrainTimeoutNodes": false,
"evictGracefully": false,
"aggressiveMode": false
},
"numTargetedNodes": 20,
"nodeTtlSeconds": 350,
"targetNodeSelectionAlgorithm": "TargetNodeSelectionAlgorithmNormalizedPrice"
},
"triggerConditions": {
"savingsPercentage": 15,
"ignoreSavings": false
},
"nextTriggerAt": "2024-10-31T10:46:05Z",
"name": "rebalancing schedule 1",
"jobs": [],
"lastTriggerAt": "2024-10-31T10:45:08.915021Z"
},
{
"id": "d1954729-6fc0-4741-aeb0-c497e16f59f7",
"schedule": {
"cron": "5 * * * * *"
},
"launchConfiguration": {
"selector": {
"nodeSelectorTerms": []
},
"rebalancingOptions": {
"minNodes": 2,
"executionConditions": {
"enabled": true,
"achievedSavingsPercentage": 15
},
"keepDrainTimeoutNodes": false,
"evictGracefully": false,
"aggressiveMode": false
},
"numTargetedNodes": 20,
"nodeTtlSeconds": 350,
"targetNodeSelectionAlgorithm": "TargetNodeSelectionAlgorithmNormalizedPrice"
},
"triggerConditions": {
"savingsPercentage": 15,
"ignoreSavings": false
},
"nextTriggerAt": "2024-10-31T10:46:05Z",
"name": "rebalancing schedule 2",
"jobs": [
{
"id": "2ac90b71-8adc-468a-8680-ea4f99e4df27",
"clusterId": "d8bdd6d1-6b9a-4dbb-a276-5e44ff512322",
"rebalancingScheduleId": "d1954729-6fc0-4741-aeb0-c497e16f59f7",
"rebalancingPlanId": "",
"enabled": true,
"lastTriggerAt": "2024-10-31T10:38:06.594638Z",
"nextTriggerAt": "2024-10-31T10:46:05Z",
"status": "JobStatusSkipped"
}
],
"lastTriggerAt": "2024-10-31T10:45:08.922097Z"
}
]
}`)))
mockClient.EXPECT().
ScheduledRebalancingAPIListRebalancingSchedules(gomock.Any()).
Return(&http.Response{StatusCode: 200, Body: body, Header: map[string][]string{"Content-Type": {"json"}}}, nil)

state := terraform.NewInstanceStateShimmedFromValue(cty.ObjectVal(map[string]cty.Value{}), 0)

resource := dataSourceRebalancingSchedule()
data := resource.Data(state)

r.NoError(data.Set("name", "rebalancing schedule 1"))

result := resource.ReadContext(ctx, data, provider)
r.Nil(result)
r.False(result.HasError())

expectedState := `ID = 9302fdac-4922-4b09-afa6-0a12be99f112
launch_configuration.# = 1
launch_configuration.0.aggressive_mode = false
launch_configuration.0.execution_conditions.# = 1
launch_configuration.0.execution_conditions.0.achieved_savings_percentage = 15
launch_configuration.0.execution_conditions.0.enabled = true
launch_configuration.0.keep_drain_timeout_nodes = false
launch_configuration.0.node_ttl_seconds = 350
launch_configuration.0.num_targeted_nodes = 20
launch_configuration.0.rebalancing_min_nodes = 2
launch_configuration.0.selector =
launch_configuration.0.target_node_selection_algorithm = TargetNodeSelectionAlgorithmNormalizedPrice
name = rebalancing schedule 1
schedule.# = 1
schedule.0.cron = 5 * * * * *
trigger_conditions.# = 1
trigger_conditions.0.ignore_savings = false
trigger_conditions.0.savings_percentage = 15
Tainted = false
`
r.Equal(expectedState, data.State().String())
}
7 changes: 4 additions & 3 deletions castai/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,10 @@ func Provider(version string) *schema.Provider {
},

DataSourcesMap: map[string]*schema.Resource{
"castai_eks_settings": dataSourceEKSSettings(),
"castai_gke_user_policies": dataSourceGKEPolicies(),
"castai_organization": dataSourceOrganization(),
"castai_eks_settings": dataSourceEKSSettings(),
"castai_gke_user_policies": dataSourceGKEPolicies(),
"castai_organization": dataSourceOrganization(),
"castai_rebalancing_schedule": dataSourceRebalancingSchedule(),

// TODO: remove in next major release
"castai_eks_user_arn": dataSourceEKSClusterUserARN(),
Expand Down
88 changes: 87 additions & 1 deletion castai/resource_rebalancing_job_eks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package castai

import (
"fmt"
"testing"

"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"
"testing"
)

func TestAccResourceRebalancingJob_eks(t *testing.T) {
Expand Down Expand Up @@ -81,3 +82,88 @@ func makeInitialRebalancingJobConfig(rName, clusterName string) string {
func makeUpdatedRebalancingJobConfig(rName, clusterName string) string {
return ConfigCompose(testAccEKSClusterConfig(rName, clusterName), makeRebalancingJobConfig(rName, "enabled=false"))
}

func TestAccResourceRebalancingJobWithDataSource_eks(t *testing.T) {
rName := fmt.Sprintf("%v-rebalancing-job-with-data-source-%v", ResourcePrefix, acctest.RandString(8))
clusterName := "core-tf-acc"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },

ProviderFactories: providerFactories,
Steps: []resource.TestStep{
{
Config: makeRebalancingScheduleConfig(rName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("castai_rebalancing_schedule.test-with-data-source", "name", rName),
),
},
{
Config: makeRebalancingJobWithDataSource(rName, clusterName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.castai_rebalancing_schedule.data-source-for-rebalancing-schedule", "name", rName),
),
},
},
ExternalProviders: map[string]resource.ExternalProvider{
"aws": {
Source: "hashicorp/aws",
VersionConstraint: "~> 4.0",
},
},
})
}

func makeRebalancingScheduleConfig(rName string) string {
template := `
resource "castai_rebalancing_schedule" "test-with-data-source" {
name = %[1]q
schedule {
cron = "5 4 * * *"
}
trigger_conditions {
savings_percentage = 15.25
}
launch_configuration {
execution_conditions {
enabled = false
achieved_savings_percentage = 0
}
}
}
`
return fmt.Sprintf(template, rName)
}

func makeRebalancingJobWithDataSourceConfig(rName string) string {
template := `
resource "castai_rebalancing_schedule" "test-with-data-source" {
name = %[1]q
schedule {
cron = "5 4 * * *"
}
trigger_conditions {
savings_percentage = 15.25
}
launch_configuration {
execution_conditions {
enabled = false
achieved_savings_percentage = 0
}
}
}

data "castai_rebalancing_schedule" "data-source-for-rebalancing-schedule" {
name = %[1]q
}

resource "castai_rebalancing_job" "test-with-data-source" {
cluster_id = castai_eks_cluster.test.id
rebalancing_schedule_id = data.castai_rebalancing_schedule.data-source-for-rebalancing-schedule.id
}
`
return fmt.Sprintf(template, rName)
}

func makeRebalancingJobWithDataSource(rName, clusterName string) string {
return ConfigCompose(testAccEKSClusterConfig(rName, clusterName), makeRebalancingJobWithDataSourceConfig(rName))
}
25 changes: 25 additions & 0 deletions castai/sdk/api.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading