github.com/kubewharf/katalyst-core@v0.5.3/pkg/controller/vpa/util/api_test.go (about)

     1  /*
     2  Copyright 2022 The Katalyst Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package util
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/stretchr/testify/assert"
    25  	core "k8s.io/api/core/v1"
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  
    28  	apis "github.com/kubewharf/katalyst-api/pkg/apis/autoscaling/v1alpha1"
    29  	externalfake "github.com/kubewharf/katalyst-api/pkg/client/clientset/versioned/fake"
    30  	"github.com/kubewharf/katalyst-core/pkg/client/control"
    31  )
    32  
    33  func TestUpdateVPAConditions(t *testing.T) {
    34  	t.Parallel()
    35  
    36  	oldvpa1 := &apis.KatalystVerticalPodAutoscaler{
    37  		ObjectMeta: metav1.ObjectMeta{
    38  			Name:      "vpa1",
    39  			Namespace: "default",
    40  		},
    41  		Status: apis.KatalystVerticalPodAutoscalerStatus{
    42  			Conditions: []apis.VerticalPodAutoscalerCondition{
    43  				{
    44  					Type:               apis.RecommendationUpdated,
    45  					Status:             core.ConditionTrue,
    46  					LastTransitionTime: metav1.NewTime(time.Now()),
    47  				},
    48  			},
    49  		},
    50  	}
    51  	newvpa1 := &apis.KatalystVerticalPodAutoscaler{
    52  		ObjectMeta: metav1.ObjectMeta{
    53  			Name:      "vpa1",
    54  			Namespace: "default",
    55  		},
    56  		Status: apis.KatalystVerticalPodAutoscalerStatus{
    57  			Conditions: []apis.VerticalPodAutoscalerCondition{
    58  				{
    59  					Type:   apis.RecommendationUpdated,
    60  					Status: core.ConditionTrue,
    61  				},
    62  			},
    63  		},
    64  	}
    65  	newvpa2 := &apis.KatalystVerticalPodAutoscaler{
    66  		ObjectMeta: metav1.ObjectMeta{
    67  			Name:      "vpa1",
    68  			Namespace: "default",
    69  		},
    70  		Status: apis.KatalystVerticalPodAutoscalerStatus{
    71  			Conditions: []apis.VerticalPodAutoscalerCondition{
    72  				{
    73  					Type:   apis.RecommendationUpdated,
    74  					Status: core.ConditionFalse,
    75  				},
    76  			},
    77  		},
    78  	}
    79  	for _, tc := range []struct {
    80  		name            string
    81  		oldvpa          *apis.KatalystVerticalPodAutoscaler
    82  		conditionType   apis.VerticalPodAutoscalerConditionType
    83  		conditionStatus core.ConditionStatus
    84  		updateTime      bool
    85  		newvpa          *apis.KatalystVerticalPodAutoscaler
    86  	}{
    87  		{
    88  			name:            "status not change",
    89  			oldvpa:          oldvpa1,
    90  			conditionType:   apis.RecommendationUpdated,
    91  			conditionStatus: core.ConditionTrue,
    92  			updateTime:      false,
    93  			newvpa:          newvpa1,
    94  		},
    95  		{
    96  			name:            "update time",
    97  			oldvpa:          oldvpa1,
    98  			conditionType:   apis.RecommendationUpdated,
    99  			conditionStatus: core.ConditionFalse,
   100  			updateTime:      true,
   101  			newvpa:          newvpa2,
   102  		},
   103  	} {
   104  		tc := tc
   105  		t.Run(tc.name, func(t *testing.T) {
   106  			t.Parallel()
   107  
   108  			vpa := tc.oldvpa.DeepCopy()
   109  			err := SetVPAConditions(vpa, tc.conditionType, tc.conditionStatus, "", "")
   110  			assert.NoError(t, err)
   111  			tc.newvpa.Status.Conditions[0].LastTransitionTime = tc.oldvpa.Status.Conditions[0].LastTransitionTime
   112  			if tc.updateTime {
   113  				assert.NotEqual(t, tc.newvpa.Status.Conditions, vpa.Status.Conditions)
   114  				tc.newvpa.Status.Conditions[0].LastTransitionTime = vpa.Status.Conditions[0].LastTransitionTime
   115  			}
   116  			assert.Equal(t, vpa, tc.newvpa)
   117  		})
   118  	}
   119  }
   120  
   121  func TestUpdateAPIVPAConditions(t *testing.T) {
   122  	t.Parallel()
   123  
   124  	oldvpa1 := &apis.KatalystVerticalPodAutoscaler{
   125  		ObjectMeta: metav1.ObjectMeta{
   126  			Name:      "vpa1",
   127  			Namespace: "default",
   128  		},
   129  		Status: apis.KatalystVerticalPodAutoscalerStatus{
   130  			Conditions: []apis.VerticalPodAutoscalerCondition{
   131  				{
   132  					Type: apis.RecommendationUpdated,
   133  				},
   134  			},
   135  		},
   136  	}
   137  	newvpa1 := &apis.KatalystVerticalPodAutoscaler{
   138  		ObjectMeta: metav1.ObjectMeta{
   139  			Name:      "vpa1",
   140  			Namespace: "default",
   141  		},
   142  		Status: apis.KatalystVerticalPodAutoscalerStatus{
   143  			Conditions: []apis.VerticalPodAutoscalerCondition{
   144  				{
   145  					Type: apis.RecommendationUpdated,
   146  				},
   147  			},
   148  		},
   149  	}
   150  	newvpa11 := &apis.KatalystVerticalPodAutoscaler{
   151  		ObjectMeta: metav1.ObjectMeta{
   152  			Name:      "vpa1",
   153  			Namespace: "default",
   154  		},
   155  		Status: apis.KatalystVerticalPodAutoscalerStatus{
   156  			Conditions: []apis.VerticalPodAutoscalerCondition{
   157  				{
   158  					Type:   apis.RecommendationUpdated,
   159  					Reason: "test",
   160  				},
   161  			},
   162  		},
   163  	}
   164  	for _, tc := range []struct {
   165  		name   string
   166  		oldvpa *apis.KatalystVerticalPodAutoscaler
   167  		newvpa *apis.KatalystVerticalPodAutoscaler
   168  	}{
   169  		{
   170  			name:   "update different type condition type",
   171  			oldvpa: oldvpa1,
   172  			newvpa: newvpa1,
   173  		},
   174  		{
   175  			name:   "update same type condition type",
   176  			oldvpa: oldvpa1,
   177  			newvpa: newvpa11,
   178  		},
   179  	} {
   180  		tc := tc
   181  		t.Run(tc.name, func(t *testing.T) {
   182  			t.Parallel()
   183  
   184  			InternalClient := externalfake.NewSimpleClientset()
   185  			vpaUpdater := control.NewRealVPAUpdater(InternalClient)
   186  			_, err := InternalClient.AutoscalingV1alpha1().KatalystVerticalPodAutoscalers(tc.oldvpa.Namespace).Create(context.TODO(), tc.oldvpa, metav1.CreateOptions{})
   187  			assert.NoError(t, err)
   188  
   189  			_, err = vpaUpdater.PatchVPAStatus(context.TODO(), tc.oldvpa, tc.newvpa)
   190  			assert.NoError(t, err)
   191  
   192  			vpa, err := InternalClient.AutoscalingV1alpha1().KatalystVerticalPodAutoscalers(tc.newvpa.Namespace).Get(context.TODO(), tc.newvpa.Name, metav1.GetOptions{})
   193  			assert.NoError(t, err)
   194  			assert.Equal(t, tc.newvpa, vpa)
   195  		})
   196  	}
   197  }
   198  
   199  func TestUpdateVPARecConditions(t *testing.T) {
   200  	t.Parallel()
   201  
   202  	oldvparec1 := &apis.VerticalPodAutoscalerRecommendation{
   203  		ObjectMeta: metav1.ObjectMeta{
   204  			Name:      "vpa1",
   205  			Namespace: "default",
   206  		},
   207  		Status: apis.VerticalPodAutoscalerRecommendationStatus{
   208  			Conditions: []apis.VerticalPodAutoscalerRecommendationCondition{
   209  				{
   210  					Type:               apis.RecommendationUpdatedToVPA,
   211  					LastTransitionTime: metav1.NewTime(time.Now()),
   212  				},
   213  			},
   214  		},
   215  	}
   216  	newvparec1 := &apis.VerticalPodAutoscalerRecommendation{
   217  		ObjectMeta: metav1.ObjectMeta{
   218  			Name:      "vpa1",
   219  			Namespace: "default",
   220  		},
   221  		Status: apis.VerticalPodAutoscalerRecommendationStatus{
   222  			Conditions: []apis.VerticalPodAutoscalerRecommendationCondition{
   223  				{
   224  					Type: apis.RecommendationUpdatedToVPA,
   225  				},
   226  			},
   227  		},
   228  	}
   229  	for _, tc := range []struct {
   230  		name            string
   231  		oldvparec       *apis.VerticalPodAutoscalerRecommendation
   232  		conditionType   apis.VerticalPodAutoscalerRecommendationConditionType
   233  		forceUpdateTime bool
   234  		newvparec       *apis.VerticalPodAutoscalerRecommendation
   235  	}{
   236  		{
   237  			name:            "force update time",
   238  			oldvparec:       oldvparec1.DeepCopy(),
   239  			conditionType:   apis.RecommendationUpdatedToVPA,
   240  			forceUpdateTime: true,
   241  			newvparec:       newvparec1.DeepCopy(),
   242  		},
   243  		{
   244  			name:            "not force update time",
   245  			oldvparec:       newvparec1.DeepCopy(),
   246  			conditionType:   apis.RecommendationUpdatedToVPA,
   247  			forceUpdateTime: false,
   248  			newvparec:       newvparec1.DeepCopy(),
   249  		},
   250  	} {
   251  		tc := tc
   252  		t.Run(tc.name, func(t *testing.T) {
   253  			t.Parallel()
   254  
   255  			vparec := tc.oldvparec.DeepCopy()
   256  			err := SetVPARecConditions(vparec, tc.conditionType, "", "", "")
   257  			assert.NoError(t, err)
   258  			if tc.forceUpdateTime {
   259  				assert.NotEqual(t, tc.newvparec.Status.Conditions, vparec.Status.Conditions)
   260  				tc.newvparec.Status.Conditions[0].LastTransitionTime = vparec.Status.Conditions[0].LastTransitionTime
   261  			}
   262  			assert.Equal(t, vparec, tc.newvparec)
   263  		})
   264  	}
   265  }