diff --git a/agents/craftassist/requirements.txt b/agents/craftassist/requirements.txt index 2693cfeef8..f15f8660e7 100644 --- a/agents/craftassist/requirements.txt +++ b/agents/craftassist/requirements.txt @@ -1,2 +1,3 @@ -r ../../requirements.txt -eventlet \ No newline at end of file +eventlet +moto[ec2,s3,all] \ No newline at end of file diff --git a/droidlet/tools/hitl/dashboard_app/README.MD b/droidlet/tools/hitl/dashboard_app/README.MD index c0e705242f..a9c1f5fb00 100644 --- a/droidlet/tools/hitl/dashboard_app/README.MD +++ b/droidlet/tools/hitl/dashboard_app/README.MD @@ -1,9 +1,11 @@ # Dashboard App for HITL -Updated July 13 by Chuxi. +Updated Aug 10 by Chuxi. This is a Dashboard app prototype for the HITL system. ## Update Note +- Aug 10: + - Updated dashboard_aws_helper_test.py to use mock s3. - July 14: - Added model visualization component, user can see text info about a model: - Demo: @@ -53,6 +55,8 @@ Please note this dashboard app is currently only in development build and is not - Dependency required for backend server (in addition to the droidelet setting, please make sure you have the updated version as below): Flask==2.1.2 Flask-SocketIO==5.2.0 +- You need to have the following python package to be able to run the tests: +moto==3.1.17 - Dependency for frontend is specified in the `fairo/droidlet/tools/hitl/dashboard_app/dashboard_frontend/package.json` file. ## How to run diff --git a/droidlet/tools/hitl/dashboard_app/backend/dashboard_aws_helper.py b/droidlet/tools/hitl/dashboard_app/backend/dashboard_aws_helper.py index f813998f88..58f4588b3b 100644 --- a/droidlet/tools/hitl/dashboard_app/backend/dashboard_aws_helper.py +++ b/droidlet/tools/hitl/dashboard_app/backend/dashboard_aws_helper.py @@ -79,7 +79,7 @@ def get_job_list(): pattern = r"([0-9]{4})(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])(2[0-3]|[01][0-9])([0-5][0-9])([0-5][0-9])" for prefix in res.search("CommonPrefixes"): - if re.match(pattern, prefix.get("Prefix")): + if prefix is not None and re.match(pattern, prefix.get("Prefix")): job_list.append(int(prefix.get("Prefix")[:-1])) return job_list diff --git a/droidlet/tools/hitl/dashboard_app/backend/tests/dashboard_aws_helper_test.py b/droidlet/tools/hitl/dashboard_app/backend/tests/dashboard_aws_helper_test.py index 6df072e91b..79624a5f82 100644 --- a/droidlet/tools/hitl/dashboard_app/backend/tests/dashboard_aws_helper_test.py +++ b/droidlet/tools/hitl/dashboard_app/backend/tests/dashboard_aws_helper_test.py @@ -1,73 +1,92 @@ import unittest import os +from unittest.mock import patch import boto3 +from moto import mock_s3 import json -from droidlet.tools.hitl.dashboard_app.backend.dashboard_aws_helper import ( - get_job_list, - get_run_info_by_id, - get_traceback_by_id, -) - S3_BUCKET_NAME = "droidlet-hitl" S3_ROOT = "s3://droidlet-hitl" VALID_ID = 222222222222222222 INVALID_ID = 11111111111111111 -AWS_ACCESS_KEY_ID = os.environ["AWS_ACCESS_KEY_ID"] -AWS_SECRET_ACCESS_KEY = os.environ["AWS_SECRET_ACCESS_KEY"] -AWS_DEFAULT_REGION = os.environ["AWS_DEFAULT_REGION"] - HITL_TMP_DIR = ( os.environ["HITL_TMP_DIR"] if os.getenv("HITL_TMP_DIR") else f"{os.path.expanduser('~')}/.hitl" ) -s3 = boto3.resource( - "s3", - region_name=AWS_DEFAULT_REGION, - aws_access_key_id=AWS_ACCESS_KEY_ID, - aws_secret_access_key=AWS_SECRET_ACCESS_KEY, -) +OS_ENV_DICT = { + "AWS_ACCESS_KEY_ID": "test_key_id", + "AWS_SECRET_ACCESS_KEY": "secretkkkkkk", + "AWS_DEFAULT_REGION": "us-east-1", +} +@mock_s3 class TestAWSHelper(unittest.TestCase): def setUp(self): + conn = boto3.resource("s3", region_name=OS_ENV_DICT["AWS_DEFAULT_REGION"]) + # We need to create the bucket since this is all in Moto's 'virtual' AWS account + conn.create_bucket(Bucket=S3_BUCKET_NAME) self._info_fname = f"job_management_records/{VALID_ID}.json" self._traceback_fname = f"{VALID_ID}/log_traceback.csv" some_dict = {"msg": "hello"} json_content = json.dumps(some_dict) + s3 = boto3.client("s3", region_name=OS_ENV_DICT["AWS_DEFAULT_REGION"]) + s3.put_object(Bucket=S3_BUCKET_NAME, Key=self._info_fname, Body=json_content) + s3.put_object(Bucket=S3_BUCKET_NAME, Key=self._traceback_fname, Body="1, 2 \n1, 2") - s3.Object(S3_BUCKET_NAME, self._info_fname).put(Body=json_content) - s3.Object(S3_BUCKET_NAME, self._traceback_fname).put(Body="1, 2 \n1, 2") - + @patch.dict("os.environ", OS_ENV_DICT) def test_get_job_list(self): + s3 = boto3.client("s3", region_name=OS_ENV_DICT["AWS_DEFAULT_REGION"]) + s3.put_object(Bucket=S3_BUCKET_NAME, Key="20220224132033/", Body="1, 2 \n1, 2") + from droidlet.tools.hitl.dashboard_app.backend.dashboard_aws_helper import get_job_list + res = get_job_list() self.assertGreater(len(res), 0) + @patch.dict("os.environ", OS_ENV_DICT) def test_get_traceback_by_id_valid(self): + from droidlet.tools.hitl.dashboard_app.backend.dashboard_aws_helper import ( + get_traceback_by_id, + ) + res, _ = get_traceback_by_id(VALID_ID) self.assertIsNotNone(res) self.assertNotEqual(res, f"cannot find traceback with id {VALID_ID}") + @patch.dict("os.environ", OS_ENV_DICT) def test_get_traceback_by_id_invalid(self): + from droidlet.tools.hitl.dashboard_app.backend.dashboard_aws_helper import ( + get_traceback_by_id, + ) + res, _ = get_traceback_by_id(INVALID_ID) self.assertEqual(res, f"cannot find traceback with id {INVALID_ID}") + @patch.dict("os.environ", OS_ENV_DICT) def test_get_run_info_by_id_valid(self): + from droidlet.tools.hitl.dashboard_app.backend.dashboard_aws_helper import ( + get_run_info_by_id, + ) + res, _ = get_run_info_by_id(VALID_ID) self.assertIsNotNone(res) self.assertNotEqual(res, f"cannot find run info with id {VALID_ID}") + @patch.dict("os.environ", OS_ENV_DICT) + @mock_s3 def test_get_run_info_by_id_inalid(self): + from droidlet.tools.hitl.dashboard_app.backend.dashboard_aws_helper import ( + get_run_info_by_id, + ) + res, _ = get_run_info_by_id(INVALID_ID) self.assertEqual(res, f"cannot find run info with id {INVALID_ID}") def tearDown(self): - s3.Object(S3_BUCKET_NAME, self._info_fname).delete() - s3.Object(S3_BUCKET_NAME, self._traceback_fname).delete() - - # remove from local temp directory as well + # no need to clean up s3 as using mock s3 client + # remove from local temp directory local_info_fname = os.path.join(HITL_TMP_DIR, self._info_fname) local_traceback_fname = os.path.join(HITL_TMP_DIR, self._traceback_fname) if os.path.exists(local_info_fname):