Skip to content

Commit

Permalink
Merge pull request #633 from GrahamDumpleton/inject-user-data-variables
Browse files Browse the repository at this point in the history
Add data variables for training portal user information.
  • Loading branch information
GrahamDumpleton authored Feb 8, 2025
2 parents e97a0bf + 4662023 commit 8ff32cc
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 25 deletions.
9 changes: 8 additions & 1 deletion project-docs/custom-resources/workshop-definition.md
Original file line number Diff line number Diff line change
Expand Up @@ -1552,7 +1552,14 @@ spec:
password: $(WORKSHOP_PASSWORD)
```

Note that this only applies to ``request.objects``. Parameters cannot be used in this way with ``session.objects`` or ``environment.objects``.
In addition to the parameters being able to be used in `request.objects`, a few extra data variables are also available. These include user information from the training portal. Whether these are useful depend on what type of authentication is used with the training portal. For example, if anonymous user authentication is used, the used identifier would be a UUID and other fields empty.

* `username` - The name of the user as registered by the training portal.
* `first_name` - The first name of the registered user.
* `last_name` - The last name of the registered user.
* `email` - The email address of the registered user.

Note that this only applies to ``request.objects``. The request parameters and user data variables cannot be used in this way with ``session.objects`` or ``environment.objects``.

(defining-additional-ingress-points)=
Defining additional ingress points
Expand Down
9 changes: 9 additions & 0 deletions project-docs/release-notes/version-3.2.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ New Features
used used by all workshops, unless overridden for a specific workshop, when
creating a portal using the `educates create-portal` command.

* User details from the training portal are now saved to a `Secret` stored in
the workshop namespace for each session, with a name of the form
`$(session_name)-user`. Attributes are `username`, `first_name`, `last_name`
and `email`. The secret can be used as a volume or as source of environment
variables for the workshop session container, with caveat that since the
secret is only available at the point a workshop session is allocated, it
should not be used with reserved sessions. These are also available to use as
data variables in `request.objects`.

Bugs Fixed
----------

Expand Down
90 changes: 66 additions & 24 deletions session-manager/handlers/workshopallocation.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ def workshop_allocation_create(

session_variables_secret_name = f"{session_name}-session"
request_variables_secret_name = f"{session_name}-request"
user_variables_secret_name = f"{session_name}-user"

report_analytics_event(
"Resource/Create",
Expand Down Expand Up @@ -345,8 +346,10 @@ def workshop_allocation_create(
)

if (
not (workshop_namespace, request_variables_secret_name)
in request_variables_secret_index
(not (workshop_namespace, request_variables_secret_name)
in request_variables_secret_index)
or (not (workshop_namespace, user_variables_secret_name)
in request_variables_secret_index)
):
if runtime.total_seconds() >= 45:
# If the parameters secret is not found in the cache after 45
Expand All @@ -358,38 +361,68 @@ def workshop_allocation_create(
# The only indication that the request has failed is the status of
# the workshop allocation request.

patch["status"] = {
OPERATOR_STATUS_KEY: {
"phase": "Failed",
"message": f"Request variables secret {request_variables_secret_name} is not available.",
if not (workshop_namespace, request_variables_secret_name) in request_variables_secret_index:
patch["status"] = {
OPERATOR_STATUS_KEY: {
"phase": "Failed",
"message": f"Request variables secret {request_variables_secret_name} is not available.",
}
}
}

report_analytics_event(
"Resource/PermanentError",
{
"kind": "WorkshopAllocation",
"name": name,
"uid": uid,
"retry": retry,
"message": f"Request variables secret {request_variables_secret_name} is not available for workshop allocation request {name}.",
},
)
report_analytics_event(
"Resource/PermanentError",
{
"kind": "WorkshopAllocation",
"name": name,
"uid": uid,
"retry": retry,
"message": f"Request variables secret {request_variables_secret_name} is not available for workshop allocation request {name}.",
},
)

raise kopf.PermanentError(
f"Request variables secret {request_variables_secret_name} is not available."
)

else:
patch["status"] = {
OPERATOR_STATUS_KEY: {
"phase": "Failed",
"message": f"Request variables secret {user_variables_secret_name} is not available.",
}
}

raise kopf.PermanentError(
f"Request variables secret {request_variables_secret_name} is not available."
)
report_analytics_event(
"Resource/PermanentError",
{
"kind": "WorkshopAllocation",
"name": name,
"uid": uid,
"retry": retry,
"message": f"Request variables secret {user_variables_secret_name} is not available for workshop allocation request {name}.",
},
)

raise kopf.PermanentError(
f"Request variables secret {user_variables_secret_name} is not available."
)

# If the request variables secret is not found in the cache, we will
# retry the request after a short delay. Make sure to set the status to
# "Pending" to indicate that the request is still being processed.

patch["status"] = {OPERATOR_STATUS_KEY: {"phase": "Pending"}}

raise kopf.TemporaryError(
f"No record of parameters secret {request_variables_secret_name} required for workshop allocation request {name}.",
delay=5,
)
if not (workshop_namespace, request_variables_secret_name) in request_variables_secret_index:
raise kopf.TemporaryError(
f"No record of parameters secret {request_variables_secret_name} required for workshop allocation request {name}.",
delay=5,
)
else:
raise kopf.TemporaryError(
f"No record of parameters secret {user_variables_secret_name} required for workshop allocation request {name}.",
delay=5,
)

# Get the session variables and request variables from the cache.

Expand All @@ -401,6 +434,10 @@ def workshop_allocation_create(
(workshop_namespace, request_variables_secret_name)
]

cached_user_variables, *_ = request_variables_secret_index[
(workshop_namespace, user_variables_secret_name)
]

# Combine the session variables and request variables into a single
# dictionary. Since the session variables and request variables are stored
# in the secrets as base64 encoded strings, we need to decode them before
Expand All @@ -413,6 +450,11 @@ def workshop_allocation_create(
"UTF-8"
)

for key, value in cached_user_variables.items():
all_data_variables[key] = base64.b64decode(value.encode("UTF-8")).decode(
"UTF-8"
)

for key, value in cached_session_variables.items():
all_data_variables[key] = base64.b64decode(value.encode("UTF-8")).decode(
"UTF-8"
Expand Down

0 comments on commit 8ff32cc

Please sign in to comment.