This is an automated email from the ASF dual-hosted git repository.

lahirujayathilake pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-custos.git

commit b93b7dc3f2c38196f0b56a479c351f05b1cf3792
Author: lahiruj <[email protected]>
AuthorDate: Tue May 5 02:16:43 2026 -0400

    support extracting the correct user role and included dev_email in the AMIE 
test packets
---
 allocations/access-amie/README.md                  |  8 +++
 allocations/access-amie/handler/handler.go         | 15 ++++
 .../access-amie/handler/request_account_create.go  |  6 +-
 allocations/devtools/amie/README.md                | 14 ++++
 allocations/devtools/amie/mock-amie-server.py      | 81 ++++++++++++++++++++++
 5 files changed, 121 insertions(+), 3 deletions(-)

diff --git a/allocations/access-amie/README.md 
b/allocations/access-amie/README.md
index 890d6589a..b754b93e0 100644
--- a/allocations/access-amie/README.md
+++ b/allocations/access-amie/README.md
@@ -28,6 +28,14 @@ export AMIE_API_KEY="your-api-key"
 
 The default `config.yaml` works for local development with the Docker Compose 
MariaDB defaults.
 
+For local dev without a real ACCESS endpoint, point the service at the local 
mock AMIE server in [`devtools/amie/`](../devtools/amie/README.md)
+
+```bash
+export AMIE_BASE_URL="http://localhost:8180";
+export AMIE_SITE_CODE="TESTSITE"
+export AMIE_API_KEY="dev"
+```
+
 ### 3. Build
 
 ```bash
diff --git a/allocations/access-amie/handler/handler.go 
b/allocations/access-amie/handler/handler.go
index 0bc946fae..70e7adac0 100644
--- a/allocations/access-amie/handler/handler.go
+++ b/allocations/access-amie/handler/handler.go
@@ -59,6 +59,21 @@ func getBody(packetJSON map[string]any) (map[string]any, 
error) {
        return body, nil
 }
 
+var roleNormalizer = strings.NewReplacer(" ", "", "-", "", "_", "")
+
+func normalizeRole(raw string) string {
+       switch strings.ToUpper(roleNormalizer.Replace(raw)) {
+       case "PI":
+               return "PI"
+       case "COPI":
+               return "CO_PI"
+       case "ALLOCATIONMANAGER":
+               return "ALLOCATION_MANAGER"
+       default:
+               return "USER"
+       }
+}
+
 func getResourceList(body map[string]any) []string {
        v, ok := body["ResourceList"]
        if !ok {
diff --git a/allocations/access-amie/handler/request_account_create.go 
b/allocations/access-amie/handler/request_account_create.go
index dc16fcab2..487b5b333 100644
--- a/allocations/access-amie/handler/request_account_create.go
+++ b/allocations/access-amie/handler/request_account_create.go
@@ -124,9 +124,9 @@ func (h *RequestAccountCreateHandler) Handle(ctx 
context.Context, tx *sql.Tx, pa
                return fmt.Errorf("request_account_create: creating/finding 
project: %w", err)
        }
 
-       // Create USER membership.
-       if _, err := h.membershipSvc.CreateMembership(ctx, tx, projectID, 
account.ID, "USER"); err != nil {
-               return fmt.Errorf("request_account_create: creating USER 
membership: %w", err)
+       role := normalizeRole(getString(body, "UserRole"))
+       if _, err := h.membershipSvc.CreateMembership(ctx, tx, projectID, 
account.ID, role); err != nil {
+               return fmt.Errorf("request_account_create: creating %s 
membership: %w", role, err)
        }
        if err := h.auditSvc.Log(ctx, tx, packet.ID, eventID, 
model.AuditCreateMembership, "membership", "", ""); err != nil {
                return fmt.Errorf("request_account_create: audit 
CREATE_MEMBERSHIP: %w", err)
diff --git a/allocations/devtools/amie/README.md 
b/allocations/devtools/amie/README.md
index 9c61c89d1..98ec62ca8 100644
--- a/allocations/devtools/amie/README.md
+++ b/allocations/devtools/amie/README.md
@@ -25,10 +25,24 @@ curl -X POST 
'http://localhost:8180/test/TESTSITE/scenarios?type=failures_only'
 
 # heavy batch
 curl -X POST 'http://localhost:8180/test/TESTSITE/scenarios?type=heavy'
+
+# dev email across multiple projects with different roles (requires DEV_EMAIL)
+curl -X POST 'http://localhost:8180/test/TESTSITE/scenarios?type=dev_email'
 ```
 
 Point `access-amie` at it with `AMIE_BASE_URL=http://localhost:8180`.
 
+### `dev_email` scenario
+
+Run the `dev_email` scenario to generate AMIE packets placing DEV_EMAIL in 
multiple projects with different roles.
+
+```bash
[email protected] python3 mock-amie-server.py
+curl -X POST 'http://localhost:8180/test/TESTSITE/scenarios?type=dev_email'
+```
+
+Today the access-amie handlers persist PI and USER memberships only; Co-PI and 
Allocation Manager positions require handler enhancement to read a role field 
from the AMIE packet.
+
 ## Load test (k6)
 
 Install k6, then run it. If you're hitting the local server, start that one 
first:
diff --git a/allocations/devtools/amie/mock-amie-server.py 
b/allocations/devtools/amie/mock-amie-server.py
index 0bd32f7c7..38f509d7e 100644
--- a/allocations/devtools/amie/mock-amie-server.py
+++ b/allocations/devtools/amie/mock-amie-server.py
@@ -27,6 +27,7 @@
 # Then point the service at: access.amie.base-url=http://localhost:8180
 
 import json
+import os
 import random
 import time
 import uuid
@@ -42,6 +43,8 @@ stats = {"created": 0, "fetched": 0, "replied": 0}
 
 SCENARIOS_DIR = Path(__file__).parent / "scenarios"
 
+DEV_EMAIL = os.getenv("DEV_EMAIL", "").strip()
+
 
 def next_id():
     global packet_counter
@@ -208,6 +211,76 @@ def gen_empty_body():
     return make_packet("request_project_create", {})
 
 
+DEV_USER_GID = "100001"
+
+DEV_MEMBER_PROJECTS = [
+    ("DEV-PROJ-002", "Climate Modeling Group", "Alice", "Smith", 
"[email protected]", "100002", "CoPI"),
+    ("DEV-PROJ-003", "Particle Physics Sim",   "Bob",   "Johnson", 
"[email protected]", "100003", "Allocation Manager"),
+    ("DEV-PROJ-004", "Genomics Pipeline",      "Carol", "Williams", 
"[email protected]", "100004", "User"),
+]
+
+
+def gen_dev_email_scenario():
+    if not DEV_EMAIL:
+        app.logger.warning("DEV_EMAIL is not set; dev_email scenario emits no 
packets")
+        return []
+
+    packets = []
+
+    packets.append(make_packet("request_project_create", {
+        "GrantNumber": "DEV-PROJ-001",
+        "PfosNumber": "PFOS-DEV-PROJ-001",
+        "ProjectTitle": "Dev's Own Project",
+        "PiGlobalID": DEV_USER_GID,
+        "PiFirstName": "Dev",
+        "PiLastName": "User",
+        "PiEmail": DEV_EMAIL,
+        "PiOrganization": "Dev Lab",
+        "PiOrgCode": "DEV",
+        "NsfStatusCode": "AC",
+        "PiDnList": ["/C=US/O=Dev Lab/CN=Dev User"],
+        "ServiceUnitsAllocated": "100000",
+        "StartDate": "2026-01-01",
+        "EndDate": "2026-12-31",
+        "ResourceList": "mock-cluster.example.edu",
+    }))
+
+    for grant, title, pi_first, pi_last, pi_email, pi_gid, dev_role in 
DEV_MEMBER_PROJECTS:
+        packets.append(make_packet("request_project_create", {
+            "GrantNumber": grant,
+            "PfosNumber": f"PFOS-{grant}",
+            "ProjectTitle": title,
+            "PiGlobalID": pi_gid,
+            "PiFirstName": pi_first,
+            "PiLastName": pi_last,
+            "PiEmail": pi_email,
+            "PiOrganization": "Bogus Lab",
+            "PiOrgCode": "BOGUS",
+            "NsfStatusCode": "AC",
+            "PiDnList": [f"/C=US/O=Bogus Lab/CN={pi_first} {pi_last}"],
+            "ServiceUnitsAllocated": "50000",
+            "StartDate": "2026-01-01",
+            "EndDate": "2026-12-31",
+            "ResourceList": "mock-cluster.example.edu",
+        }))
+        packets.append(make_packet("request_account_create", {
+            "ProjectID": f"PRJ-{grant}",
+            "GrantNumber": grant,
+            "UserGlobalID": DEV_USER_GID,
+            "UserFirstName": "Dev",
+            "UserLastName": "User",
+            "UserEmail": DEV_EMAIL,
+            "UserOrganization": "Dev Lab",
+            "UserOrgCode": "DEV",
+            "NsfStatusCode": "AC",
+            "UserDnList": ["/C=US/O=Dev Lab/CN=Dev User"],
+            "UserRole": dev_role,
+            "ResourceList": "mock-cluster.example.edu",
+        }))
+
+    return packets
+
+
 # Scenario mix
 
 SUCCESS_GENERATORS = [
@@ -303,6 +376,8 @@ def create_scenario(site):
         packets = generate_batch(success_count=8, failure_count=0)
     elif scenario_type == "heavy":
         packets = generate_batch(success_count=15, failure_count=10)
+    elif scenario_type == "dev_email":
+        packets = gen_dev_email_scenario()
     else:
         packets = generate_batch(success_count=3, failure_count=2)
 
@@ -332,5 +407,11 @@ if __name__ == "__main__":
     print("  POST /test/{site}/scenarios?type=failures_only  — 8 failures")
     print("  POST /test/{site}/scenarios?type=success_only   — 8 successes")
     print("  POST /test/{site}/scenarios?type=heavy          — 15 success + 10 
failure")
+    print("  POST /test/{site}/scenarios?type=dev_email      — scripted set 
placing DEV_EMAIL across projects")
+    print("")
+    if DEV_EMAIL:
+        print(f"DEV_EMAIL injection enabled: {DEV_EMAIL}")
+    else:
+        print("DEV_EMAIL is unset — set it (e.g. [email protected]) 
to use the dev_email scenario")
     print("")
     app.run(host="0.0.0.0", port=8180, debug=False)

Reply via email to