@@ -14,6 +14,7 @@ import (
1414 "github.com/golang/mock/gomock"
1515 "github.com/hashicorp/go-cty/cty"
1616 "github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
17+ "github.com/samber/lo"
1718 "github.com/stretchr/testify/require"
1819
1920 "github.com/castai/terraform-provider-castai/castai/sdk"
@@ -592,20 +593,17 @@ func TestAutoscalerResource_CustomizeDiff(t *testing.T) {
592593}
593594
594595func TestAutoscalerResource_ToAutoscalerPolicy (t * testing.T ) {
595- tt := []struct {
596- name string
596+ tt := map [string ]struct {
597597 data cty.Value
598598 expected * types.AutoscalerPolicy
599599 shouldFail bool
600600 expectedErr error
601601 }{
602- {
603- name : "should return nil when data is nil" ,
602+ "should return nil when data is nil" : {
604603 data : cty .NilVal ,
605604 expected : nil ,
606605 },
607- {
608- name : "should handle nested objects" ,
606+ "should handle nested objects" : {
609607 data : cty .ObjectVal (
610608 map [string ]cty.Value {
611609 FieldAutoscalerSettings : cty .ListVal (
@@ -640,7 +638,8 @@ func TestAutoscalerResource_ToAutoscalerPolicy(t *testing.T) {
640638 expected : & types.AutoscalerPolicy {
641639 Enabled : true ,
642640 UnschedulablePods : & types.UnschedulablePods {
643- Enabled : true ,
641+ Enabled : true ,
642+ CustomInstances : lo .ToPtr (false ),
644643 PodPinner : & types.PodPinner {
645644 Enabled : true ,
646645 },
@@ -649,10 +648,10 @@ func TestAutoscalerResource_ToAutoscalerPolicy(t *testing.T) {
649648 },
650649 }
651650
652- for _ , test := range tt {
651+ for testName , test := range tt {
653652 r := require .New (t )
654653
655- t .Run (test . name , func (t * testing.T ) {
654+ t .Run (testName , func (t * testing.T ) {
656655 resource := resourceAutoscaler ()
657656 state := terraform .NewInstanceStateShimmedFromValue (test .data , 0 )
658657 actual , err := toAutoscalerPolicy (resource .Data (state ))
@@ -857,6 +856,108 @@ func TestAutoscalerResource_GetChangePolicies_ComparePolicyJsonAndDef(t *testing
857856 }
858857}
859858
859+ // Checks if the value of custom_instances_enabled is retained as received from the API
860+ // in case when it is not specified (null) in the resource configuration
861+ func TestAutoscalerResource_GetChangePolicies_AdjustPolicyForDrift (t * testing.T ) {
862+ r := require .New (t )
863+ mockCtrl := gomock .NewController (t )
864+ mockClient := mock_sdk .NewMockClientInterface (mockCtrl )
865+ clusterID := "cluster_id"
866+ provider := & ProviderConfig {
867+ api : & sdk.ClientWithResponses {
868+ ClientInterface : mockClient ,
869+ },
870+ }
871+ originalPolicyStr := `{
872+ "enabled": true,
873+ "isScopedMode": false,
874+ "nodeTemplatesPartialMatchingEnabled": false,
875+ "unschedulablePods": {
876+ "enabled": true,
877+ "custom_instances_enabled": true
878+ }
879+ }`
880+ expectedPolicyStr := `{
881+ "enabled": false,
882+ "isScopedMode": false,
883+ "nodeTemplatesPartialMatchingEnabled": false,
884+ "unschedulablePods": {
885+ "enabled": false,
886+ "custom_instances_enabled": true
887+ }
888+ }`
889+
890+ policyJSON , err := normalizeJSON ([]byte (originalPolicyStr ))
891+ r .NoError (err )
892+
893+ expectedPolicyJSON , err := normalizeJSON ([]byte (expectedPolicyStr ))
894+ r .NoError (err )
895+
896+ mockClient .EXPECT ().
897+ PoliciesAPIGetClusterPolicies (gomock .Any (), gomock .Any (), gomock .Any ()).
898+ Times (1 ).
899+ DoAndReturn (
900+ func (_ context.Context , _ string ) (* http.Response , error ) {
901+ return & http.Response {StatusCode : 200 , Body : io .NopCloser (bytes .NewReader (policyJSON ))}, nil
902+ },
903+ )
904+
905+ value := cty .ObjectVal (map [string ]cty.Value {
906+ FieldClusterId : cty .StringVal (clusterID ),
907+ FieldAutoscalerSettings : cty .ListVal (
908+ []cty.Value {
909+ cty .ObjectVal (
910+ map [string ]cty.Value {
911+ "enabled" : cty .BoolVal (false ),
912+ "unschedulable_pods" : cty .ListVal (
913+ []cty.Value {
914+ cty .ObjectVal (
915+ map [string ]cty.Value {
916+ "enabled" : cty .BoolVal (false ),
917+ },
918+ ),
919+ },
920+ ),
921+ },
922+ ),
923+ },
924+ ),
925+ })
926+ rawConfig := cty .ObjectVal (
927+ map [string ]cty.Value {
928+ "autoscaler_settings" : cty .ListVal (
929+ []cty.Value {
930+ cty .ObjectVal (
931+ map [string ]cty.Value {
932+ "enabled" : cty .BoolVal (false ),
933+ "unschedulable_pods" : cty .ListVal (
934+ []cty.Value {
935+ cty .ObjectVal (
936+ map [string ]cty.Value {
937+ "enabled" : cty .BoolVal (false ),
938+ "custom_instances_enabled" : cty .NullVal (cty .Bool ),
939+ },
940+ ),
941+ },
942+ ),
943+ },
944+ ),
945+ },
946+ ),
947+ },
948+ )
949+
950+ stateWithPolicyDefinition := terraform .NewInstanceStateShimmedFromValue (value , 0 )
951+ stateWithPolicyDefinition .RawConfig = rawConfig
952+
953+ resource := resourceAutoscaler ()
954+ data := resource .Data (stateWithPolicyDefinition )
955+ result , err := getChangedPolicies (context .Background (), data , provider , clusterID )
956+
957+ r .NoError (err )
958+ r .Equal (string (expectedPolicyJSON ), string (result ))
959+ }
960+
860961func JSONBytesEqual (a , b []byte ) (bool , error ) {
861962 var j , j2 interface {}
862963 if err := json .Unmarshal (a , & j ); err != nil {
0 commit comments