diff --git a/pkg/analyzer/analyzer.go b/pkg/analyzer/analyzer.go index c18d9fa..e6ec2c2 100644 --- a/pkg/analyzer/analyzer.go +++ b/pkg/analyzer/analyzer.go @@ -47,7 +47,7 @@ var coreAnalyzerMap = map[string]common.IAnalyzer{ } var additionalAnalyzerMap = map[string]common.IAnalyzer{ - "HorizontalPodAutoScaler": HpaAnalyzer{}, + "HorizontalPodAutoscaler": HpaAnalyzer{}, "PodDisruptionBudget": PdbAnalyzer{}, "NetworkPolicy": NetworkPolicyAnalyzer{}, "Log": LogAnalyzer{}, diff --git a/pkg/analyzer/hpa.go b/pkg/analyzer/hpa.go index 749e9b7..cc2d003 100644 --- a/pkg/analyzer/hpa.go +++ b/pkg/analyzer/hpa.go @@ -20,6 +20,7 @@ import ( "github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes" "github.com/k8sgpt-ai/k8sgpt/pkg/util" appsv1 "k8s.io/api/apps/v1" + autoscalingv2 "k8s.io/api/autoscaling/v2" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -34,7 +35,7 @@ func (HpaAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) { Kind: kind, ApiVersion: schema.GroupVersion{ Group: "autoscaling", - Version: "v1", + Version: "v2", }, OpenapiSchema: a.OpenapiSchema, } @@ -56,11 +57,22 @@ func (HpaAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) { //check the error from status field conditions := hpa.Status.Conditions for _, condition := range conditions { - if condition.Status != "True" { - failures = append(failures, common.Failure{ - Text: condition.Message, - Sensitive: []common.Sensitive{}, - }) + // https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/#appendix-horizontal-pod-autoscaler-status-conditions + switch condition.Type { + case autoscalingv2.ScalingLimited: + if condition.Status == corev1.ConditionTrue { + failures = append(failures, common.Failure{ + Text: condition.Message, + Sensitive: []common.Sensitive{}, + }) + } + default: + if condition.Status == corev1.ConditionFalse { + failures = append(failures, common.Failure{ + Text: condition.Message, + Sensitive: []common.Sensitive{}, + }) + } } } diff --git a/pkg/analyzer/hpaAnalyzer_test.go b/pkg/analyzer/hpa_test.go similarity index 89% rename from pkg/analyzer/hpaAnalyzer_test.go rename to pkg/analyzer/hpa_test.go index e48a35b..62b273f 100644 --- a/pkg/analyzer/hpaAnalyzer_test.go +++ b/pkg/analyzer/hpa_test.go @@ -735,3 +735,87 @@ func TestHPAAnalyzerStatusField(t *testing.T) { assert.Equal(t, len(analysisResults), 1) } + +func TestHPAAnalyzerStatusScalingLimitedError(t *testing.T) { + clientset := fake.NewSimpleClientset( + &autoscalingv2.HorizontalPodAutoscaler{ + ObjectMeta: metav1.ObjectMeta{ + Name: "example", + Namespace: "default", + Annotations: map[string]string{}, + }, + Spec: autoscalingv2.HorizontalPodAutoscalerSpec{ + ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{ + Kind: "Deployment", + Name: "example", + }, + }, + Status: autoscalingv2.HorizontalPodAutoscalerStatus{ + Conditions: []autoscalingv2.HorizontalPodAutoscalerCondition{ + { + Type: autoscalingv2.AbleToScale, + Status: "True", + Message: "recommended size matches current size", + }, + { + Type: autoscalingv2.ScalingActive, + Status: "True", + Message: "the HPA was able to successfully calculate a replica count", + }, + { + Type: autoscalingv2.ScalingLimited, + Status: "True", + Message: "the desired replica count is less than the minimum replica count", + }, + }, + }, + }, + &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: "example", + Namespace: "default", + Annotations: map[string]string{}, + }, + Spec: appsv1.DeploymentSpec{ + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "example", + Image: "nginx", + }, + }, + }, + }, + }, + }, + ) + hpaAnalyzer := HpaAnalyzer{} + config := common.Analyzer{ + Client: &kubernetes.Client{ + Client: clientset, + }, + Context: context.Background(), + Namespace: "default", + } + analysisResults, err := hpaAnalyzer.Analyze(config) + if err != nil { + t.Error(err) + } + var errorFound bool + want := "the desired replica count is less than the minimum replica count" + for _, analysis := range analysisResults { + for _, got := range analysis.Error { + if want == got.Text { + errorFound = true + } + } + if errorFound { + break + } + } + + if !errorFound { + t.Errorf("Expected message, <%v> , not found in HorizontalPodAutoscaler's analysis results", want) + } +}