Skip to content

Commit

Permalink
Add e2e test for HorizontalPodAutoscaler
Browse files Browse the repository at this point in the history
  • Loading branch information
karlkfi committed Dec 20, 2024
1 parent be31a2c commit d101c00
Show file tree
Hide file tree
Showing 7 changed files with 431 additions and 0 deletions.
2 changes: 2 additions & 0 deletions e2e/nomostest/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (

admissionv1 "k8s.io/api/admissionregistration/v1"
appsv1 "k8s.io/api/apps/v1"
autoscalingv2 "k8s.io/api/autoscaling/v2"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
Expand Down Expand Up @@ -95,6 +96,7 @@ func newScheme(t testing.NTB) *runtime.Scheme {
resourcegroupv1alpha1.SchemeBuilder.SchemeBuilder,
apiregistrationv1.SchemeBuilder,
hubv1.SchemeBuilder,
autoscalingv2.SchemeBuilder,
}
for _, b := range builders {
err := b.AddToScheme(s)
Expand Down
104 changes: 104 additions & 0 deletions e2e/testcases/hpa_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package e2e

import (
"context"
"fmt"
"testing"
"time"

"github.com/google/go-cmp/cmp"
"github.com/pkg/errors"
appsv1 "k8s.io/api/apps/v1"
autoscalingv2 "k8s.io/api/autoscaling/v2"
"k8s.io/apimachinery/pkg/api/equality"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"kpt.dev/configsync/e2e/nomostest"
"kpt.dev/configsync/e2e/nomostest/ntopts"
nomostesting "kpt.dev/configsync/e2e/nomostest/testing"
"kpt.dev/configsync/e2e/nomostest/testwatcher"
"kpt.dev/configsync/pkg/kinds"
"sigs.k8s.io/controller-runtime/pkg/client"
)

func TestHPA(t *testing.T) {
nt := nomostest.New(t, nomostesting.Reconciliation2,
ntopts.SyncWithGitSource(nomostest.DefaultRootSyncID, ntopts.Unstructured))
rootSyncGitRepo := nt.SyncSourceGitReadWriteRepository(nomostest.DefaultRootSyncID)

nt.T.Log("Checking if metrics-server is installed")
found := false
for _, ns := range []string{"kube-system", "metrics-system"} {
metricsServerObj := &appsv1.Deployment{}
if err := nt.KubeClient.Get("metrics-server", ns, metricsServerObj); err != nil {
if apierrors.IsNotFound(err) {
continue
}
nt.T.Fatal(err)
}
found = true
break
}

if !found {
nt.T.Log("Deploy metrics-server Deployment & APIService")
nt.Must(rootSyncGitRepo.Copy(fmt.Sprintf("%s/metrics-server/components-v0.7.2.yaml", yamlDir), "acme/namespaces/metrics-system/components-v0.7.2.yaml"))
nt.Must(rootSyncGitRepo.CommitAndPush("Add metrics-server"))
nt.Must(nt.WatchForAllSyncs())

nt.T.Log("Wait for metrics-server Deployment to be available")
nt.Must(nt.Watcher.WatchForCurrentStatus(kinds.Deployment(), "metrics-server", "metrics-system"))
}

nt.T.Log("Deploy hello-world Deployment")
nt.Must(rootSyncGitRepo.Copy(fmt.Sprintf("%s/hpa/ns-helloworld.yaml", yamlDir), "acme/namespaces/helloworld/ns-helloworld.yaml"))
nt.Must(rootSyncGitRepo.Copy(fmt.Sprintf("%s/hpa/deployment-helloworld.yaml", yamlDir), "acme/namespaces/helloworld/deployment-helloworld.yaml"))
nt.Must(rootSyncGitRepo.CommitAndPush("Add deployment"))
nt.Must(nt.WatchForAllSyncs())

nt.T.Log("Wait for hello-world Deployment to be available")
nt.Must(nt.Watcher.WatchForCurrentStatus(kinds.Deployment(), "hello-world", "hello-world"))

nt.T.Log("Deploy hello-world HPA")
nt.Must(rootSyncGitRepo.Copy(fmt.Sprintf("%s/hpa/hpa-helloworld.yaml", yamlDir), "acme/namespaces/helloworld/hpa-helloworld.yaml"))
nt.Must(rootSyncGitRepo.CommitAndPush("Add HPA"))
nt.Must(nt.WatchForAllSyncs())

nt.T.Log("Wait for hello-world HPA to be available")
nt.Must(nt.Watcher.WatchForCurrentStatus(kinds.HorizontalPodAutoscaler(), "hello-world", "hello-world"))

oldHPPObj := &autoscalingv2.HorizontalPodAutoscaler{}
nt.Must(nt.KubeClient.Get("hello-world", "hello-world", oldHPPObj))

metricsHaveChanged := func(obj client.Object) error {
newHPAObj := obj.(*autoscalingv2.HorizontalPodAutoscaler)
if !equality.Semantic.DeepEqual(oldHPPObj.Spec.Metrics, newHPAObj.Spec.Metrics) {
return errors.Errorf("metrics have changed:\n%s",
cmp.Diff(oldHPPObj.Spec.Metrics, newHPAObj.Spec.Metrics))
}
return errors.New("metrics have not changed")
}

// Once available, the spec.metrics should not change
err := nt.Watcher.WatchObject(kinds.HorizontalPodAutoscaler(), "hello-world", "hello-world",
testwatcher.WatchPredicates(metricsHaveChanged),
testwatcher.WatchTimeout(30*time.Second))
if err == nil {
nt.T.Fatal("unexpected result: WatchObject with metricsHaveChanged should always error")
} else if !errors.Is(err, context.DeadlineExceeded) {
nt.T.Fatal(err)
}
}
35 changes: 35 additions & 0 deletions e2e/testdata/hpa/deployment-helloworld.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
namespace: hello-world
spec:
selector:
matchLabels:
app: hello-world
replicas: 1
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: hello
image: "gcr.io/google-samples/hello-app:2.0"
env:
- name: "PORT"
value: "50000"
33 changes: 33 additions & 0 deletions e2e/testdata/hpa/hpa-helloworld.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: hello-world
namespace: hello-world
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: hello-world
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
18 changes: 18 additions & 0 deletions e2e/testdata/hpa/ns-helloworld.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: v1
kind: Namespace
metadata:
name: hello-world
Loading

0 comments on commit d101c00

Please sign in to comment.