This is an automated email from the ASF dual-hosted git repository.
lahirujayathilake pushed a commit to branch allocation-management
in repository https://gitbox.apache.org/repos/asf/airavata-custos.git
The following commit(s) were added to refs/heads/allocation-management by this
push:
new 5d3028607 support extracting the correct user role and included
dev_email in the AMIE test packets
5d3028607 is described below
commit 5d3028607a6441c3f7875076ffc8652d2ea4e2d7
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)