Skip to content
This repository was archived by the owner on Jun 13, 2024. It is now read-only.

Commit ef8afd8

Browse files
t-perssonTobias Persson
andauthored
Make sure etos client can download artifacts from events (#12)
Co-authored-by: Tobias Persson <tobias.persson@axis.com>
1 parent 1d0daaf commit ef8afd8

File tree

4 files changed

+122
-25
lines changed

4 files changed

+122
-25
lines changed

src/etos_client/lib/graphql.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
# limitations under the License.
1616
"""GraphQL query handler."""
1717
from .graphql_queries import (
18+
ARTIFACTS,
1819
ACTIVITY_TRIGGERED,
1920
CONFIDENCE_LEVEL,
2021
TEST_SUITE_STARTED,
@@ -205,3 +206,21 @@ def request_environment(etos, ids):
205206
yield environment
206207
return None # StopIteration
207208
return None # StopIteration
209+
210+
211+
def request_artifacts(etos, context):
212+
"""Request artifacts from graphql.
213+
214+
:param etos: ETOS client query etos.
215+
:type etos: :obj:`etos_lib.etos.ETOS`
216+
:param context: ID of the activity used in CONTEXT.
217+
:type context: str
218+
"""
219+
for response in request(etos, ARTIFACTS % context):
220+
if response:
221+
for _, artifact in etos.graphql.search_for_nodes(
222+
response, "artifactCreated"
223+
):
224+
yield artifact
225+
return None # StopIteration
226+
return None # StopIteration

src/etos_client/lib/graphql_queries.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,3 +154,44 @@
154154
}
155155
}
156156
"""
157+
158+
159+
ARTIFACTS = """
160+
{
161+
artifactCreated(search: "{'links.type': 'CONTEXT', 'links.target': '%s'}") {
162+
edges {
163+
node {
164+
data {
165+
fileInformation {
166+
name
167+
}
168+
}
169+
links {
170+
... on Cause {
171+
links {
172+
... on TestSuiteStarted {
173+
data {
174+
name
175+
}
176+
}
177+
}
178+
}
179+
}
180+
reverse {
181+
edges {
182+
node {
183+
... on ArtifactPublished {
184+
data {
185+
locations {
186+
uri
187+
}
188+
}
189+
}
190+
}
191+
}
192+
}
193+
}
194+
}
195+
}
196+
}
197+
"""

src/etos_client/lib/log_handler.py

Lines changed: 61 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import json
2020
import shutil
2121
from requests.exceptions import HTTPError
22+
from etos_client.lib.graphql import request_artifacts
2223

2324
_LOGGER = logging.getLogger(__name__)
2425

@@ -75,16 +76,23 @@ def all_logs(self):
7576
for log in self._logs(finished):
7677
yield log
7778

78-
def _get_path(self, _):
79-
"""Path to store log in.
80-
81-
:param log_name: Log name to check.
82-
:type log_name: str
83-
:return: Path where to store log.
84-
:rtype: str
85-
"""
86-
# TODO: Detect artifact logs for artifact_dir.
87-
return self.report_dir
79+
@property
80+
def all_artifacts(self):
81+
"""Iterate over all artifacts for the executed test suite."""
82+
for artifact_created in request_artifacts(
83+
self.etos, self.events.get("activityId")
84+
):
85+
for _, location in self.etos.utils.search(artifact_created, "uri"):
86+
suite_name = ""
87+
for link in artifact_created.get("links", []):
88+
for _, name in self.etos.utils.search(
89+
link.get("links", {}), "name"
90+
):
91+
suite_name = name # There should be exactly one!
92+
for _, name in self.etos.utils.search(
93+
artifact_created.get("data", {}), "name"
94+
):
95+
yield f"{suite_name}_{name}", f"{location}/{name}"
8896

8997
def _iut_data(self, environment):
9098
"""Get IUT data from Environment URI.
@@ -106,26 +114,55 @@ def iuts(self):
106114
if environment.get("data", {}).get("name", "").startswith("IUT Data"):
107115
yield self._iut_data(environment.get("data"))
108116

117+
def _download(self, name, uri, directory, spinner):
118+
"""Download a file and and write to disk.
119+
120+
:param name: Name of resulting file.
121+
:type name: str
122+
:param uri: URI from where the file can be downloaded.
123+
:type uri: str
124+
:param directory: Into which directory to write the downloaded file.
125+
:type directory: str
126+
:param spinner: Spinner text item.
127+
:type spinner: :obj:`Spinner`
128+
"""
129+
index = 0
130+
download_name = name
131+
while os.path.exists(os.path.join(directory, download_name)):
132+
index += 1
133+
download_name = f"{index}_{name}"
134+
spinner.text = "Downloading {}".format(download_name)
135+
generator = self.etos.http.wait_for_request(uri, as_json=False, stream=True)
136+
try:
137+
for response in generator:
138+
with open(os.path.join(directory, download_name), "wb+") as report:
139+
for chunk in response:
140+
report.write(chunk)
141+
break
142+
return True
143+
except (ConnectionError, HTTPError) as error:
144+
spinner.warn("Failed in downloading '{}'.".format(download_name))
145+
spinner.warn(str(error))
146+
return False
147+
109148
def download_logs(self, spinner):
110149
"""Download all logs to report and artifact directories."""
111150
nbr_of_logs_downloaded = 0
112151
incomplete = False
113152

114153
for name, uri in self.all_logs:
115-
path = self._get_path(name)
116-
spinner.text = "Downloading {}".format(name)
117-
generator = self.etos.http.wait_for_request(uri, as_json=False, stream=True)
118-
try:
119-
for response in generator:
120-
with open(os.path.join(path, name), "wb+") as report:
121-
for chunk in response:
122-
report.write(chunk)
123-
nbr_of_logs_downloaded += 1
124-
break
125-
except (ConnectionError, HTTPError) as error:
154+
result = self._download(name, uri, self.report_dir, spinner)
155+
if result:
156+
nbr_of_logs_downloaded += 1
157+
else:
158+
incomplete = True
159+
160+
for name, uri in self.all_artifacts:
161+
result = self._download(name, uri, self.artifact_dir, spinner)
162+
if result:
163+
nbr_of_logs_downloaded += 1
164+
else:
126165
incomplete = True
127-
spinner.warn("Failed in downloading '{}'.".format(name))
128-
spinner.warn(str(error))
129166

130167
for index, iut in enumerate(self.iuts):
131168
if iut is None:
@@ -135,7 +172,7 @@ def download_logs(self, spinner):
135172
filename = "IUT_{}.json".format(index)
136173
with open(os.path.join(self.artifact_dir, filename), "w+") as report:
137174
json.dump(iut, report)
138-
except: # pylint:disable=bare-except
175+
except Exception as error: # pylint:disable=broad-except
139176
spinner.warn("Failed in downloading '{}'.".format(filename))
140177
spinner.warn(str(error))
141178
incomplete = True

src/etos_client/lib/test_result_handler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ def get_events(self, suite_id):
205205
return {}
206206
self.activity_id = activity["meta"]["id"]
207207

208-
results = {}
208+
results = {"activityId": self.activity_id}
209209

210210
started = list(request_test_suite_started(self.etos, self.activity_id))
211211
if not started:

0 commit comments

Comments
 (0)