-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
eb9d5ce
commit e1d3d27
Showing
3 changed files
with
275 additions
and
99 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,270 @@ | ||
//go:build e2e | ||
// +build e2e | ||
|
||
package new_relic_test | ||
|
||
import ( | ||
"encoding/base64" | ||
"fmt" | ||
"os" | ||
"testing" | ||
"time" | ||
|
||
"github.com/joho/godotenv" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
"k8s.io/client-go/kubernetes" | ||
|
||
. "github.com/kedacore/keda/v2/tests/helper" | ||
) | ||
|
||
// Load environment variables from .env file | ||
var _ = godotenv.Load("../../.env") | ||
var now = time.Now() | ||
|
||
const ( | ||
testName = "new-relic-test" | ||
) | ||
|
||
var ( | ||
testNamespace = fmt.Sprintf("%s-ns", testName) | ||
deploymentName = fmt.Sprintf("%s-deployment", testName) | ||
serviceName = fmt.Sprintf("%s-service-%v", testName, now.Unix()) | ||
monitoredDeploymentName = fmt.Sprintf("%s-monitored-deployment", testName) | ||
scaledObjectName = fmt.Sprintf("%s-so", testName) | ||
secretName = fmt.Sprintf("%s-secret", testName) | ||
triggerAuthName = fmt.Sprintf("%s-ta", testName) | ||
newRelicApiKey = os.Getenv("NEWRELIC_API_KEY") | ||
newRelicLicenseKey = os.Getenv("NEWRELIC_LICENSE") | ||
newRelicRegion = os.Getenv("NEWRELIC_REGION") | ||
newRelicAccountId = os.Getenv("NEWRELIC_ACCOUNT_ID") | ||
kuberneteClusterName = "keda-new-relic-cluster" | ||
newRelicHelmRepoUrl = "https://helm-charts.newrelic.com" | ||
deploymentReplicas = 1 | ||
minReplicaCount = 1 | ||
maxReplicaCount = 3 | ||
) | ||
|
||
type templateData struct { | ||
TestNamespace string | ||
DeploymentName string | ||
ServiceName string | ||
ScaledObjectName string | ||
TriggerAuthName string | ||
SecretName string | ||
NewRelicApiKey string | ||
DeploymentReplicas string | ||
NewRelicRegion string | ||
NewRelicAccountID string | ||
KuberneteClusterName string | ||
MinReplicaCount string | ||
MaxReplicaCount string | ||
} | ||
type templateValues map[string]string | ||
|
||
const ( | ||
secretTemplate = `apiVersion: v1 | ||
kind: Secret | ||
metadata: | ||
name: {{.SecretName}} | ||
namespace: {{.TestNamespace}} | ||
data: | ||
newRelicApiKey: {{.NewRelicApiKey}} | ||
` | ||
|
||
triggerAuthenticationTemplate = `apiVersion: keda.sh/v1alpha1 | ||
kind: TriggerAuthentication | ||
metadata: | ||
name: {{.TriggerAuthName}} | ||
namespace: {{.TestNamespace}} | ||
spec: | ||
secretTargetRef: | ||
- parameter: queryKey # Required. | ||
name: {{.SecretName}} # Required. | ||
key: newRelicApiKey # Required. | ||
` | ||
|
||
deploymentTemplate = `apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: {{.DeploymentName}} | ||
namespace: {{.TestNamespace}} | ||
labels: | ||
app: {{.DeploymentName}} | ||
spec: | ||
replicas: {{.DeploymentReplicas}} | ||
selector: | ||
matchLabels: | ||
app: {{.DeploymentName}} | ||
template: | ||
metadata: | ||
labels: | ||
app: {{.DeploymentName}} | ||
spec: | ||
containers: | ||
- name: prom-test-app | ||
image: tbickford/simple-web-app-prometheus:a13ade9 | ||
imagePullPolicy: IfNotPresent | ||
` | ||
|
||
serviceTemplate = `apiVersion: v1 | ||
kind: Service | ||
metadata: | ||
labels: | ||
name: {{.ServiceName}} | ||
namespace: {{.TestNamespace}} | ||
annotations: | ||
prometheus.io/scrape: "true" | ||
name: {{.ServiceName}} | ||
spec: | ||
ports: | ||
- name: http | ||
port: 80 | ||
protocol: TCP | ||
targetPort: 8080 | ||
selector: | ||
app: {{.DeploymentName}} | ||
` | ||
|
||
scaledObjectTemplate = `apiVersion: keda.sh/v1alpha1 | ||
kind: ScaledObject | ||
metadata: | ||
name: {{.ScaledObjectName}} | ||
namespace: {{.TestNamespace}} | ||
labels: | ||
app: {{.DeploymentName}} | ||
spec: | ||
scaleTargetRef: | ||
name: {{.DeploymentName}} | ||
minReplicaCount: {{.MinReplicaCount}} | ||
maxReplicaCount: {{.MaxReplicaCount}} | ||
pollingInterval: 1 | ||
cooldownPeriod: 1 | ||
advanced: | ||
horizontalPodAutoscalerConfig: | ||
behavior: | ||
scaleDown: | ||
stabilizationWindowSeconds: 10 | ||
triggers: | ||
- type: new-relic | ||
metadata: | ||
account: "{{.NewRelicAccountID}}" | ||
region: {{.NewRelicRegion}} | ||
threshold: "2" | ||
nrql: SELECT rate(sum(http_requests_total), 1 SECONDS) FROM Metric where serviceName='{{.ServiceName}}' and namespaceName='{{.TestNamespace}}' since 120 seconds ago | ||
authenticationRef: | ||
name: {{.TriggerAuthName}} | ||
` | ||
|
||
lightLoadTemplate = `apiVersion: v1 | ||
kind: Pod | ||
metadata: | ||
name: fake-light-traffic | ||
namespace: {{.TestNamespace}} | ||
spec: | ||
containers: | ||
- image: busybox | ||
name: test | ||
command: ["/bin/sh"] | ||
args: ["-c", "while true; do wget -O /dev/null -o /dev/null http://{{.ServiceName}}/; sleep 0.5; done"]` | ||
|
||
heavyLoadTemplate = `apiVersion: v1 | ||
kind: Pod | ||
metadata: | ||
name: fake-heavy-traffic | ||
namespace: {{.TestNamespace}} | ||
spec: | ||
containers: | ||
- image: busybox | ||
name: test | ||
command: ["/bin/sh"] | ||
args: ["-c", "while true; do wget -O /dev/null -o /dev/null http://{{.ServiceName}}/; sleep 0.1; done"]` | ||
) | ||
|
||
func TestNewRelicScaler(t *testing.T) { | ||
// setup | ||
t.Log("--- setting up ---") | ||
require.NotEmpty(t, newRelicApiKey, "NEWRELIC_API_KEY env variable is required for new relic tests") | ||
require.NotEmpty(t, newRelicLicenseKey, "NEWRELIC_LICENSE env variable is required for new relic tests") | ||
require.NotEmpty(t, newRelicAccountId, "NEWRELIC_ACCOUNT_ID env variable is required for new relic tests") | ||
require.NotEmpty(t, newRelicRegion, "NEWRELIC_REGION env variable is required for new relic tests") | ||
|
||
// Create kubernetes resources | ||
kc := GetKubernetesClient(t) | ||
data, templates := getTemplateData() | ||
CreateKubernetesResources(t, kc, testNamespace, data, templates) | ||
|
||
installNewRelic(t) | ||
|
||
assert.True(t, WaitForDeploymentReplicaReadyCount(t, kc, deploymentName, testNamespace, minReplicaCount, 60, 1), | ||
"replica count should be %s after a minute", minReplicaCount) | ||
|
||
// test scaling | ||
testActivation(t, kc, data) | ||
testScaleUp(t, kc, data) | ||
testScaleDown(t, kc, data) | ||
|
||
// cleanup | ||
DeleteKubernetesResources(t, kc, testNamespace, data, templates) | ||
} | ||
|
||
func testActivation(t *testing.T, kc *kubernetes.Clientset, data templateData) { | ||
t.Log("--- testing activation ---") | ||
KubectlApplyWithTemplate(t, data, "lightLoadTemplate", lightLoadTemplate) | ||
|
||
AssertReplicaCountNotChangeDuringTimePeriod(t, kc, deploymentName, testNamespace, minReplicaCount, 60) | ||
} | ||
|
||
func testScaleUp(t *testing.T, kc *kubernetes.Clientset, data templateData) { | ||
t.Log("--- testing scale up ---") | ||
KubectlApplyWithTemplate(t, data, "heavyLoadTemplate", heavyLoadTemplate) | ||
|
||
assert.True(t, WaitForDeploymentReplicaReadyCount(t, kc, deploymentName, testNamespace, maxReplicaCount, 60, 3), | ||
"replica count should be %d after 3 minutes", maxReplicaCount) | ||
} | ||
|
||
func testScaleDown(t *testing.T, kc *kubernetes.Clientset, data templateData) { | ||
t.Log("--- testing scale down ---") | ||
KubectlDeleteWithTemplate(t, data, "lightLoadTemplate", lightLoadTemplate) | ||
KubectlDeleteWithTemplate(t, data, "heavyLoadTemplate", heavyLoadTemplate) | ||
assert.True(t, WaitForDeploymentReplicaReadyCount(t, kc, deploymentName, testNamespace, minReplicaCount, 60, 3), | ||
"replica count should be %d after 3 minutes", minReplicaCount) | ||
} | ||
|
||
func installNewRelic(t *testing.T) { | ||
_, err := ExecuteCommand(fmt.Sprintf("helm repo add new-relic %s", newRelicHelmRepoUrl)) | ||
assert.NoErrorf(t, err, "cannot execute command - %s", err) | ||
_, err = ExecuteCommand("helm repo update") | ||
assert.NoErrorf(t, err, "cannot execute command - %s", err) | ||
|
||
cmd := fmt.Sprintf(`helm upgrade --install --set global.cluster=%s --set prometheus.enabled=true --set ksm.enabled=true --set global.lowDataMode=true --set global.licenseKey=%s --timeout 600s --set logging.enabled=false --set ksm.enabled=true --set logging.enabled=true --namespace %s ri-keda new-relic/nri-bundle`, | ||
kuberneteClusterName, | ||
newRelicLicenseKey, | ||
testNamespace) | ||
|
||
_, err = ExecuteCommand(cmd) | ||
assert.NoErrorf(t, err, "cannot execute command - %s", err) | ||
} | ||
|
||
func getTemplateData() (templateData, templateValues) { | ||
return templateData{ | ||
TestNamespace: testNamespace, | ||
DeploymentName: deploymentName, | ||
ServiceName: serviceName, | ||
TriggerAuthName: triggerAuthName, | ||
ScaledObjectName: scaledObjectName, | ||
SecretName: secretName, | ||
NewRelicRegion: newRelicRegion, | ||
KuberneteClusterName: kuberneteClusterName, | ||
MinReplicaCount: fmt.Sprintf("%v", minReplicaCount), | ||
MaxReplicaCount: fmt.Sprintf("%v", maxReplicaCount), | ||
DeploymentReplicas: fmt.Sprintf("%v", deploymentReplicas), | ||
NewRelicAccountID: newRelicAccountId, | ||
NewRelicApiKey: base64.StdEncoding.EncodeToString([]byte(newRelicApiKey)), | ||
}, templateValues{ | ||
"secretTemplate": secretTemplate, | ||
"triggerAuthenticationTemplate": triggerAuthenticationTemplate, | ||
"serviceTemplate": serviceTemplate, | ||
"deploymentTemplate": deploymentTemplate, | ||
"scaledObjectTemplate": scaledObjectTemplate} | ||
} |