Skip to content

Commit 21069c3

Browse files
update_job_status() now has option to ignore runtime errors (#51)
* update_job_status() now has option to ignore runtime errors * Updates based on CI failures * Updated CI config * Migrating CI off Python 2.x Migrating CI off Python 2.x to support latest change. Since latest change is straightforward, current operation using Python 2.7 should not be disrupted. * Updated CI configuration based on qp-klp plugin config. * bugfix * Recently renamed certs * Remove 3.11 from test matrix * Added script to add qiita root-ca to environment. Added script to add the root-ca used to sign Qiita's server.crt to qiita_client's environment. The functionality in this small script may be more useful if it becomes part of qiita_client itself. * Update PluginTestCase base class Update PluginTestCase base class to rely on standard environment to verify server credentials. Rely on new script to update standard environment. * Updated CI config to avoid installing extra plugins * Updates from testing * Add testing for 3.11 * Removed matrix testing for python 3.11 * test removal of pip updates * Test removal of some qiita installation commands * Updated based on discussions * test change * Removed unused config setting * Updates based on feedback
1 parent d4e83b7 commit 21069c3

File tree

7 files changed

+80
-40
lines changed

7 files changed

+80
-40
lines changed

.github/workflows/qiita-ci.yml

+4-8
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111

1212
strategy:
1313
matrix:
14-
python-version: ["2.7", "3.9"]
14+
python-version: ["3.9"]
1515

1616
services:
1717
postgres:
@@ -79,14 +79,13 @@ jobs:
7979
run: |
8080
conda create --yes -n qiita_client python=${{ matrix.python-version }} pip nose flake8 coverage
8181
conda activate qiita_client
82-
8382
pip --quiet install .
8483
8584
- name: Starting Main Services
8685
shell: bash -l {0}
8786
run: |
8887
conda activate qiita
89-
export QIITA_SERVER_CERT=`pwd`/qiita-dev/qiita_core/support_files/server.crt
88+
export QIITA_ROOTCA_CERT=`pwd`/qiita-dev/qiita_core/support_files/ci_rootca.crt
9089
export QIITA_CONFIG_FP=`pwd`/qiita-dev/qiita_core/support_files/config_test_local.cfg
9190
sed "s#/home/runner/work/qiita/qiita#${PWD}/qiita-dev/#g" `pwd`/qiita-dev/qiita_core/support_files/config_test.cfg > ${QIITA_CONFIG_FP}
9291
@@ -118,12 +117,9 @@ jobs:
118117
COVER_PACKAGE: ${{ matrix.cover_package }}
119118
run: |
120119
conda activate qiita_client
121-
export QIITA_SERVER_CERT=`pwd`/qiita-dev/qiita_core/support_files/server.crt
120+
export QIITA_ROOTCA_CERT=`pwd`/qiita-dev/qiita_core/support_files/ci_rootca.crt
122121
export QIITA_CONFIG_FP=`pwd`/qiita-dev/qiita_core/support_files/config_test_local.cfg
123-
124-
nosetests --with-doctest --with-coverage --cover-package=qiita_client
125-
126-
- uses: codecov/codecov-action@v1
122+
- uses: codecov/codecov-action@v3
127123
with:
128124
token: ${{ secrets.CODECOV_TOKEN }}
129125
file: codecov.yml

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ This package includes the Qiita Client utility library, a library to simplify th
1010
How to test this package?
1111
-------------------------
1212
In order to test the Qiita Client package, a local installation of Qiita should be running in test mode on the address `https://localhost:21174`, with the default test database created in Qiita's test suite.
13-
Also, if Qiita is running with the default server SSL certificate, you need to export the variable `QIITA_SERVER_CERT` in your environment, so the Qiita Client can perform secure connections against the Qiita server:
13+
Also, if Qiita is running with the default server SSL certificate, you need to export the variable `QIITA_ROOTCA_CERT` in your environment, so the Qiita Client can perform secure connections against the Qiita server:
1414

1515
```bash
1616

17-
export QIITA_SERVER_CERT=<QIITA_INSTALL_PATH>/qiita_core/support_files/server.crt
17+
export QIITA_ROOT_CA=<QIITA_INSTALL_PATH>/qiita_core/support_files/ci_rootca.crt
1818
```

qiita_client/plugin.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,12 @@ def __call__(self, server_url, job_id, output_dir):
245245

246246
qclient = QiitaClient(server_url, config.get('oauth2', 'CLIENT_ID'),
247247
config.get('oauth2', 'CLIENT_SECRET'),
248-
server_cert=config.get('oauth2', 'SERVER_CERT'))
248+
# for this group of tests, confirm optional
249+
# ca_cert parameter works as intended. Setting
250+
# this value will prevent underlying libraries
251+
# from validating the server's cert using
252+
# certifi's pem cache.
253+
ca_cert=environ['QIITA_ROOTCA_CERT'])
249254

250255
if job_id == 'register':
251256
self._register(qclient)
@@ -374,6 +379,5 @@ def register_command(self, command):
374379
PUBLICATIONS = %s
375380
376381
[oauth2]
377-
SERVER_CERT = %s
378382
CLIENT_ID = %s
379383
CLIENT_SECRET = %s"""

qiita_client/qiita_client.py

+21-10
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def __init__(self, output_name, artifact_type, files, archive=None):
5757

5858
def __eq__(self, other):
5959
logger.debug('Entered ArtifactInfo.__eq__()')
60-
if type(self) != type(other):
60+
if type(self) is not type(other):
6161
return False
6262
if self.output_name != other.output_name or \
6363
self.artifact_type != other.artifact_type or \
@@ -166,16 +166,16 @@ class QiitaClient(object):
166166
The client id to connect to the Qiita server
167167
client_secret : str
168168
The client secret id to connect to the Qiita server
169-
server_cert : str, optional
170-
The server certificate, in case that it is not verified
169+
ca_cert : str, optional
170+
CA cert used to sign and verify cert@server_url
171171
172172
173173
Methods
174174
-------
175175
get
176176
post
177177
"""
178-
def __init__(self, server_url, client_id, client_secret, server_cert=None):
178+
def __init__(self, server_url, client_id, client_secret, ca_cert=None):
179179
self._server_url = server_url
180180
self._session = requests.Session()
181181

@@ -186,16 +186,21 @@ def __init__(self, server_url, client_id, client_secret, server_cert=None):
186186
# if certificate verification should be performed or not, or a
187187
# string with the path to the certificate file that needs to be used
188188
# to verify the identity of the server.
189-
# We are setting this attribute at __init__ time so we can avoid
190-
# executing this if statement for each request issued.
191-
if not server_cert:
189+
# We are setting this attribute at __init__ time to avoid executing
190+
# this if statement for each request issued.
191+
192+
# As self-signed server certs are no longer allowed in one or more of
193+
# our dependencies, ca_cert (if provided) must now reference a file
194+
# that can be used to verify the certificate used by the server
195+
# referenced by server_url, rather than the server's own certificate.
196+
if not ca_cert:
192197
# The server certificate is not provided, use standard certificate
193198
# verification methods
194199
self._verify = True
195200
else:
196201
# The server certificate is provided, use it to verify the identity
197202
# of the server
198-
self._verify = server_cert
203+
self._verify = ca_cert
199204

200205
# Set up oauth2
201206
self._client_id = client_id
@@ -527,7 +532,7 @@ def get_job_info(self, job_id):
527532
logger.debug('Entered QiitaClient.get_job_info()')
528533
return self.get("/qiita_db/jobs/%s" % job_id)
529534

530-
def update_job_step(self, job_id, new_step):
535+
def update_job_step(self, job_id, new_step, ignore_error=True):
531536
"""Updates the current step of the job in the server
532537
533538
Parameters
@@ -536,10 +541,16 @@ def update_job_step(self, job_id, new_step):
536541
The job id
537542
new_step : str
538543
The new step
544+
ignore_error : bool
545+
Problems communicating w/Qiita will not raise an Error.
539546
"""
540547
logger.debug('Entered QiitaClient.update_job_step()')
541548
json_payload = dumps({'step': new_step})
542-
self.post("/qiita_db/jobs/%s/step/" % job_id, data=json_payload)
549+
try:
550+
self.post("/qiita_db/jobs/%s/step/" % job_id, data=json_payload)
551+
except BaseException as e:
552+
if ignore_error is False:
553+
raise e
543554

544555
def complete_job(self, job_id, success, error_msg=None,
545556
artifacts_info=None):

qiita_client/testing.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ def setUpClass(cls):
2424
cls.client_id = '19ndkO3oMKsoChjVVWluF7QkxHRfYhTKSFbAVt8IhK7gZgDaO4'
2525
cls.client_secret = ('J7FfQ7CQdOxuKhQAf1eoGgBAE81Ns8Gu3EKaWFm3IO2JKh'
2626
'AmmCWZuabe0O5Mp28s1')
27-
cls.server_cert = environ.get('QIITA_SERVER_CERT', None)
2827
qiita_port = int(environ.get('QIITA_PORT', 21174))
29-
cls.qclient = QiitaClient(
30-
"https://localhost:%d" % qiita_port, cls.client_id,
31-
cls.client_secret, server_cert=cls.server_cert)
28+
29+
# do not rely on defining ca_cert for these tests. Instead append
30+
# the appropriate CA cert to certifi's pem file.
31+
cls.qclient = QiitaClient("https://localhost:%d" % qiita_port,
32+
cls.client_id, cls.client_secret)
3233
logger.debug(
3334
'PluginTestCase.setUpClass() token %s' % cls.qclient._token)
3435
cls.qclient.post('/apitest/reload_plugins/')

qiita_client/tests/test_plugin.py

+3-6
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,7 @@ def html_generator_func(a, b, c, d):
146146
'PLUGIN_TYPE = artifact definition\n',
147147
'PUBLICATIONS = \n',
148148
'\n',
149-
'[oauth2]\n',
150-
'SERVER_CERT = \n']
149+
'[oauth2]\n']
151150
# We will test the last 2 lines independently since they're variable
152151
# in each test run
153152
self.assertEqual(conf[:-2], exp_lines)
@@ -168,8 +167,7 @@ def html_generator_func(a, b, c, d):
168167
validate_func, html_generator_func, atypes)
169168

170169
# Generate the config file for the new plugin
171-
tester.generate_config('ls', 'echo',
172-
server_cert=self.server_cert)
170+
tester.generate_config('ls', 'echo')
173171
# Ask Qiita to reload the plugins
174172
self.qclient.post('/apitest/reload_plugins/')
175173

@@ -213,8 +211,7 @@ def func(qclient, job_id, job_params, working_dir):
213211
{'out1': 'Demultiplexed'})
214212
tester.register_command(a_cmd)
215213

216-
tester.generate_config('ls', 'echo',
217-
server_cert=self.server_cert)
214+
tester.generate_config('ls', 'echo')
218215
self.qclient.post('/apitest/reload_plugins/')
219216
tester("https://localhost:21174", 'register', 'ignored')
220217

qiita_client/tests/test_qiita_client.py

+39-8
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
# -----------------------------------------------------------------------------
88

99
from unittest import TestCase, main
10-
from os import environ, remove, close
10+
from os import remove, close, environ
1111
from os.path import basename, exists
1212
from tempfile import mkstemp
1313
from json import dumps
@@ -19,6 +19,7 @@
1919
from qiita_client.exceptions import BadRequestError
2020

2121
CLIENT_ID = '19ndkO3oMKsoChjVVWluF7QkxHRfYhTKSFbAVt8IhK7gZgDaO4'
22+
BAD_CLIENT_ID = 'NOT_A_CLIENT_ID'
2223
CLIENT_SECRET = ('J7FfQ7CQdOxuKhQAf1eoGgBAE81Ns8Gu3EKaWFm3IO2JKh'
2324
'AmmCWZuabe0O5Mp28s1')
2425

@@ -96,9 +97,12 @@ def test_format_payload_error(self):
9697

9798
class QiitaClientTests(PluginTestCase):
9899
def setUp(self):
99-
self.server_cert = environ.get('QIITA_SERVER_CERT', None)
100-
self.tester = QiitaClient("https://localhost:21174", CLIENT_ID,
101-
CLIENT_SECRET, server_cert=self.server_cert)
100+
self.tester = QiitaClient("https://localhost:21174",
101+
CLIENT_ID,
102+
CLIENT_SECRET)
103+
self.bad_tester = QiitaClient("https://localhost:21174",
104+
BAD_CLIENT_ID,
105+
CLIENT_SECRET)
102106
self.clean_up_files = []
103107

104108
# making assertRaisesRegex compatible with Python 2.7 and 3.9
@@ -111,12 +115,14 @@ def tearDown(self):
111115
remove(fp)
112116

113117
def test_init(self):
114-
obs = QiitaClient("https://localhost:21174", CLIENT_ID,
115-
CLIENT_SECRET, server_cert=self.server_cert)
118+
obs = QiitaClient("https://localhost:21174",
119+
CLIENT_ID,
120+
CLIENT_SECRET,
121+
ca_cert=environ['QIITA_ROOT_CA'])
116122
self.assertEqual(obs._server_url, "https://localhost:21174")
117123
self.assertEqual(obs._client_id, CLIENT_ID)
118124
self.assertEqual(obs._client_secret, CLIENT_SECRET)
119-
self.assertEqual(obs._verify, self.server_cert)
125+
self.assertEqual(obs._verify, environ['QIITA_ROOT_CA'])
120126

121127
def test_get(self):
122128
obs = self.tester.get("/qiita_db/artifacts/1/")
@@ -232,11 +238,36 @@ def test_update_job_step(self):
232238
obs = self.tester.update_job_step(job_id, new_step)
233239
self.assertIsNone(obs)
234240

241+
def test_update_job_step_ignore_failure(self):
242+
job_id = "bcc7ebcd-39c1-43e4-af2d-822e3589f14d"
243+
new_step = "some new step"
244+
245+
# confirm that update_job_step behaves as before when ignore_error
246+
# parameter absent or set to False.
247+
248+
with self.assertRaises(BaseException):
249+
self.bad_tester.update_job_step(job_id, new_step)
250+
251+
with self.assertRaises(BaseException):
252+
self.bad_tester.update_job_step(job_id,
253+
new_step,
254+
ignore_error=False)
255+
256+
# confirm that when ignore_error is set to True, an Error is NOT
257+
# raised.
258+
try:
259+
self.bad_tester.update_job_step(job_id,
260+
new_step,
261+
ignore_error=True)
262+
except BaseException as e:
263+
self.fail("update_job_step() raised an error: %s" % str(e))
264+
235265
def test_complete_job(self):
236266
# Create a new job
237267
data = {
238268
'user': '[email protected]',
239-
'command': dumps(['QIIME', '1.9.1', 'Pick closed-reference OTUs']),
269+
'command': dumps(['QIIMEq2', '1.9.1',
270+
'Pick closed-reference OTUs']),
240271
'status': 'running',
241272
'parameters': dumps({"reference": 1,
242273
"sortmerna_e_value": 1,

0 commit comments

Comments
 (0)