From c3480221b77f04e8004d419d06d121d3c5023140 Mon Sep 17 00:00:00 2001 From: zgoldberg22 Date: Mon, 18 Dec 2023 16:14:43 -0500 Subject: [PATCH 01/14] added plans tags to be downloaded --- src/aerie_cli/aerie_client.py | 6 ++++++ src/aerie_cli/schemas/api.py | 1 + src/aerie_cli/schemas/client.py | 13 +++++++++++++ 3 files changed, 20 insertions(+) diff --git a/src/aerie_cli/aerie_client.py b/src/aerie_cli/aerie_client.py index 3c606482..3910e424 100644 --- a/src/aerie_cli/aerie_client.py +++ b/src/aerie_cli/aerie_client.py @@ -62,6 +62,12 @@ def get_activity_plan_by_id(self, plan_id: int, full_args: str = None) -> Activi simulations{ id } + tags { + tag { + id + name + } + } activity_directives(order_by: { start_offset: asc }) { id name diff --git a/src/aerie_cli/schemas/api.py b/src/aerie_cli/schemas/api.py index 1d7a872e..e4658d41 100644 --- a/src/aerie_cli/schemas/api.py +++ b/src/aerie_cli/schemas/api.py @@ -119,6 +119,7 @@ class ApiActivityPlanBase(ApiSerialize): start_time: Arrow = field( converter=arrow.get ) + tags: List[Dict] @define class ApiActivityPlanCreate(ApiActivityPlanBase): diff --git a/src/aerie_cli/schemas/client.py b/src/aerie_cli/schemas/client.py index c8ecdc00..309e1eb1 100644 --- a/src/aerie_cli/schemas/client.py +++ b/src/aerie_cli/schemas/client.py @@ -113,6 +113,7 @@ class EmptyActivityPlan(ClientSerialize): ) end_time: Arrow = field( converter = arrow.get) + tags: List[Dict] def duration(self) -> timedelta: return self.end_time - self.start_time @@ -145,6 +146,9 @@ class ActivityPlanCreate(EmptyActivityPlan): sim_id: Optional[int] = field( default=None ) + tags: Optional[List[Dict]] = field( + default=None + ) @classmethod @@ -154,6 +158,7 @@ def from_plan_read(cls, plan_read: "ActivityPlanRead") -> "ActivityPlanCreate": start_time=plan_read.start_time, end_time=plan_read.end_time, activities=plan_read.activities, + tags=plan_read.tags ) def to_api_create(self, model_id: int) -> "ApiActivityPlanCreate": @@ -162,6 +167,7 @@ def to_api_create(self, model_id: int) -> "ApiActivityPlanCreate": name=self.name, start_time=self.start_time, duration=self.end_time - self.start_time, + tags=self.tags ) @@ -170,6 +176,12 @@ class ActivityPlanRead(EmptyActivityPlan): id: int model_id: int sim_id: int + tags: Optional[List[Dict]] = field( + default = None, + converter=converters.optional( + lambda listOfDicts: [d for d in listOfDicts] + ) + ) activities: Optional[List[Activity]] = field( default = None, converter=converters.optional( @@ -220,6 +232,7 @@ def from_api_read(cls, api_plan_read: ApiActivityPlanRead) -> "ActivityPlanRead" sim_id=api_plan_read.simulations[0]["id"], start_time=plan_start, end_time=plan_start + api_plan_read.duration, + tags=api_plan_read.tags, activities= None if api_plan_read.activity_directives is None else [ Activity.from_api_read(api_activity) for api_activity in api_plan_read.activity_directives From 1ac075674ec512cc8d046a7fc3669a93e73f4d96 Mon Sep 17 00:00:00 2001 From: zgoldberg22 Date: Wed, 20 Dec 2023 15:50:28 +0600 Subject: [PATCH 02/14] initial modifications to upload plan tags --- src/aerie_cli/aerie_client.py | 63 +++++++++++++++++++++++++++++++++ src/aerie_cli/schemas/client.py | 3 +- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/aerie_cli/aerie_client.py b/src/aerie_cli/aerie_client.py index 3910e424..60105b9d 100644 --- a/src/aerie_cli/aerie_client.py +++ b/src/aerie_cli/aerie_client.py @@ -153,6 +153,63 @@ def get_plan_id_by_sim_id(self, simulation_dataset_id: int) -> int: simulation_dataset_id=simulation_dataset_id ) return resp['simulation']['plan']['id'] + + def get_tag_id_by_name(self, tag_name: str): + get_tags_by_name_query = """ + query GetTagByName($name: String) { + tags(where: {name: {_eq: $name}}) { + id + } + } + """ + + #make default color of tag white + create_new_tag = """ + mutation CreateNewTag($name: String, $color: String = "#FFFFFF") { + insert_tags_one(object: {name: $name, color: $color}) { + id + } + } + """ + + resp = self.aerie_host.post_to_graphql( + get_tags_by_name_query, + name=tag_name + ) + + #if a tag with the specified name exists and returns the ID, else creates a new tag with this name + if len(resp["tags"]) > 0: + return resp["tags"][0]["id"] + else: + new_tag_resp = self.aerie_host.post_to_graphql( + create_new_tag, + name=tag_name + ) + + return new_tag_resp["id"] + + def add_plan_tag(self, plan_id: int, tag_name: str): + add_tag_to_plan = """ + mutation AddTagToPlan($plan_id: Int, $tag_id: Int) { + insert_plan_tags(objects: {plan_id: $plan_id, tag_id: $tag_id}) { + returning { + tag_id + } + } + } + """ + #add tag to plan + tag_to_add = { + "plan_id": plan_id, + "tag_id": self.get_tag_id_by_name(tag_name) + } + + resp = self.aerie_host.post_to_graphql( + add_tag_to_plan, + objects={tag_to_add} + ) + + return resp[0] def create_activity_plan( self, model_id: int, plan_to_create: ActivityPlanCreate @@ -173,6 +230,12 @@ def create_activity_plan( ) plan_id = plan_resp["id"] plan_revision = plan_resp["revision"] + + #add plan tags if exists + if len(plan_to_create.tags) > 0: + for tag in plan_to_create.tags: + self.add_plan_tag(plan_id, tag["name"]) + # This loop exists to make sure all anchor IDs are updated as necessary # Deep copy activities so we can augment and pop from the list diff --git a/src/aerie_cli/schemas/client.py b/src/aerie_cli/schemas/client.py index 309e1eb1..d8e15760 100644 --- a/src/aerie_cli/schemas/client.py +++ b/src/aerie_cli/schemas/client.py @@ -147,7 +147,7 @@ class ActivityPlanCreate(EmptyActivityPlan): default=None ) tags: Optional[List[Dict]] = field( - default=None + default=[] ) @@ -167,7 +167,6 @@ def to_api_create(self, model_id: int) -> "ApiActivityPlanCreate": name=self.name, start_time=self.start_time, duration=self.end_time - self.start_time, - tags=self.tags ) From b63fb3d355728138b65f3e0833ca297ddbf9952e Mon Sep 17 00:00:00 2001 From: zgoldberg22 Date: Wed, 20 Dec 2023 16:19:05 +0600 Subject: [PATCH 03/14] fixed edit to api for tags --- src/aerie_cli/schemas/api.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/aerie_cli/schemas/api.py b/src/aerie_cli/schemas/api.py index e4658d41..1d7a872e 100644 --- a/src/aerie_cli/schemas/api.py +++ b/src/aerie_cli/schemas/api.py @@ -119,7 +119,6 @@ class ApiActivityPlanBase(ApiSerialize): start_time: Arrow = field( converter=arrow.get ) - tags: List[Dict] @define class ApiActivityPlanCreate(ApiActivityPlanBase): From f77e8019f7b72a8f190dceff4115f32da956e473 Mon Sep 17 00:00:00 2001 From: zgoldberg22 Date: Wed, 20 Dec 2023 16:41:30 +0600 Subject: [PATCH 04/14] remove unnecessary if, added default tag --- src/aerie_cli/aerie_client.py | 7 +++---- src/aerie_cli/schemas/client.py | 8 +++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/aerie_cli/aerie_client.py b/src/aerie_cli/aerie_client.py index 60105b9d..c6ebe0ca 100644 --- a/src/aerie_cli/aerie_client.py +++ b/src/aerie_cli/aerie_client.py @@ -231,10 +231,9 @@ def create_activity_plan( plan_id = plan_resp["id"] plan_revision = plan_resp["revision"] - #add plan tags if exists - if len(plan_to_create.tags) > 0: - for tag in plan_to_create.tags: - self.add_plan_tag(plan_id, tag["name"]) + #add plan tags if exists from plan_to_create + for tag in plan_to_create.tags: + self.add_plan_tag(plan_id, tag["tag"]["name"]) # This loop exists to make sure all anchor IDs are updated as necessary diff --git a/src/aerie_cli/schemas/client.py b/src/aerie_cli/schemas/client.py index d8e15760..2fd3cb48 100644 --- a/src/aerie_cli/schemas/client.py +++ b/src/aerie_cli/schemas/client.py @@ -147,10 +147,12 @@ class ActivityPlanCreate(EmptyActivityPlan): default=None ) tags: Optional[List[Dict]] = field( - default=[] + default=[], + converter=converters.optional( + lambda listOfDicts: [d for d in listOfDicts] + ) ) - @classmethod def from_plan_read(cls, plan_read: "ActivityPlanRead") -> "ActivityPlanCreate": return ActivityPlanCreate( @@ -176,7 +178,7 @@ class ActivityPlanRead(EmptyActivityPlan): model_id: int sim_id: int tags: Optional[List[Dict]] = field( - default = None, + default = [], converter=converters.optional( lambda listOfDicts: [d for d in listOfDicts] ) From 1d8cbbda467bf501aa4171ab9501cae765201990 Mon Sep 17 00:00:00 2001 From: zgoldberg22 Date: Sat, 23 Dec 2023 00:25:40 +0600 Subject: [PATCH 05/14] fixed graphql mutations --- src/aerie_cli/aerie_client.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/aerie_cli/aerie_client.py b/src/aerie_cli/aerie_client.py index c6ebe0ca..c9c8f26e 100644 --- a/src/aerie_cli/aerie_client.py +++ b/src/aerie_cli/aerie_client.py @@ -177,9 +177,9 @@ def get_tag_id_by_name(self, tag_name: str): name=tag_name ) - #if a tag with the specified name exists and returns the ID, else creates a new tag with this name - if len(resp["tags"]) > 0: - return resp["tags"][0]["id"] + #if a tag with the specified name exists then returns the ID, else creates a new tag with this name + if len(resp) > 0: + return resp[0]["id"] else: new_tag_resp = self.aerie_host.post_to_graphql( create_new_tag, @@ -198,15 +198,12 @@ def add_plan_tag(self, plan_id: int, tag_name: str): } } """ + #add tag to plan - tag_to_add = { - "plan_id": plan_id, - "tag_id": self.get_tag_id_by_name(tag_name) - } - resp = self.aerie_host.post_to_graphql( add_tag_to_plan, - objects={tag_to_add} + plan_id=plan_id, + tag_id=self.get_tag_id_by_name(tag_name) ) return resp[0] From 2d937917b43d21256788d5159a4c019a5d33b782 Mon Sep 17 00:00:00 2001 From: zgoldberg22 Date: Sat, 23 Dec 2023 00:38:26 +0600 Subject: [PATCH 06/14] fixed return error when adding tags --- src/aerie_cli/aerie_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aerie_cli/aerie_client.py b/src/aerie_cli/aerie_client.py index c9c8f26e..e1593dae 100644 --- a/src/aerie_cli/aerie_client.py +++ b/src/aerie_cli/aerie_client.py @@ -206,7 +206,7 @@ def add_plan_tag(self, plan_id: int, tag_name: str): tag_id=self.get_tag_id_by_name(tag_name) ) - return resp[0] + return resp['returning'][0] def create_activity_plan( self, model_id: int, plan_to_create: ActivityPlanCreate From a02d49a83cd0aa0151bb7f1103e3d622aa79131c Mon Sep 17 00:00:00 2001 From: zgoldberg22 Date: Wed, 10 Jan 2024 14:02:42 -0600 Subject: [PATCH 07/14] added tags attribute to ApiActivityPlanRead --- src/aerie_cli/aerie_client.py | 6 ++++++ src/aerie_cli/schemas/api.py | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/aerie_cli/aerie_client.py b/src/aerie_cli/aerie_client.py index e1593dae..f010555b 100644 --- a/src/aerie_cli/aerie_client.py +++ b/src/aerie_cli/aerie_client.py @@ -98,6 +98,12 @@ def list_all_activity_plans(self) -> List[ActivityPlanRead]: simulations{ id } + tags { + tag { + id + name + } + } } } """ diff --git a/src/aerie_cli/schemas/api.py b/src/aerie_cli/schemas/api.py index 1d7a872e..8c578141 100644 --- a/src/aerie_cli/schemas/api.py +++ b/src/aerie_cli/schemas/api.py @@ -138,6 +138,12 @@ class ApiActivityPlanRead(ApiActivityPlanBase): converter=converters.optional( lambda listOfDicts: [ApiActivityRead.from_dict(d) if isinstance(d, dict) else d for d in listOfDicts]) ) + tags: Optional[List[Dict]] = field( + default = [], + converter=converters.optional( + lambda listOfDicts: [d for d in listOfDicts] + ) + ) @define From ec98cb13b0f8d1dd8f11bc31c3bbc9163acc9d14 Mon Sep 17 00:00:00 2001 From: zgoldberg22 Date: Wed, 10 Jan 2024 14:50:09 -0600 Subject: [PATCH 08/14] fix unit tests --- .../expected_results/get_activity_plan_by_id.json | 1 + .../mock_responses/get_activity_plan_by_id.json | 2 +- .../mock_responses/list_all_activity_plans.json | 13 +++++++++++-- tests/unit_tests/test_aerie_client.py | 11 ++++++++++- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/tests/unit_tests/files/expected_results/get_activity_plan_by_id.json b/tests/unit_tests/files/expected_results/get_activity_plan_by_id.json index c32930a1..29dc3012 100644 --- a/tests/unit_tests/files/expected_results/get_activity_plan_by_id.json +++ b/tests/unit_tests/files/expected_results/get_activity_plan_by_id.json @@ -5,6 +5,7 @@ "id": 1, "model_id": 1, "sim_id": 1, + "tags": [], "activities": [ { "type": "ACT_One", diff --git a/tests/unit_tests/files/mock_responses/get_activity_plan_by_id.json b/tests/unit_tests/files/mock_responses/get_activity_plan_by_id.json index 4ec7aa9b..c24cb954 100644 --- a/tests/unit_tests/files/mock_responses/get_activity_plan_by_id.json +++ b/tests/unit_tests/files/mock_responses/get_activity_plan_by_id.json @@ -1,7 +1,7 @@ [ { "request": { - "query": "query get_plans ($plan_id: Int!) { plan_by_pk(id: $plan_id) { id model_id name start_time duration simulations{ id } activity_directives(order_by: { start_offset: asc }) { id name type start_offset arguments metadata anchor_id anchored_to_start } } }", + "query": "query get_plans ($plan_id: Int!) { plan_by_pk(id: $plan_id) { id model_id name start_time duration simulations{ id } tags { tag { id name } } activity_directives(order_by: { start_offset: asc }) { id name type start_offset arguments metadata anchor_id anchored_to_start } } }", "variables": { "plan_id": 1 } diff --git a/tests/unit_tests/files/mock_responses/list_all_activity_plans.json b/tests/unit_tests/files/mock_responses/list_all_activity_plans.json index 4dede461..485b3b7b 100644 --- a/tests/unit_tests/files/mock_responses/list_all_activity_plans.json +++ b/tests/unit_tests/files/mock_responses/list_all_activity_plans.json @@ -1,7 +1,7 @@ [ { "request": { - "query": "\n query list_all_plans {\n plan(order_by: { id: asc }) {\n id\n model_id\n name\n start_time\n duration\n simulations{\n id\n }\n }\n }", + "query": "\n query list_all_plans {\n plan(order_by: { id: asc }) {\n id\n model_id\n name\n start_time\n duration\n simulations{\n id\n }\n tags {\n tag {\n id\n name\n }\n }\n }\n }", "variables": {} }, "response": [ @@ -15,7 +15,8 @@ { "id": 1 } - ] + ], + "tags": [] }, { "id": 2, @@ -27,6 +28,14 @@ { "id": 2 } + ], + "tags": [ + { + "tag": { + "id": 1, + "name": "Test" + } + } ] } ] diff --git a/tests/unit_tests/test_aerie_client.py b/tests/unit_tests/test_aerie_client.py index 73051b37..62b1300f 100644 --- a/tests/unit_tests/test_aerie_client.py +++ b/tests/unit_tests/test_aerie_client.py @@ -88,7 +88,8 @@ def test_list_all_activity_plans(): { "id": 1 } - ] + ], + "tags": [] }, { "id": 2, @@ -100,6 +101,14 @@ def test_list_all_activity_plans(): { "id": 2 } + ], + "tags": [ + { + "tag": { + "id": 1, + "name": "Test" + } + } ] } ]""") From b0787f0fe41f488835de7a804e43a1c441669954 Mon Sep 17 00:00:00 2001 From: zgoldberg22 Date: Fri, 26 Jan 2024 16:13:24 -0500 Subject: [PATCH 09/14] made tags attribtue Optional in EmptyActivityPlan --- src/aerie_cli/schemas/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aerie_cli/schemas/client.py b/src/aerie_cli/schemas/client.py index 2fd3cb48..9b84bec8 100644 --- a/src/aerie_cli/schemas/client.py +++ b/src/aerie_cli/schemas/client.py @@ -113,7 +113,7 @@ class EmptyActivityPlan(ClientSerialize): ) end_time: Arrow = field( converter = arrow.get) - tags: List[Dict] + tags: Optional[List[Dict]] def duration(self) -> timedelta: return self.end_time - self.start_time From 6bb7e345167bec672da645c21613aa8fc06e256e Mon Sep 17 00:00:00 2001 From: Carter Mak Date: Sat, 27 Jan 2024 15:40:49 -0800 Subject: [PATCH 10/14] Update constriant violations query to Aerie 2.2.0 --- src/aerie_cli/aerie_client.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/aerie_cli/aerie_client.py b/src/aerie_cli/aerie_client.py index f010555b..9aedce0f 100644 --- a/src/aerie_cli/aerie_client.py +++ b/src/aerie_cli/aerie_client.py @@ -1713,12 +1713,12 @@ def get_constraint_violations(self, plan_id): get_violations_query = """ query ($plan_id: Int!) { constraintResponses: constraintViolations(planId: $plan_id) { + constraintId + constraintName + type success results { - constraintId - constraintName resourceIds - type gaps { end start From c5150100ada70ff5320153128d3d574e4db627ec Mon Sep 17 00:00:00 2001 From: Carter Mak Date: Wed, 10 Jan 2024 15:39:18 -0800 Subject: [PATCH 11/14] Add Aerie 2.2.0 to integration tests. Removes Aerie 2.1.0 from full compatibility. --- .env | 2 +- .github/workflows/test.yml | 8 ++++---- tests/integration_tests/conftest.py | 2 +- ...ation-2.1.0.jar => banananation-2.2.0.jar} | Bin 10383185 -> 10383194 bytes 4 files changed, 6 insertions(+), 6 deletions(-) rename tests/integration_tests/files/models/{banananation-2.1.0.jar => banananation-2.2.0.jar} (97%) diff --git a/.env b/.env index 4872a4a8..80d9ddf7 100644 --- a/.env +++ b/.env @@ -1,4 +1,4 @@ -DOCKER_TAG=v2.1.0 +DOCKER_TAG=v2.2.0 REPOSITORY_DOCKER_URL=ghcr.io/nasa-ammos AERIE_USERNAME=aerie diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 45f57d53..02f847dc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -24,7 +24,7 @@ jobs: environment: integration-test-workflow strategy: matrix: - python-version: [ "3.6.15", "3.7", "3.8", "3.9", "3.10", "3.11" ] + python-version: ["3.6.15", "3.7", "3.8", "3.9", "3.10", "3.11"] steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} @@ -46,8 +46,8 @@ jobs: environment: integration-test-workflow strategy: matrix: - python-version: [ "3.6.15", "3.11" ] - aerie-version: ["2.1.0"] + python-version: ["3.6.15", "3.11"] + aerie-version: ["2.2.0"] steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} @@ -86,4 +86,4 @@ jobs: docker ps -a - name: Prune volumes if: always() - run: docker volume prune --force \ No newline at end of file + run: docker volume prune --force diff --git a/tests/integration_tests/conftest.py b/tests/integration_tests/conftest.py index a5e20dfe..8defaf54 100644 --- a/tests/integration_tests/conftest.py +++ b/tests/integration_tests/conftest.py @@ -41,7 +41,7 @@ CONFIGURATIONS_PATH = os.path.join(FILES_PATH, "configuration") CONFIGURATION_PATH = os.path.join(CONFIGURATIONS_PATH, "localhost_config.json") MODELS_PATH = os.path.join(FILES_PATH, "models") -MODEL_VERSION = os.environ.get("AERIE_VERSION", "2.1.0") +MODEL_VERSION = os.environ.get("AERIE_VERSION", "2.2.0") MODEL_JAR = os.path.join(MODELS_PATH, f"banananation-{MODEL_VERSION}.jar") MODEL_NAME = "banananation" MODEL_VERSION = "0.0.1" diff --git a/tests/integration_tests/files/models/banananation-2.1.0.jar b/tests/integration_tests/files/models/banananation-2.2.0.jar similarity index 97% rename from tests/integration_tests/files/models/banananation-2.1.0.jar rename to tests/integration_tests/files/models/banananation-2.2.0.jar index 6c7618d0998706724a5f19012b4fb4e36f333ed0..84844aa69fc8241ebd856ed9eed4e8db3abaff25 100644 GIT binary patch delta 58778 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 delta 57988 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

E0Kbg= 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 From 025feaad428380edfb900e699f0b662cbc34c726 Mon Sep 17 00:00:00 2001 From: Carter Mak Date: Sat, 27 Jan 2024 14:58:59 -0800 Subject: [PATCH 12/14] Update query to create expansion rules --- src/aerie_cli/aerie_client.py | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/aerie_cli/aerie_client.py b/src/aerie_cli/aerie_client.py index 9aedce0f..79e172e7 100644 --- a/src/aerie_cli/aerie_client.py +++ b/src/aerie_cli/aerie_client.py @@ -853,6 +853,8 @@ def create_expansion_rule( activity_name: str, model_id: str, command_dictionary_id: str, + name: str = None, + description: str = None ) -> int: """Submit expansion logic to an Aerie instance @@ -861,34 +863,31 @@ def create_expansion_rule( activity_name (str): Name of the activity model_id (str): Aerie model ID command_dictionary_id (str): Aerie command dictionary ID + name (str, Optional): Name of the expansion rule + description (str, Optional): Description of the expansion rule Returns: int: Expansion Rule ID in Aerie """ create_expansion_logic_query = """ - mutation UploadExpansionLogic( - $activity_type_name: String! - $expansion_logic: String! - $command_dictionary_id: Int! - $mission_model_id: Int! - ) { - addCommandExpansionTypeScript( - activityTypeName: $activity_type_name - expansionLogic: $expansion_logic - authoringCommandDictionaryId: $command_dictionary_id - authoringMissionModelId: $mission_model_id - ) { + mutation CreateExpansionRule($rule: expansion_rule_insert_input!) { + createExpansionRule: insert_expansion_rule_one(object: $rule) { id } } """ + rule = { + "activity_type": activity_name, + "authoring_command_dict_id": command_dictionary_id, + "authoring_mission_model_id": model_id, + "expansion_logic": expansion_logic, + "name": name if (name is not None) else activity_name + arrow.utcnow().format("_YYYY-MM-DDTHH-mm-ss"), + "description": description if (description is not None) else "" + } data = self.aerie_host.post_to_graphql( create_expansion_logic_query, - activity_type_name=activity_name, - expansion_logic=expansion_logic, - mission_model_id=model_id, - command_dictionary_id=command_dictionary_id, + rule=rule ) return data["id"] From 353ffbfa04973d85afc11cb4a7e733d0136d0109 Mon Sep 17 00:00:00 2001 From: Carter Mak Date: Sat, 27 Jan 2024 15:21:32 -0800 Subject: [PATCH 13/14] Implement expansion deploy command --- src/aerie_cli/commands/expansion.py | 106 +++++++++++++++++- src/aerie_cli/schemas/client.py | 25 +++++ .../files/expansion/BakeBananaBread_exp.ts | 6 + .../files/expansion/BiteBanana_exp.ts | 6 + .../expansion/expansion_deploy_config.json | 28 +++++ tests/integration_tests/test_expansion.py | 29 +++++ 6 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 tests/integration_tests/files/expansion/BakeBananaBread_exp.ts create mode 100644 tests/integration_tests/files/expansion/BiteBanana_exp.ts create mode 100644 tests/integration_tests/files/expansion/expansion_deploy_config.json diff --git a/src/aerie_cli/commands/expansion.py b/src/aerie_cli/commands/expansion.py index 998ee619..8ad2303d 100644 --- a/src/aerie_cli/commands/expansion.py +++ b/src/aerie_cli/commands/expansion.py @@ -4,12 +4,14 @@ from pathlib import Path import fnmatch +import arrow + from rich.console import Console from rich.table import Table from aerie_cli.commands.command_context import CommandContext from aerie_cli.utils.prompts import select_from_list -from aerie_cli.schemas.client import ExpansionRun +from aerie_cli.schemas.client import ExpansionRun, ExpansionDeployConfiguration app = typer.Typer() sequences_app = typer.Typer() @@ -19,6 +21,108 @@ app.add_typer(runs_app, name='runs', help='Commands for expansion runs') app.add_typer(sets_app, name='sets', help='Commands for expansion sets') +# === Bulk Deploy Command === + +@app.command('deploy') +def bulk_deploy( + model_id: int = typer.Option( + ..., '--model-id', '-m', prompt='Mission Model ID', + help='Mission Model ID' + ), + command_dictionary_id: int = typer.Option( + ..., '--command-dict-id', '-d', prompt='Command Dictionary ID', + help='Command Dictionary ID' + ), + config_file: str = typer.Option( + ..., "--config-file", "-c", prompt="Configuration file", + help="Deploy configuration JSON file" + ), + rules_path: Path = typer.Option( + Path.cwd(), help="Path to folder containing expansion rule files" + ), + time_tag: bool = typer.Option(False, help="Append time tags to create unique expansion rule/set names") +): + """ + Bulk deploy command expansion rules and sets to an Aerie instance according to a JSON configuration file. + + The configuration file contains a list of rules and a list of sets: + + ``` + { + "rules": [...], + "sets": [...] + } + ``` + + Each rule must provide a unique rule name, the activity type name, and the name of the file with expansion logic: + + ``` + { + "name": "Expansion Rule Name", + "activity_type": "Activity Type Name", + "file_name": "my_file.ts" + } + ``` + + Each set must provide a unique set name and a list of rule names to add: + + ``` + { + "name": "Expansion Set Name", + "rules": ["Expansion Rule Name", ...] + } + ``` + """ + + client = CommandContext.get_client() + + with open(Path(config_file), "r") as fid: + configuration: ExpansionDeployConfiguration = ExpansionDeployConfiguration.from_dict(json.load(fid)) + + name_suffix = arrow.utcnow().format("_YYYY-MM-DDTHH-mm-ss") if time_tag else "" + + # Loop and upload all expansion rules + uploaded_rules = {} + for rule in configuration.rules: + try: + with open(rules_path.joinpath(rule.file_name), "r") as fid: + expansion_logic = fid.read() + + rule_id = client.create_expansion_rule( + expansion_logic=expansion_logic, + activity_name=rule.activity_type, + model_id=model_id, + command_dictionary_id=command_dictionary_id, + name=rule.name + name_suffix + ) + typer.echo(f"Created expansion rule {rule.name + name_suffix}: {rule_id}") + uploaded_rules[rule.name] = rule_id + except: + typer.echo(f"Failed to create expansion rule {rule.name}") + + for set in configuration.sets: + try: + rule_ids = [] + for rule_name in set.rules: + if rule_name in uploaded_rules.keys(): + rule_ids.append(uploaded_rules[rule_name]) + else: + typer.echo(f"No uploaded rule {rule_name} for set {set.name}") + + assert len(rule_ids) + + set_id = client.create_expansion_set( + command_dictionary_id=command_dictionary_id, + model_id=model_id, + expansion_ids=rule_ids, + name=set.name + name_suffix + ) + + typer.echo(f"Created expansion set {set.name + name_suffix}: {set_id}") + except: + typer.echo(f"Failed to create expansion set {set.name}") + + # === Commands for expansion runs === diff --git a/src/aerie_cli/schemas/client.py b/src/aerie_cli/schemas/client.py index 9b84bec8..c9497f1c 100644 --- a/src/aerie_cli/schemas/client.py +++ b/src/aerie_cli/schemas/client.py @@ -392,3 +392,28 @@ class ExpansionRule(ClientSerialize): class ResourceType(ClientSerialize): name: str schema: Dict + + +@define +class ExpansionDeployRule(ClientSerialize): + name: str + activity_type: str + file_name: str + + +@define +class ExpansionDeploySet(ClientSerialize): + name: str + rules: List[str] + + +@define +class ExpansionDeployConfiguration(ClientSerialize): + rules: List[ExpansionDeployRule] = field( + converter=converters.optional( + lambda x: [ExpansionDeployRule.from_dict(d) if isinstance(d, dict) else d for d in x]) + ) + sets: List[ExpansionDeploySet] = field( + converter=converters.optional( + lambda x: [ExpansionDeploySet.from_dict(d) if isinstance(d, dict) else d for d in x]) + ) diff --git a/tests/integration_tests/files/expansion/BakeBananaBread_exp.ts b/tests/integration_tests/files/expansion/BakeBananaBread_exp.ts new file mode 100644 index 00000000..5efc4564 --- /dev/null +++ b/tests/integration_tests/files/expansion/BakeBananaBread_exp.ts @@ -0,0 +1,6 @@ +export default function MyExpansion(props: { + activityInstance: ActivityType +}): ExpansionReturn { + const { activityInstance } = props + return [] +} \ No newline at end of file diff --git a/tests/integration_tests/files/expansion/BiteBanana_exp.ts b/tests/integration_tests/files/expansion/BiteBanana_exp.ts new file mode 100644 index 00000000..5efc4564 --- /dev/null +++ b/tests/integration_tests/files/expansion/BiteBanana_exp.ts @@ -0,0 +1,6 @@ +export default function MyExpansion(props: { + activityInstance: ActivityType +}): ExpansionReturn { + const { activityInstance } = props + return [] +} \ No newline at end of file diff --git a/tests/integration_tests/files/expansion/expansion_deploy_config.json b/tests/integration_tests/files/expansion/expansion_deploy_config.json new file mode 100644 index 00000000..78e4f6d0 --- /dev/null +++ b/tests/integration_tests/files/expansion/expansion_deploy_config.json @@ -0,0 +1,28 @@ +{ + "rules": [ + { + "name": "integration_test_BakeBananaBread", + "activity_type": "BakeBananaBread", + "file_name": "BakeBananaBread_exp.ts" + }, + { + "name": "integration_test_BiteBanana", + "activity_type": "BiteBanana", + "file_name": "BiteBanana_exp.ts" + }, + { + "name": "integration_test_bad", + "activity_type": "Fake", + "file_name": "this path no exist" + } + ], + "sets": [ + { + "name": "integration_test_set", + "rules": [ + "integration_test_BakeBananaBread", + "integration_test_BiteBanana" + ] + } + ] +} \ No newline at end of file diff --git a/tests/integration_tests/test_expansion.py b/tests/integration_tests/test_expansion.py index c004fdb8..0e882e37 100644 --- a/tests/integration_tests/test_expansion.py +++ b/tests/integration_tests/test_expansion.py @@ -37,6 +37,8 @@ # Expansion Variables expansion_set_id = -1 expansion_sequence_id = 1 +EXPANSION_FILES_PATH = os.path.join(FILES_PATH, "expansion") +EXPANSION_DEPLOY_CONFIG_PATH = os.path.join(EXPANSION_FILES_PATH, "expansion_deploy_config.json") @pytest.fixture(scope="module", autouse=True) def set_up_environment(request): @@ -127,6 +129,33 @@ def test_expansion_sequence_delete(): # Uses model, command dictionary, and activity types ####################### + +def test_expansion_deploy(): + result = runner.invoke( + app, + [ + "expansion", + "deploy", + "-m", + str(model_id), + "-d", + str(command_dictionary_id), + "-c", + EXPANSION_DEPLOY_CONFIG_PATH, + "--rules-path", + EXPANSION_FILES_PATH, + "--time-tag" + ], + catch_exceptions=False + ) + assert result.exit_code == 0, \ + f"{result.stdout}"\ + f"{result.stderr}" + assert "Created expansion rule integration_test_BakeBananaBread" in result.stdout + assert "Created expansion rule integration_test_BiteBanana" in result.stdout + assert "Failed to create expansion rule integration_test_bad" in result.stdout + assert "Created expansion set integration_test_set" in result.stdout + def test_expansion_set_create(): client.create_expansion_rule( expansion_logic=""" From 38e7426f1cfcc434bcf9eca6980c5be5bb6fbd13 Mon Sep 17 00:00:00 2001 From: Carter Mak Date: Wed, 31 Jan 2024 20:30:51 -0800 Subject: [PATCH 14/14] Version bump --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ba578bd4..5973b120 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "aerie-cli" -version = "0.0.0-dev0" +version = "2.3.0" description = "A CLI application and Python API for interacting with Aerie." authors = [] license = "MIT"