Skip to content

Commit bee0ed4

Browse files
committed
Release 0.2.5
1 parent f5feafd commit bee0ed4

13 files changed

+97
-51
lines changed

CITATION.cff

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
cff-version: "1.1.0"
22
message: "If you use this software, please cite it using these metadata."
33
title: ElasticBLAST
4-
version: "0.2.4"
5-
date-released: 2022-03-04
4+
version: "0.2.5"
5+
date-released: 2022-03-24
66
license: "NCBI Public Domain"
77
repository-code: "https://github.com/ncbi/elastic-blast/"
88
authors:

bin/aws-create-elastic-blast-janitor-role.sh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
# Author: Christiam Camacho (camacho@ncbi.nlm.nih.gov)
66
# Created: Mon Nov 29 17:29:31 EST 2021
77

8-
export PATH=/bin:/usr/local/bin:/usr/bin
98
set -xeuo pipefail
109
shopt -s nullglob
1110

bin/aws-delete-elastic-blast-janitor-role.sh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
# Author: Christiam Camacho (camacho@ncbi.nlm.nih.gov)
66
# Created: Tue Nov 30 08:07:53 EST 2021
77

8-
export PATH=/bin:/usr/local/bin:/usr/bin
98
set -xuo pipefail
109
shopt -s nullglob
1110

bin/aws-describe-elastic-blast-janitor-role.sh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
# Author: Christiam Camacho (camacho@ncbi.nlm.nih.gov)
66
# Created: Tue Nov 30 08:09:03 EST 2021
77

8-
export PATH=/bin:/usr/local/bin:/usr/bin
98
set -xuo pipefail
109
shopt -s nullglob
1110

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/bin/bash
2+
# bin/gcp-setup-elastic-blast-janitor.sh: Script to set up the ElasticBLAST
3+
# janitor permissions in GCP
4+
#
5+
# Author: Christiam Camacho (camacho@ncbi.nlm.nih.gov)
6+
# Created: Tue 08 Mar 2022 04:53:15 PM EST
7+
8+
set -euo pipefail
9+
shopt -s nullglob
10+
11+
command -v gcloud >&/dev/null || { echo "gcloud must be in your PATH for this script to work"; exit 1; }
12+
13+
user=$(gcloud config get-value account)
14+
prj=$(gcloud config get-value project)
15+
16+
usage() {
17+
echo -e "$0 [-h] [-u USERNAME] [-p GCP_PROJECT_ID]\n"
18+
echo -e "This script sets up the permissions to the ElasticBLAST janitor in GCP"
19+
echo -e "Options:"
20+
echo -e "\t-u USERNAME: GCP user, group or service account to configure (default: user:$user)"
21+
echo -e "\t\tFor specific format, please see https://cloud.google.com/sdk/gcloud/reference/projects/add-iam-policy-binding#--member"
22+
echo -e "\t-p GCP_PROJECT_ID: GCP project ID (default: ${prj})"
23+
echo -e "\t\tDocumentation: https://cloud.google.com/sdk/gcloud/reference/projects/add-iam-policy-binding#PROJECT_ID"
24+
echo -e "\t-h: Show this message"
25+
}
26+
27+
while getopts "u:ph" OPT; do
28+
case $OPT in
29+
u) user=${OPTARG}
30+
;;
31+
p) prj=${OPTARG}
32+
;;
33+
h) usage
34+
exit 0
35+
;;
36+
esac
37+
done
38+
39+
gcloud projects add-iam-policy-binding ${prj} --member=user:${user} --role=roles/container.admin

docker-blast/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ GCP_IMG?=gcr.io/ncbi-sandbox-blast/${IMG}
3030
AWS_SERVER?=public.ecr.aws/i6v3i0i9
3131
AWS_IMG?=${AWS_SERVER}/elasticblast-elb
3232
AWS_REGION?=us-east-1
33-
VERSION?=1.0.3
33+
VERSION?=1.1.0
3434

3535
ifeq (, $(shell which vmtouch 2>/dev/null))
3636
NOVMTOUCH?=--no-vmtouch

requirements/base.txt

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
wheel
2-
setuptools
3-
importlib-resources
4-
importlib-metadata
5-
pex
6-
boto3==1.21.10
7-
botocore==1.24.10
8-
awslimitchecker
9-
tenacity
10-
dataclasses_json
11-
types-pkg-resources
1+
wheel == 0.37.1
2+
setuptools == 56.0.0
3+
importlib-resources == 5.4.0
4+
importlib-metadata == 4.11.3
5+
pex == 2.1.73
6+
boto3 == 1.21.24
7+
botocore == 1.24.24
8+
awslimitchecker == 12.0.0
9+
tenacity == 8.0.1
10+
dataclasses-json == 0.5.7
11+
types-pkg-resources == 0.1.3

requirements/test.txt

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
-r base.txt
22

3-
pytest
4-
pytest-cov
5-
pytest-mock
6-
teamcity-messages
7-
mypy
8-
pylint==2.7.4
9-
tox
10-
yamllint
11-
moto >= 2.2.19
12-
docker
13-
cfn-lint
3+
pytest == 7.1.1
4+
pytest-cov == 3.0.0
5+
pytest-mock == 3.7.0
6+
teamcity-messages == 1.31
7+
mypy == 0.941
8+
pylint == 2.7.4
9+
tox == 3.24.5
10+
yamllint == 1.26.3
11+
moto == 3.1.1
12+
docker == 5.0.3
13+
cfn-lint == 0.58.4

src/elastic_blast/aws.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
from .constants import ELB_AWS_JANITOR_LAMBDA_DEPLOYMENT_BUCKET, ELB_AWS_JANITOR_LAMBDA_DEPLOYMENT_KEY
6464
from .constants import CFG_CLOUD_PROVIDER, CFG_CP_AWS_AUTO_SHUTDOWN_ROLE, CSP
6565
from .constants import AWS_JANITOR_ROLE_NAME
66+
from .constants import STATUS_MESSAGE_ERROR, STATUS_MESSAGE_VERBOSE
6667
from .filehelper import parse_bucket_name_key
6768
from .aws_traits import get_machine_properties, create_aws_config, get_availability_zones_for
6869
from .object_storage_utils import write_to_s3
@@ -933,20 +934,20 @@ def upload_query_length(self, query_length: int) -> None:
933934
logging.debug('dry-run: would have uploaded query length')
934935

935936

936-
def check_status(self, extended=False) -> Tuple[ElbStatus, Dict[str, int], str]:
937+
def check_status(self, extended=False) -> Tuple[ElbStatus, Dict[str, int], Dict[str, str]]:
937938
""" Check execution status of ElasticBLAST search
938939
Parameters:
939940
extended - do we need verbose information about jobs
940941
Returns:
941942
tuple of
942943
status - cluster status, ElbStatus
943944
counts - job counts for all job states
944-
verbose_result - detailed info about jobs
945+
verbose_result - a dictionary with entries: label, detailed info about jobs
945946
"""
946947
try:
947948
retval = self._status_from_results()
948949
if retval != ElbStatus.UNKNOWN:
949-
return retval, self.cached_counts, self.cached_failure_message
950+
return retval, self.cached_counts, {STATUS_MESSAGE_ERROR: self.cached_failure_message}
950951

951952
counts, details = self._check_status(extended)
952953
njobs = sum(counts.values())
@@ -995,12 +996,12 @@ def _load_job_ids_from_aws(self):
995996
raise
996997

997998
@handle_aws_error
998-
def _check_status(self, extended) -> Tuple[Dict[str, int], str]:
999+
def _check_status(self, extended) -> Tuple[Dict[str, int], Dict[str, str]]:
9991000
""" Internal check_status, converts AWS exceptions to UserReportError """
10001001
counts : Dict[str, int] = defaultdict(int)
10011002
if self.dry_run:
10021003
logging.info('dry-run: would have checked status')
1003-
return counts, ''
1004+
return counts, {}
10041005

10051006
if extended:
10061007
return self._check_status_extended()
@@ -1024,9 +1025,9 @@ def _check_status(self, extended) -> Tuple[Dict[str, int], str]:
10241025
'succeeded': counts['SUCCEEDED'],
10251026
'failed': counts['FAILED'],
10261027
}
1027-
return status, ''
1028+
return status, {}
10281029

1029-
def _check_status_extended(self) -> Tuple[Dict[str, int], str]:
1030+
def _check_status_extended(self) -> Tuple[Dict[str, int], Dict[str, str]]:
10301031
""" Internal check_status_extended, not protected against exceptions in AWS """
10311032
logging.debug(f'Retrieving jobs for queue {self.job_queue_name}')
10321033
jobs = {}
@@ -1073,7 +1074,7 @@ def _check_status_extended(self) -> Tuple[Dict[str, int], str]:
10731074
detailed_rep.append(f'{status.capitalize()} {jobs_in_status}')
10741075
if jobs_in_status:
10751076
detailed_rep.append('\n'.join(detailed_info[status]))
1076-
return counts, '\n'.join(detailed_rep)
1077+
return counts, {STATUS_MESSAGE_VERBOSE: '\n'.join(detailed_rep)}
10771078

10781079
def _remove_ancillary_data(self, bucket_prefix: str) -> None:
10791080
""" Removes ancillary data from the end user's result bucket

src/elastic_blast/commands/status.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import logging
3030
from typing import Any, List
3131

32-
from elastic_blast.constants import ElbCommand, ElbStatus
32+
from elastic_blast.constants import ElbCommand, ElbStatus, STATUS_MESSAGE_ERROR
3333
from elastic_blast.elasticblast_factory import ElasticBlastFactory
3434
from elastic_blast.elb_config import ElasticBlastConfig
3535

@@ -53,7 +53,7 @@ def _status(args, cfg: ElasticBlastConfig, clean_up_stack: List[Any]) -> int:
5353
cfg.validate(ElbCommand.STATUS)
5454
returncode = 0
5555
try:
56-
verbose_result = ''
56+
verbose_result = {}
5757
elastic_blast = ElasticBlastFactory(cfg, False, clean_up_stack)
5858
while True:
5959
status, counts, verbose_result = elastic_blast.check_status(args.verbose)
@@ -90,8 +90,10 @@ def _status(args, cfg: ElasticBlastConfig, clean_up_stack: List[Any]) -> int:
9090
print(f'Your ElasticBLAST search succeeded, results can be found in {cfg.cluster.results}')
9191
elif status == ElbStatus.FAILURE:
9292
print(FAILURE_MESSAGE)
93+
if not args.verbose and STATUS_MESSAGE_ERROR in verbose_result:
94+
print(verbose_result[STATUS_MESSAGE_ERROR])
9395
else:
9496
print(result)
9597
if args.verbose and verbose_result:
96-
print(verbose_result)
98+
print('\n'.join(verbose_result.values()))
9799
return returncode

src/elastic_blast/constants.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ def __str__(self):
200200
ELB_DFLT_GCP_REGION = 'us-east4'
201201
ELB_DFLT_AWS_REGION = 'us-east-1'
202202

203-
ELB_DOCKER_VERSION = '1.0.3'
203+
ELB_DOCKER_VERSION = '1.1.0'
204204
ELB_QS_DOCKER_VERSION = '0.1.2'
205205
ELB_JANITOR_DOCKER_VERSION = '0.2.0'
206206
ELB_JOB_SUBMIT_DOCKER_VERSION = '2.0.0'
@@ -327,3 +327,9 @@ def __str__(self):
327327
ELB_DFLT_NUM_BATCHES_FOR_TESTING = 100
328328
ELB_DFLT_LOGLEVEL = 'DEBUG'
329329
ELB_DFLT_LOGFILE = 'elastic-blast.log'
330+
331+
# Labels for messages generated when checking search status
332+
# alwsays printed to the screen
333+
STATUS_MESSAGE_ERROR = 'error'
334+
# printed only when requested
335+
STATUS_MESSAGE_VERBOSE = 'verbose'

src/elastic_blast/elasticblast.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,15 @@ def submit(self, query_batches: List[str], query_length, one_stage_cloud_query_s
7676
of executing a regular job """
7777

7878
@abstractmethod
79-
def check_status(self, extended=False) -> Tuple[ElbStatus, Dict[str, int], str]:
79+
def check_status(self, extended=False) -> Tuple[ElbStatus, Dict[str, int], Dict[str, str]]:
8080
""" Check execution status of ElasticBLAST search
8181
Parameters:
8282
extended - do we need verbose information about jobs
8383
Returns:
8484
tuple of
8585
status - cluster status, ElbStatus
8686
counts - job counts for all job states
87-
verbose_result - detailed info about jobs
87+
verbose_result - a dictionary where each entry is label, detailed info about jobs
8888
"""
8989

9090
# Compatibility method, used now only in janitor.py

src/elastic_blast/gcp.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
from .constants import GKE_CLUSTER_STATUS_PROVISIONING, GKE_CLUSTER_STATUS_RECONCILING
6060
from .constants import GKE_CLUSTER_STATUS_RUNNING, GKE_CLUSTER_STATUS_RUNNING_WITH_ERROR
6161
from .constants import GKE_CLUSTER_STATUS_STOPPING, GKE_CLUSTER_STATUS_ERROR
62+
from .constants import STATUS_MESSAGE_ERROR
6263
from .elb_config import ElasticBlastConfig
6364
from .elasticblast import ElasticBlast
6465

@@ -176,41 +177,41 @@ def submit(self, query_batches: List[str], query_length, one_stage_cloud_query_s
176177
self.cleanup_stack.clear()
177178
self.cleanup_stack.append(lambda: kubernetes.collect_k8s_logs(self.cfg))
178179

179-
def check_status(self, extended=False) -> Tuple[ElbStatus, Dict[str, int], str]:
180+
def check_status(self, extended=False) -> Tuple[ElbStatus, Dict[str, int], Dict[str, str]]:
180181
""" Check execution status of ElasticBLAST search
181182
Parameters:
182183
extended - do we need verbose information about jobs
183184
Returns:
184185
tuple of
185186
status - cluster status, ElbStatus
186187
counts - job counts for all job states
187-
verbose_result - detailed info about jobs
188+
verbose_result - a dictionary with enrties: label, detailed info about jobs
188189
"""
189190
try:
190191
return self._check_status(extended)
191192
except SafeExecError as err:
192193
# cluster is not valid, return empty result
193194
msg = err.message.strip()
194195
logging.info(msg)
195-
return ElbStatus.UNKNOWN, defaultdict(int), msg
196+
return ElbStatus.UNKNOWN, defaultdict(int), {STATUS_MESSAGE_ERROR: msg} if msg else {}
196197

197-
def _check_status(self, extended=False) -> Tuple[ElbStatus, Dict[str, int], str]:
198+
def _check_status(self, extended=False) -> Tuple[ElbStatus, Dict[str, int], Dict[str, str]]:
198199
# We cache only status from gone cluster - it can't change anymore
199200
if self.cached_status:
200-
return self.cached_status, self.cached_counts, self.cached_failure_message
201+
return self.cached_status, self.cached_counts, {STATUS_MESSAGE_ERROR: self.cached_failure_message} if self.cached_failure_message else {}
201202
counts: DefaultDict[str, int] = defaultdict(int)
202203
self._enable_gcp_apis()
203204
status = self._status_from_results()
204205
if status != ElbStatus.UNKNOWN:
205-
return status, self.cached_counts, self.cached_failure_message
206+
return status, self.cached_counts, {STATUS_MESSAGE_ERROR: self.cached_failure_message} if self.cached_failure_message else {}
206207

207208
gke_status = check_cluster(self.cfg)
208209
if not gke_status:
209-
return ElbStatus.UNKNOWN, {}, f'Cluster "{self.cfg.cluster.name}" was not found'
210+
return ElbStatus.UNKNOWN, {}, {STATUS_MESSAGE_ERROR: f'Cluster "{self.cfg.cluster.name}" was not found'}
210211

211212
logging.debug(f'GKE status: {gke_status}')
212213
if gke_status in [GKE_CLUSTER_STATUS_RECONCILING, GKE_CLUSTER_STATUS_PROVISIONING]:
213-
return ElbStatus.SUBMITTING, {}, ''
214+
return ElbStatus.SUBMITTING, {}, {}
214215

215216
if gke_status == GKE_CLUSTER_STATUS_STOPPING:
216217
# TODO: This behavior is consistent with current tests, consider returning a value
@@ -272,7 +273,7 @@ def _check_status(self, extended=False) -> Tuple[ElbStatus, Dict[str, int], str]
272273
if failed > 0:
273274
status = ElbStatus.FAILURE
274275

275-
return status, counts, ''
276+
return status, counts, {}
276277

277278
def _job_status_by_app(self, app):
278279
""" get status of jobs (pending/running, succeeded, failed) by app """

0 commit comments

Comments
 (0)