forked from kedacore/keda
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixes kedacore#1528 Signed-off-by: Ram Cohen <[email protected]>
- Loading branch information
Showing
1 changed file
with
235 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,235 @@ | ||
import * as crypto from 'crypto' | ||
import * as fs from 'fs' | ||
import * as sh from 'shelljs' | ||
import * as tmp from 'tmp' | ||
import test from 'ava' | ||
|
||
const testNamespace = 'gcp-pubsub-test' | ||
const projectId = 'nth-hybrid-341214' | ||
const topicId = `projects/${projectId}/topics/keda-test-topic-` + crypto.randomBytes(6).toString('hex') | ||
const subscriptionName = `keda-test-topic-sub-` + crypto.randomBytes(6).toString('hex') | ||
const subscriptionId = `projects/${projectId}/subscriptions/${subscriptionName}` | ||
const deploymentName = 'dummy-consumer' | ||
const maxReplicaCount = '4' | ||
const gsPrefix = `kubectl exec --namespace ${testNamespace} deploy/gcp-sdk -- ` | ||
|
||
test.before(t => { | ||
sh.exec(`kubectl create namespace ${testNamespace}`) | ||
|
||
// deploy dummy consumer app, scaled object etc. | ||
const tmpFile = tmp.fileSync() | ||
fs.writeFileSync(tmpFile.name, deployYaml.replace("{{GCP_CREDS}}", Buffer.from(serviceAccountJson).toString("base64"))) | ||
|
||
t.is( | ||
0, | ||
sh.exec(`kubectl apply -f ${tmpFile.name} --namespace ${testNamespace}`).code, | ||
'creating a deployment should work..' | ||
) | ||
|
||
}) | ||
|
||
test.serial('Deployment should have 0 replicas on start', t => { | ||
const replicaCount = sh.exec( | ||
`kubectl get deployment.apps/${deploymentName} --namespace ${testNamespace} -o jsonpath="{.spec.replicas}"` | ||
).stdout | ||
t.is(replicaCount, '0', 'replica count should start out as 0') | ||
}) | ||
|
||
test.serial('creating the gcp-sdk pod should work..', t => { | ||
let tmpFile = tmp.fileSync() | ||
fs.writeFileSync(tmpFile.name, gcpSdkYaml) | ||
t.is( | ||
0, | ||
sh.exec(`kubectl apply -f ${tmpFile.name} --namespace ${testNamespace}`).code, | ||
'creating the gcp-sdk pod should work..' | ||
) | ||
|
||
// wait for the gcp-sdkpod to be ready | ||
let gcpSdkReadyReplicaCount = '0' | ||
for (let i = 0; i < 30; i++) { | ||
gcpSdkReadyReplicaCount = sh.exec(`kubectl get deploy/gcp-sdk -n ${testNamespace} -o jsonpath='{.status.readyReplicas}'`).stdout | ||
if (gcpSdkReadyReplicaCount != '1') { | ||
sh.exec('sleep 2s') | ||
} | ||
} | ||
t.is('1', gcpSdkReadyReplicaCount, 'GCP-SDK pod is not in a ready state') | ||
}) | ||
|
||
test.serial('initializing the gcp-sdk pod should work..', t => { | ||
// Authenticate to GCP | ||
t.is( | ||
0, | ||
sh.exec(gsPrefix + `gcloud auth activate-service-account --key-file /etc/secret-volume/creds.json`).code, | ||
'Executing remote command on gcp-sdk should work..' | ||
) | ||
|
||
// Set project id | ||
sh.exec(gsPrefix + `gcloud config set project ${projectId}`) | ||
|
||
// Create topic and subscription | ||
t.is( | ||
0, | ||
sh.exec(gsPrefix + `gcloud pubsub topics create ${topicId}`).code, | ||
'Creating a topic should work..' | ||
) | ||
|
||
t.is(0, | ||
sh.exec(gsPrefix + `gcloud pubsub subscriptions create ${subscriptionId} --topic=${topicId}`).code, | ||
'Creating a subscription should work..' | ||
) | ||
}) | ||
|
||
test.serial(`Publishing to pubsub`, t => { | ||
let replicaCount = '0' | ||
|
||
// Publish 30 messages | ||
for (let i = 0; i < 30; i++) { | ||
t.is( | ||
0, | ||
sh.exec(gsPrefix + `gcloud pubsub topics publish ${topicId} --message="AAAAAAAAAA"`).code, | ||
'Publishing a message to pub/sub should work..' | ||
) | ||
} | ||
}) | ||
|
||
test.serial(`Deployment should scale to ${maxReplicaCount} (the max) then back to 0`, t => { | ||
let replicaCount = '0' | ||
|
||
// Wait for the number of replicas to be scaled up to maxReplicaCount | ||
for (let i = 0; i < 150 && replicaCount != maxReplicaCount; i++) { | ||
replicaCount = sh.exec( | ||
`kubectl get deployment.apps/${deploymentName} --namespace ${testNamespace} -o jsonpath="{.spec.replicas}"` | ||
).stdout | ||
if (replicaCount != maxReplicaCount) { | ||
sh.exec('sleep 2s') | ||
} | ||
} | ||
|
||
t.is(maxReplicaCount, replicaCount, `Replica count should be ${maxReplicaCount} after 120 seconds but is ${replicaCount}`) | ||
|
||
// Purge all messages | ||
sh.exec(gsPrefix + `gcloud pubsub subscriptions seek ${subscriptionId} --time=-p1s`) | ||
|
||
// Wait for the number of replicas to be scaled down to 0 | ||
for (let i = 0; i < 30 && replicaCount !== '0'; i++) { | ||
replicaCount = sh.exec( | ||
`kubectl get deployment.apps/${deploymentName} --namespace ${testNamespace} -o jsonpath="{.spec.replicas}"` | ||
).stdout | ||
if (replicaCount != '0') { | ||
sh.exec('sleep 10s') | ||
} | ||
} | ||
|
||
t.is('0', replicaCount, 'Replica count should be 0 after 3 minutes') | ||
}) | ||
|
||
test.after.always.cb('clean up', t => { | ||
// Delete the subscription and topic | ||
sh.exec(gsPrefix + `gcloud pubsub subscriptions delete ${subscriptionId}`) | ||
sh.exec(gsPrefix + `gcloud pubsub topics delete ${topicId}`) | ||
|
||
sh.exec(`kubectl delete deployment.apps/${deploymentName} --namespace ${testNamespace}`) | ||
sh.exec(`kubectl delete namespace ${testNamespace}`) | ||
|
||
t.end() | ||
}) | ||
|
||
|
||
const deployYaml = `apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: ${deploymentName} | ||
namespace: ${testNamespace} | ||
labels: | ||
app: ${deploymentName} | ||
spec: | ||
replicas: 0 | ||
selector: | ||
matchLabels: | ||
app: ${deploymentName} | ||
template: | ||
metadata: | ||
labels: | ||
app: ${deploymentName} | ||
spec: | ||
containers: | ||
- name: ${deploymentName}-processor | ||
image: google/cloud-sdk:slim | ||
# Consume a message | ||
command: [ "/bin/bash", "-c", "--" ] | ||
args: [ "gcloud auth activate-service-account --key-file /etc/secret-volume/creds.json && gcloud pubsub subscriptions pull ${subscriptionId} --auto-ack" ] | ||
env: | ||
- name: GOOGLE_APPLICATION_CREDENTIALS_JSON | ||
valueFrom: | ||
secretKeyRef: | ||
name: pubsub-secrets | ||
key: creds.json | ||
volumeMounts: | ||
- name: secret-volume | ||
mountPath: /etc/secret-volume | ||
volumes: | ||
- name: secret-volume | ||
secret: | ||
secretName: pubsub-secrets | ||
--- | ||
apiVersion: v1 | ||
kind: Secret | ||
metadata: | ||
name: pubsub-secrets | ||
type: Opaque | ||
data: | ||
creds.json: {{GCP_CREDS}} | ||
--- | ||
apiVersion: keda.sh/v1alpha1 | ||
kind: ScaledObject | ||
metadata: | ||
name: test-scaledobject | ||
spec: | ||
scaleTargetRef: | ||
name: ${deploymentName} | ||
pollingInterval: 5 | ||
maxReplicaCount: ${maxReplicaCount} | ||
cooldownPeriod: 10 | ||
triggers: | ||
- type: gcp-pubsub | ||
metadata: | ||
subscriptionName: ${subscriptionName} | ||
mode: SubscriptionSize | ||
value: "5" | ||
credentialsFromEnv: GOOGLE_APPLICATION_CREDENTIALS_JSON | ||
` | ||
|
||
const gcpSdkYaml = `apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: gcp-sdk | ||
namespace: ${testNamespace} | ||
labels: | ||
app: gcp-sdk | ||
spec: | ||
replicas: 1 | ||
selector: | ||
matchLabels: | ||
app: gcp-sdk | ||
template: | ||
metadata: | ||
labels: | ||
app: gcp-sdk | ||
spec: | ||
containers: | ||
- name: gcp-sdk-container | ||
image: google/cloud-sdk:slim | ||
# Just spin & wait forever | ||
command: [ "/bin/bash", "-c", "--" ] | ||
args: [ "while true; do sleep 30; done;" ] | ||
volumeMounts: | ||
- name: secret-volume | ||
mountPath: /etc/secret-volume | ||
volumes: | ||
- name: secret-volume | ||
secret: | ||
secretName: pubsub-secrets | ||
` | ||
|
||
const serviceAccountJson = `{ | ||
}` // Json key with \n converted to \\n |