@@ -958,6 +958,171 @@ async Task AssertMd5sumAsync(string file, byte[] orig)
958958 }
959959 }
960960
961+ [ MinikubeFact ]
962+ public async Task V2HorizontalPodAutoscalerTestAsync ( )
963+ {
964+ var namespaceParameter = "default" ;
965+ var deploymentName = "k8scsharp-e2e-hpa-deployment" ;
966+ var hpaName = "k8scsharp-e2e-hpa" ;
967+
968+ using var client = CreateClient ( ) ;
969+
970+ async Task CleanupAsync ( )
971+ {
972+ var deleteOptions = new V1DeleteOptions { PropagationPolicy = "Foreground" } ;
973+
974+ try
975+ {
976+ await client . AutoscalingV2 . DeleteNamespacedHorizontalPodAutoscalerAsync ( hpaName , namespaceParameter , deleteOptions ) . ConfigureAwait ( false ) ;
977+ }
978+ catch ( HttpOperationException e )
979+ {
980+ if ( e . Response ? . StatusCode != System . Net . HttpStatusCode . NotFound )
981+ {
982+ throw ;
983+ }
984+ }
985+
986+ try
987+ {
988+ await client . AppsV1 . DeleteNamespacedDeploymentAsync ( deploymentName , namespaceParameter , deleteOptions ) . ConfigureAwait ( false ) ;
989+ }
990+ catch ( HttpOperationException e )
991+ {
992+ if ( e . Response ? . StatusCode != System . Net . HttpStatusCode . NotFound )
993+ {
994+ throw ;
995+ }
996+ }
997+
998+ var attempts = 10 ;
999+ while ( attempts -- > 0 )
1000+ {
1001+ var hpaList = await client . AutoscalingV2 . ListNamespacedHorizontalPodAutoscalerAsync ( namespaceParameter ) . ConfigureAwait ( false ) ;
1002+ var deploymentList = await client . AppsV1 . ListNamespacedDeploymentAsync ( namespaceParameter ) . ConfigureAwait ( false ) ;
1003+ if ( hpaList . Items . All ( item => item . Metadata . Name != hpaName ) && deploymentList . Items . All ( item => item . Metadata . Name != deploymentName ) )
1004+ {
1005+ break ;
1006+ }
1007+
1008+ await Task . Delay ( TimeSpan . FromSeconds ( 2 ) ) . ConfigureAwait ( false ) ;
1009+ }
1010+ }
1011+
1012+ try
1013+ {
1014+ await CleanupAsync ( ) . ConfigureAwait ( false ) ;
1015+
1016+ var labels = new Dictionary < string , string > { [ "app" ] = "k8scsharp-hpa" } ;
1017+
1018+ await client . AppsV1 . CreateNamespacedDeploymentAsync (
1019+ new V1Deployment
1020+ {
1021+ Metadata = new V1ObjectMeta { Name = deploymentName , Labels = new Dictionary < string , string > ( labels ) } ,
1022+ Spec = new V1DeploymentSpec
1023+ {
1024+ Replicas = 1 ,
1025+ Selector = new V1LabelSelector { MatchLabels = new Dictionary < string , string > ( labels ) } ,
1026+ Template = new V1PodTemplateSpec
1027+ {
1028+ Metadata = new V1ObjectMeta { Labels = new Dictionary < string , string > ( labels ) } ,
1029+ Spec = new V1PodSpec
1030+ {
1031+ Containers = new [ ]
1032+ {
1033+ new V1Container
1034+ {
1035+ Name = "k8scsharp-hpa" ,
1036+ Image = "nginx" ,
1037+ Resources = new V1ResourceRequirements
1038+ {
1039+ Requests = new Dictionary < string , ResourceQuantity >
1040+ {
1041+ { "cpu" , new ResourceQuantity ( "100m" ) } ,
1042+ { "memory" , new ResourceQuantity ( "128Mi" ) } ,
1043+ } ,
1044+ Limits = new Dictionary < string , ResourceQuantity >
1045+ {
1046+ { "cpu" , new ResourceQuantity ( "200m" ) } ,
1047+ { "memory" , new ResourceQuantity ( "256Mi" ) } ,
1048+ } ,
1049+ } ,
1050+ } ,
1051+ } ,
1052+ } ,
1053+ } ,
1054+ } ,
1055+ } ,
1056+ namespaceParameter ) . ConfigureAwait ( false ) ;
1057+
1058+ var hpa = new V2HorizontalPodAutoscaler
1059+ {
1060+ Metadata = new V1ObjectMeta { Name = hpaName } ,
1061+ Spec = new V2HorizontalPodAutoscalerSpec
1062+ {
1063+ MinReplicas = 1 ,
1064+ MaxReplicas = 3 ,
1065+ ScaleTargetRef = new V2CrossVersionObjectReference
1066+ {
1067+ ApiVersion = "apps/v1" ,
1068+ Kind = "Deployment" ,
1069+ Name = deploymentName ,
1070+ } ,
1071+ Metrics = new List < V2MetricSpec >
1072+ {
1073+ new V2MetricSpec
1074+ {
1075+ Type = "Resource" ,
1076+ Resource = new V2ResourceMetricSource
1077+ {
1078+ Name = "cpu" ,
1079+ Target = new V2MetricTarget
1080+ {
1081+ Type = "Utilization" ,
1082+ AverageUtilization = 50 ,
1083+ } ,
1084+ } ,
1085+ } ,
1086+ } ,
1087+ } ,
1088+ } ;
1089+
1090+ await client . AutoscalingV2 . CreateNamespacedHorizontalPodAutoscalerAsync ( hpa , namespaceParameter ) . ConfigureAwait ( false ) ;
1091+
1092+ var hpaList = await client . AutoscalingV2 . ListNamespacedHorizontalPodAutoscalerAsync ( namespaceParameter ) . ConfigureAwait ( false ) ;
1093+ Assert . Contains ( hpaList . Items , item => item . Metadata . Name == hpaName ) ;
1094+
1095+ var created = await client . AutoscalingV2 . ReadNamespacedHorizontalPodAutoscalerAsync ( hpaName , namespaceParameter ) . ConfigureAwait ( false ) ;
1096+ Assert . Equal ( 1 , created . Spec . MinReplicas ) ;
1097+
1098+ created . Spec . MinReplicas = 2 ;
1099+ await client . AutoscalingV2 . ReplaceNamespacedHorizontalPodAutoscalerAsync ( created , hpaName , namespaceParameter ) . ConfigureAwait ( false ) ;
1100+
1101+ var updated = await client . AutoscalingV2 . ReadNamespacedHorizontalPodAutoscalerAsync ( hpaName , namespaceParameter ) . ConfigureAwait ( false ) ;
1102+ Assert . Equal ( 2 , updated . Spec . MinReplicas ) ;
1103+
1104+ await client . AutoscalingV2 . DeleteNamespacedHorizontalPodAutoscalerAsync ( hpaName , namespaceParameter , new V1DeleteOptions { PropagationPolicy = "Foreground" } ) . ConfigureAwait ( false ) ;
1105+
1106+ var retries = 10 ;
1107+ while ( retries -- > 0 )
1108+ {
1109+ hpaList = await client . AutoscalingV2 . ListNamespacedHorizontalPodAutoscalerAsync ( namespaceParameter ) . ConfigureAwait ( false ) ;
1110+ if ( hpaList . Items . All ( item => item . Metadata . Name != hpaName ) )
1111+ {
1112+ break ;
1113+ }
1114+
1115+ await Task . Delay ( TimeSpan . FromSeconds ( 2 ) ) . ConfigureAwait ( false ) ;
1116+ }
1117+
1118+ Assert . DoesNotContain ( hpaList . Items , item => item . Metadata . Name == hpaName ) ;
1119+ }
1120+ finally
1121+ {
1122+ await CleanupAsync ( ) . ConfigureAwait ( false ) ;
1123+ }
1124+ }
1125+
9611126 public static IKubernetes CreateClient ( )
9621127 {
9631128 return new Kubernetes ( KubernetesClientConfiguration . BuildDefaultConfig ( ) ) ;
0 commit comments