Skip to content

Commit d672174

Browse files
committed
test: new test, verify support data collection
Signed-off-by: Joachim Wiberg <[email protected]>
1 parent d1f053b commit d672174

File tree

7 files changed

+256
-0
lines changed

7 files changed

+256
-0
lines changed

test/case/misc/Readme.adoc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
11
:testgroup:
22
== Miscellaneous Tests
33

4+
Tests verifying system utilities and operational features:
5+
6+
- Operational datastore query for all configuration
7+
- Support data collection with work-dir and GPG encryption
8+
49
include::operational_all/Readme.adoc[]
10+
11+
<<<
12+
13+
include::support_collect/Readme.adoc[]

test/case/misc/all.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,8 @@
22
- name: Get operational
33
case: operational_all/test.py
44

5+
- name: Support data collection
6+
case: support_collect/test.py
7+
58
#- name: start_from_startup
69
# case: start_from_startup.py
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
test.adoc
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
=== Support data collection
2+
3+
ifdef::topdoc[:imagesdir: {topdoc}../../test/case/misc/support_collect]
4+
5+
==== Description
6+
7+
Verify that the support collect command works and produces a valid tarball
8+
with expected content. Tests both the --work-dir global option and GPG
9+
encryption (when available on target).
10+
11+
==== Topology
12+
13+
image::topology.svg[Support data collection topology, align=center, scaledwidth=75%]
14+
15+
==== Sequence
16+
17+
. Set up topology and attach to target DUT
18+
. Check for GPG availability on target
19+
. Run support collect with --work-dir and short log tail
20+
. Verify tarball was created and is valid
21+
. Run support collect with GPG encryption
22+
. Verify encrypted file and decrypt it
23+
24+
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
#!/usr/bin/env python3
2+
"""Support data collection
3+
4+
Verify that the support collect command works and produces a valid tarball
5+
with expected content. Tests both the --work-dir global option and GPG
6+
encryption (when available on target).
7+
8+
"""
9+
10+
import os
11+
import subprocess
12+
import tarfile
13+
import tempfile
14+
import infamy
15+
import infamy.ssh as ssh
16+
17+
with infamy.Test() as test:
18+
with test.step("Set up topology and attach to target DUT"):
19+
env = infamy.Env()
20+
target = env.attach("target", "mgmt")
21+
tgtssh = env.attach("target", "mgmt", "ssh")
22+
23+
with test.step("Check for GPG availability on target"):
24+
result = tgtssh.run("command -v gpg >/dev/null 2>&1", check=False)
25+
has_gpg = (result.returncode == 0)
26+
if has_gpg:
27+
print("GPG is available on target - will test encryption")
28+
else:
29+
print("GPG not available on target - skipping encryption tests")
30+
31+
with test.step("Run support collect with --work-dir and short log tail"):
32+
# Create temporary file for output
33+
with tempfile.NamedTemporaryFile(suffix=".tar.gz", delete=False) as tmp:
34+
output_file = tmp.name
35+
36+
# Use /tmp as work-dir to test the --work-dir option
37+
# Run support collect via SSH with short log tail for testing
38+
# Capture stdout (the tarball) to file
39+
# Note: timeout is generous to handle systems with many network ports
40+
# (ethtool collection scales with number of interfaces)
41+
with open(output_file, 'wb') as f:
42+
result = tgtssh.run("support --work-dir /tmp collect --log-sec 2",
43+
stdout=f,
44+
stderr=subprocess.PIPE,
45+
timeout=120)
46+
47+
if result.returncode != 0:
48+
stderr_output = result.stderr.decode('utf-8') if result.stderr else ""
49+
print(f"support collect failed with return code {result.returncode}")
50+
print(f"stderr: {stderr_output}")
51+
raise Exception("support collect command failed")
52+
53+
with test.step("Verify tarball was created and is valid"):
54+
if not os.path.exists(output_file):
55+
raise Exception(f"Output file {output_file} was not created")
56+
57+
file_size = os.path.getsize(output_file)
58+
if file_size == 0:
59+
raise Exception("Output tarball is empty")
60+
61+
print(f"Tarball created: {file_size} bytes")
62+
63+
# Verify it's a valid tar.gz
64+
try:
65+
with tarfile.open(output_file, 'r:gz') as tar:
66+
members = tar.getnames()
67+
print(f"Tarball contains {len(members)} files/directories")
68+
69+
# Verify some expected files exist
70+
expected_files = [
71+
'collection.log',
72+
'operational-config.json',
73+
'system/dmesg.txt',
74+
'system/meminfo.txt',
75+
'network/ip/addr.json'
76+
]
77+
78+
root_dir = members[0] if members else None
79+
for expected in expected_files:
80+
full_path = f"{root_dir}/{expected}" if root_dir else expected
81+
if full_path not in members:
82+
print(f"Warning: Expected file '{expected}' not found in tarball")
83+
else:
84+
print(f"Found: {expected}")
85+
86+
except tarfile.TarError as e:
87+
raise Exception(f"Invalid tarball: {e}")
88+
89+
finally:
90+
# Clean up
91+
if os.path.exists(output_file):
92+
os.remove(output_file)
93+
94+
if has_gpg:
95+
with test.step("Run support collect with GPG encryption"):
96+
# Create temporary file for encrypted output
97+
with tempfile.NamedTemporaryFile(suffix=".tar.gz.gpg", delete=False) as tmp:
98+
encrypted_file = tmp.name
99+
100+
# Use a test password
101+
test_password = "test-support-password-123"
102+
103+
# Run support collect with encryption
104+
with open(encrypted_file, 'wb') as f:
105+
result = tgtssh.run(f"support --work-dir /tmp collect --log-sec 2 --password {test_password}",
106+
stdout=f,
107+
stderr=subprocess.PIPE,
108+
timeout=120)
109+
110+
if result.returncode != 0:
111+
stderr_output = result.stderr.decode('utf-8') if result.stderr else ""
112+
print(f"support collect with encryption failed: {stderr_output}")
113+
raise Exception("support collect with --password failed")
114+
115+
with test.step("Verify encrypted file and decrypt it"):
116+
if not os.path.exists(encrypted_file):
117+
raise Exception(f"Encrypted output file {encrypted_file} was not created")
118+
119+
file_size = os.path.getsize(encrypted_file)
120+
if file_size == 0:
121+
raise Exception("Encrypted output file is empty")
122+
123+
print(f"Encrypted file created: {file_size} bytes")
124+
125+
# Create temporary file for decrypted output
126+
with tempfile.NamedTemporaryFile(suffix=".tar.gz", delete=False) as tmp:
127+
decrypted_file = tmp.name
128+
129+
try:
130+
# Decrypt the file using gpg
131+
with open(encrypted_file, 'rb') as ef:
132+
with open(decrypted_file, 'wb') as df:
133+
decrypt_result = subprocess.run(
134+
["gpg", "--batch", "--yes", "--passphrase", test_password,
135+
"--pinentry-mode", "loopback", "-d"],
136+
stdin=ef,
137+
stdout=df,
138+
stderr=subprocess.PIPE,
139+
timeout=30
140+
)
141+
142+
if decrypt_result.returncode != 0:
143+
stderr_output = decrypt_result.stderr.decode('utf-8') if decrypt_result.stderr else ""
144+
print(f"GPG decryption failed: {stderr_output}")
145+
raise Exception("Failed to decrypt GPG-encrypted support data")
146+
147+
print("Successfully decrypted GPG file")
148+
149+
# Verify the decrypted file is a valid tarball
150+
with tarfile.open(decrypted_file, 'r:gz') as tar:
151+
members = tar.getnames()
152+
print(f"Decrypted tarball contains {len(members)} files/directories")
153+
154+
# Verify some expected files exist
155+
expected_files = [
156+
'collection.log',
157+
'operational-config.json',
158+
'system/dmesg.txt'
159+
]
160+
161+
root_dir = members[0] if members else None
162+
for expected in expected_files:
163+
full_path = f"{root_dir}/{expected}" if root_dir else expected
164+
if full_path not in members:
165+
print(f"Warning: Expected file '{expected}' not found in decrypted tarball")
166+
else:
167+
print(f"Found in decrypted tarball: {expected}")
168+
169+
except tarfile.TarError as e:
170+
raise Exception(f"Decrypted file is not a valid tarball: {e}")
171+
172+
except subprocess.TimeoutExpired:
173+
raise Exception("GPG decryption timed out")
174+
175+
except FileNotFoundError:
176+
print("Warning: gpg not available on host system - skipping decryption verification")
177+
178+
finally:
179+
# Clean up
180+
if os.path.exists(encrypted_file):
181+
os.remove(encrypted_file)
182+
if os.path.exists(decrypted_file):
183+
os.remove(decrypted_file)
184+
185+
test.succeed()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../infamy/topologies/1x1.dot
Lines changed: 33 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)