Skip to content

Commit ded0d65

Browse files
chore: Add an integration test for profiling (#465)
* chore: Add test for profiling * Remove metadata from TestAsserts * Use the repository docker.stackable.tech/sandbox/docker-images-pr540-5212814 for Hadoop in the integration tests * Fix linter warnings * Disable test case listener-class external-unstable * Revert using images from the sandbox repository * Enable test case listener-class external-unstable * fix: openshift test * fix: set openshift to false by default * Rename test files and create assertions for Role, RoleBinding, and ServiceAccount --------- Co-authored-by: Razvan-Daniel Mihai <[email protected]>
1 parent 730cc83 commit ded0d65

14 files changed

+319
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
apiVersion: kuttl.dev/v1beta1
3+
kind: TestAssert
4+
---
5+
apiVersion: rbac.authorization.k8s.io/v1
6+
kind: Role
7+
metadata:
8+
name: test-role
9+
---
10+
apiVersion: rbac.authorization.k8s.io/v1
11+
kind: RoleBinding
12+
metadata:
13+
name: test-rb
14+
---
15+
apiVersion: v1
16+
kind: ServiceAccount
17+
metadata:
18+
name: test-sa
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
kind: Role
3+
apiVersion: rbac.authorization.k8s.io/v1
4+
metadata:
5+
name: test-role
6+
rules:
7+
{% if test_scenario['values']['openshift'] == "true" %}
8+
- apiGroups: ["security.openshift.io"]
9+
resources: ["securitycontextconstraints"]
10+
resourceNames: ["privileged"]
11+
verbs: ["use"]
12+
{% endif %}
13+
---
14+
apiVersion: v1
15+
kind: ServiceAccount
16+
metadata:
17+
name: test-sa
18+
---
19+
kind: RoleBinding
20+
apiVersion: rbac.authorization.k8s.io/v1
21+
metadata:
22+
name: test-rb
23+
subjects:
24+
- kind: ServiceAccount
25+
name: test-sa
26+
roleRef:
27+
kind: Role
28+
name: test-role
29+
apiGroup: rbac.authorization.k8s.io
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
apiVersion: kuttl.dev/v1beta1
3+
kind: TestAssert
4+
{% if lookup('env', 'VECTOR_AGGREGATOR') %}
5+
---
6+
apiVersion: v1
7+
kind: ConfigMap
8+
metadata:
9+
name: vector-aggregator-discovery
10+
{% endif %}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{% if lookup('env', 'VECTOR_AGGREGATOR') %}
2+
---
3+
apiVersion: v1
4+
kind: ConfigMap
5+
metadata:
6+
name: vector-aggregator-discovery
7+
data:
8+
ADDRESS: {{ lookup('env', 'VECTOR_AGGREGATOR') }}
9+
{% endif %}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
apiVersion: kuttl.dev/v1beta1
3+
kind: TestAssert
4+
timeout: 600
5+
---
6+
apiVersion: apps/v1
7+
kind: StatefulSet
8+
metadata:
9+
name: test-zk-server-default
10+
status:
11+
readyReplicas: 1
12+
replicas: 1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
apiVersion: zookeeper.stackable.tech/v1alpha1
3+
kind: ZookeeperCluster
4+
metadata:
5+
name: test-zk
6+
spec:
7+
image:
8+
productVersion: "{{ test_scenario['values']['zookeeper-latest'] }}"
9+
pullPolicy: IfNotPresent
10+
{% if lookup('env', 'VECTOR_AGGREGATOR') %}
11+
clusterConfig:
12+
vectorAggregatorConfigMapName: vector-aggregator-discovery
13+
{% endif %}
14+
servers:
15+
config:
16+
logging:
17+
enableVectorAgent: {{ lookup('env', 'VECTOR_AGGREGATOR') | length > 0 }}
18+
roleGroups:
19+
default:
20+
replicas: 1
21+
---
22+
apiVersion: zookeeper.stackable.tech/v1alpha1
23+
kind: ZookeeperZnode
24+
metadata:
25+
name: test-znode
26+
spec:
27+
clusterRef:
28+
name: test-zk
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
apiVersion: kuttl.dev/v1beta1
3+
kind: TestAssert
4+
timeout: 600
5+
---
6+
apiVersion: apps/v1
7+
kind: StatefulSet
8+
metadata:
9+
name: test-hdfs-namenode-default
10+
status:
11+
readyReplicas: 2
12+
replicas: 2
13+
---
14+
apiVersion: apps/v1
15+
kind: StatefulSet
16+
metadata:
17+
name: test-hdfs-journalnode-default
18+
status:
19+
readyReplicas: 1
20+
replicas: 1
21+
---
22+
apiVersion: apps/v1
23+
kind: StatefulSet
24+
metadata:
25+
name: test-hdfs-datanode-default
26+
status:
27+
readyReplicas: 1
28+
replicas: 1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
---
2+
apiVersion: hdfs.stackable.tech/v1alpha1
3+
kind: HdfsCluster
4+
metadata:
5+
name: test-hdfs
6+
spec:
7+
image:
8+
productVersion: "{{ test_scenario['values']['hadoop'] }}"
9+
pullPolicy: IfNotPresent
10+
clusterConfig:
11+
dfsReplication: 1
12+
zookeeperConfigMapName: test-znode
13+
{% if lookup('env', 'VECTOR_AGGREGATOR') %}
14+
vectorAggregatorConfigMapName: vector-aggregator-discovery
15+
{% endif %}
16+
nameNodes:
17+
config:
18+
logging:
19+
enableVectorAgent: {{ lookup('env', 'VECTOR_AGGREGATOR') | length > 0 }}
20+
roleGroups:
21+
default:
22+
replicas: 2
23+
dataNodes:
24+
config:
25+
logging:
26+
enableVectorAgent: {{ lookup('env', 'VECTOR_AGGREGATOR') | length > 0 }}
27+
roleGroups:
28+
default:
29+
replicas: 1
30+
journalNodes:
31+
config:
32+
logging:
33+
enableVectorAgent: {{ lookup('env', 'VECTOR_AGGREGATOR') | length > 0 }}
34+
roleGroups:
35+
default:
36+
replicas: 1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
apiVersion: kuttl.dev/v1beta1
3+
kind: TestAssert
4+
timeout: 300
5+
---
6+
apiVersion: apps/v1
7+
kind: StatefulSet
8+
metadata:
9+
name: test-runner
10+
status:
11+
readyReplicas: 1
12+
replicas: 1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
apiVersion: kuttl.dev/v1beta1
3+
kind: TestStep
4+
metadata:
5+
name: install-test-container
6+
timeout: 300
7+
---
8+
apiVersion: apps/v1
9+
kind: StatefulSet
10+
metadata:
11+
name: test-runner
12+
labels:
13+
app: test-runner
14+
spec:
15+
replicas: 1
16+
selector:
17+
matchLabels:
18+
app: test-runner
19+
template:
20+
metadata:
21+
labels:
22+
app: test-runner
23+
spec:
24+
serviceAccountName: test-sa
25+
securityContext:
26+
fsGroup: 1000
27+
containers:
28+
- name: python
29+
image: docker.stackable.tech/stackable/testing-tools:0.2.0-stackable0.0.0-dev
30+
stdin: true
31+
tty: true
32+
resources:
33+
requests:
34+
memory: "128Mi"
35+
cpu: "512m"
36+
limits:
37+
memory: "128Mi"
38+
cpu: "1"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
apiVersion: kuttl.dev/v1beta1
3+
kind: TestAssert
4+
timeout: 300
5+
commands:
6+
- script: >-
7+
kubectl exec -n $NAMESPACE test-runner-0 --
8+
python /stackable/run-profiler.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
apiVersion: kuttl.dev/v1beta1
3+
kind: TestStep
4+
metadata:
5+
name: run-profiler
6+
commands:
7+
- script: |-
8+
kubectl cp run-profiler.py $NAMESPACE/test-runner-0:/stackable
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import re
2+
import requests
3+
import time
4+
5+
EVENT_TYPE = "itimer"
6+
PROFILING_DURATION_IN_SEC = 1
7+
8+
9+
def start_profiling_and_get_refresh_header(service_url):
10+
prof_page = requests.get(
11+
f"{service_url}/prof"
12+
f"?event={EVENT_TYPE}&duration={PROFILING_DURATION_IN_SEC}")
13+
14+
assert prof_page.ok, \
15+
f"""Profiling could not be started.
16+
URL: {prof_page.request.url}
17+
Status Code: {prof_page.status_code}"""
18+
19+
return prof_page.headers['Refresh']
20+
21+
22+
def parse_refresh_header(refresh_header):
23+
refresh_time_in_sec, refresh_path = refresh_header.split(';', 1)
24+
refresh_time_in_sec = int(refresh_time_in_sec)
25+
26+
assert refresh_time_in_sec == PROFILING_DURATION_IN_SEC, \
27+
f"""Profiling duration and refresh time should be equal.
28+
expected: {PROFILING_DURATION_IN_SEC}
29+
actual: {refresh_time_in_sec}"""
30+
31+
expected_refresh_path_pattern = \
32+
r'/prof-output-hadoop/async-prof-pid-\d+-itimer-\d+.html'
33+
assert re.fullmatch(expected_refresh_path_pattern, refresh_path), \
34+
f"""The path to the flamegraph contains an unexpected pattern.
35+
expected pattern: {expected_refresh_path_pattern}"
36+
actual path: {refresh_path}"""
37+
38+
return refresh_time_in_sec, refresh_path
39+
40+
41+
def wait_for_profiling_to_finish(refresh_time_in_sec):
42+
additional_sleep_time_in_sec = 2
43+
time.sleep(refresh_time_in_sec + additional_sleep_time_in_sec)
44+
45+
46+
def fetch_flamegraph(service_url, refresh_path):
47+
flamegraph_page = requests.get(f"{service_url}{refresh_path}")
48+
49+
assert flamegraph_page.ok, \
50+
f"""The flamegraph could not be fetched.
51+
URL: {flamegraph_page.request.url}
52+
Status Code: {flamegraph_page.status_code}"""
53+
54+
55+
def test_profiling(role, port):
56+
service_url = (
57+
f"http://test-hdfs-{role}-default-0.test-hdfs-{role}-default"
58+
f":{port}")
59+
60+
print(f"Test profiling on {service_url}")
61+
62+
refresh_header = start_profiling_and_get_refresh_header(service_url)
63+
64+
refresh_time_in_sec, refresh_path = \
65+
parse_refresh_header(refresh_header)
66+
67+
wait_for_profiling_to_finish(refresh_time_in_sec)
68+
69+
fetch_flamegraph(service_url, refresh_path)
70+
71+
72+
test_profiling(role="namenode", port=9870)
73+
test_profiling(role="datanode", port=9864)
74+
test_profiling(role="journalnode", port=8480)

tests/test-definition.yaml

+9
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ dimensions:
44
values:
55
- 3.2.4
66
- 3.3.4
7+
- 3.3.6
78
- name: hadoop-latest
89
values:
910
- 3.3.4
@@ -39,6 +40,9 @@ dimensions:
3940
# Requires manual setup, see create-kerberos-secretclass.yaml
4041
# This will *not* respect the kerberos-realm test attribute, but instead use a hard-coded realm
4142
# - activeDirectory
43+
- name: openshift
44+
values:
45+
- "false"
4246
tests:
4347
- name: smoke
4448
dimensions:
@@ -66,6 +70,11 @@ tests:
6670
dimensions:
6771
- hadoop-latest
6872
- zookeeper-latest
73+
- name: profiling
74+
dimensions:
75+
- hadoop
76+
- zookeeper-latest
77+
- openshift
6978
# Broken due to https://github.com/kudobuilder/kuttl/issues/322, see 40-assert.yaml for more details
7079
# - name: external-access
7180
# dimensions:

0 commit comments

Comments
 (0)