Skip to content
Open
Show file tree
Hide file tree
Changes from 50 commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
34127c1
support custom TopCP images
MattShirley Sep 23, 2025
ba71014
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 23, 2025
86d536d
resolve flake8 issues
MattShirley Sep 23, 2025
b518d40
Revert "resolve flake8 issues"
MattShirley Sep 23, 2025
c185637
Merge branch '1162-support-custom-topcp-images' of https://github.com…
MattShirley Sep 23, 2025
8286d95
fix broken test
MattShirley Sep 23, 2025
2e706b7
add back allowed_repos logic
MattShirley Sep 23, 2025
fe976f3
remove accidental values changes
MattShirley Sep 23, 2025
e129256
moving towards MVP (app server is failing due to bad mount)
MattShirley Oct 8, 2025
0386476
update directory structure
MattShirley Oct 21, 2025
d0776b0
tighten flake8
MattShirley Oct 21, 2025
1cade42
Merge branch 'develop' of https://github.com/ssl-hep/ServiceX into 11…
MattShirley Oct 21, 2025
f1b7b43
remove comments and unused env vars
MattShirley Oct 21, 2025
8a4fbb7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 21, 2025
0fd050d
rewrite custom_docker_image logic
MattShirley Oct 23, 2025
2d3bf8f
Merge branch 'develop' of https://github.com/ssl-hep/ServiceX into 11…
MattShirley Oct 24, 2025
8fc3645
Merge branch '1162-support-custom-topcp-images' of https://github.com…
MattShirley Oct 28, 2025
d7bb6cd
add back runTop_el
MattShirley Oct 28, 2025
e5024d0
remove old test files
MattShirley Oct 28, 2025
0125f41
fix local volume mount
MattShirley Oct 29, 2025
b49b9ee
change reload to mountLocal
MattShirley Oct 29, 2025
f799896
Merge branch 'develop' of https://github.com/ssl-hep/ServiceX into 11…
MattShirley Oct 31, 2025
6686336
update helm charts and other config stuff
MattShirley Oct 31, 2025
0f4f3f4
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 31, 2025
8aeff9e
resolve flake8
MattShirley Oct 31, 2025
c9aaf95
Merge branch '1162-support-custom-topcp-images' of https://github.com…
MattShirley Oct 31, 2025
981504b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 31, 2025
28523ed
move boot.sh
MattShirley Oct 31, 2025
c60e495
Merge branch '1162-support-custom-topcp-images' of https://github.com…
MattShirley Oct 31, 2025
ce26f8f
update boot.sh command
MattShirley Oct 31, 2025
6c2059f
update test coverage
MattShirley Oct 31, 2025
3dfd2ad
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 31, 2025
5aa97d6
resolve flake8
MattShirley Oct 31, 2025
8aa6bf2
Merge branch '1162-support-custom-topcp-images' of https://github.com…
MattShirley Oct 31, 2025
8cce096
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 31, 2025
01c453a
resolve flake8 again
MattShirley Oct 31, 2025
91343d2
remove unneeded defaultBaseImage from values.yaml
MattShirley Nov 4, 2025
a172125
properly source app config values
MattShirley Nov 10, 2025
78ddeac
resolve flake8
MattShirley Nov 10, 2025
6bbd73b
update tests to use app.config
MattShirley Nov 10, 2025
1f20afe
resolve flake8
MattShirley Nov 10, 2025
f8b8dde
remove local dev related changes
MattShirley Nov 11, 2025
d03f8ba
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 11, 2025
1098084
remove Procfile changes from this PR
MattShirley Nov 11, 2025
f9fe691
Merge branch '1162-support-custom-topcp-images' of https://github.com…
MattShirley Nov 11, 2025
cdc29c2
add topcp codegen values to reference.md
MattShirley Nov 11, 2025
e2e076c
correct topcp pullpolicy
MattShirley Nov 11, 2025
1b140d0
move custom image logic to topcp codegen
MattShirley Nov 13, 2025
eea313b
move boot.sh back
MattShirley Nov 13, 2025
e348931
remove comment
MattShirley Nov 13, 2025
2ba1a2a
move docker image validation tests to codegen
MattShirley Nov 13, 2025
50c542c
flake8/black
MattShirley Nov 13, 2025
5fc9d75
flake8
MattShirley Nov 13, 2025
c45ad9f
revert submit.py
MattShirley Nov 13, 2025
7141637
remove TOPCP_CUSTOM_IMAGES from app template
MattShirley Nov 13, 2025
1d9fab9
remove custom_image from generate_code_for_selection
MattShirley Nov 13, 2025
4cca0aa
flake8
MattShirley Nov 13, 2025
c688ece
add new codegen topcp custom docker image test
MattShirley Nov 13, 2025
c956c90
update test
MattShirley Nov 13, 2025
8a1d8a5
add json parsing check to topcp codegen startup
MattShirley Nov 13, 2025
2a5f730
check to make sure allowed_images_json is truthy
MattShirley Nov 13, 2025
53448d8
Merge branch 'develop' into 1162-support-custom-topcp-images
MattShirley Nov 14, 2025
32293b5
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 14, 2025
19601a7
cleanup merge conflict
MattShirley Nov 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file modified code_generator_TopCPToolkit/boot.sh
100644 → 100755
Empty file.
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import json
import os

options = {
Expand Down Expand Up @@ -36,12 +35,15 @@
"ifTrue": ["--no-filter"],
"ifFalse": None,
},
"docker_image": {
"properType": str,
"properTypeString": "string",
"optional": True,
},
}


def generate_files_from_query(query, query_file_path):
jquery = json.loads(query)

def generate_files_from_query(jquery: dict, query_file_path):
runTopCommand = [
"runTop_el.py",
"-i",
Expand All @@ -52,16 +54,19 @@ def generate_files_from_query(query, query_file_path):
"customConfig",
]

# ensure all keys are specified
# ensure all required keys are specified
for key in options:
if key not in jquery:
# Skip optional parameters
if options[key].get("optional", False):
continue
raise ValueError(
key + " must be specified. May be type None or ",
options[key]["properTypeString"],
)

for key in jquery:
# ensure only aviable options are allowed
# ensure only available options are allowed
if key not in options:
raise KeyError(
key + " is not implemented. Available keys: " + str(options.keys())
Expand All @@ -78,7 +83,7 @@ def generate_files_from_query(query, query_file_path):
)

# check for reco.yaml, parton.yaml and particle.yaml files
if isinstance(jquery[key], str):
if isinstance(jquery[key], str) and "fileName" in options[key]:
with open(
os.path.join(query_file_path, options[key]["fileName"]), "w"
) as file:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,34 @@
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os
import json
import shutil

from . import query_translate
from servicex_codegen.code_generator import (
CodeGenerator,
GeneratedFileResult,
GenerateCodeException,
)

def validate_custom_docker_image(image_name: str) -> bool:
allowed_images_json = os.environ.get("TOPCP_ALLOWED_IMAGES")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be moved to the codegen's __init__ so that if there is a formatting error in the ALLOWED_IMAGES it will fail at startup instead of the first time someone submits?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function call can't go in __init__.py because there's nothing to compare it to. However, I added a check in create_app to validate the JSON parsing of of TOPCP_ALLOWED_IMAGES. And I removed type guarding from validate_custom_docker_image.


if not allowed_images_json:
raise GenerateCodeException("Custom Docker images are not allowed.")

try:
allowed_prefixes = json.loads(allowed_images_json)
if not isinstance(allowed_prefixes, list):
raise GenerateCodeException("TopCP allowed images are improperly configured.")
for prefix in allowed_prefixes:
if image_name.startswith(prefix):
return True

raise GenerateCodeException(f"Custom Docker image '{image_name}' not allowed.")

except json.JSONDecodeError:
raise GenerateCodeException("TopCP allowed images are improperly configured.")

class TopCPTranslator(CodeGenerator):
# Generate the code. Ignoring caching for now
Expand Down Expand Up @@ -62,11 +82,22 @@ def generate_code(self, query, cache_path: str):
capabilities_path = os.environ.get(
"CAPABILITIES_PATH", "/home/servicex/transformer_capabilities.json"
)

jquery = json.loads(query)
query_translate.generate_files_from_query(jquery, query_file_path)

shutil.copyfile(
capabilities_path,
os.path.join(query_file_path, "transformer_capabilities.json"),
)

query_translate.generate_files_from_query(query, query_file_path)
results = GeneratedFileResult(_hash, query_file_path)

if "docker_image" in jquery:
docker_image = jquery["docker_image"]

validate_custom_docker_image(docker_image)

results.image = docker_image

return GeneratedFileResult(_hash, query_file_path)
return results
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,23 @@ def transform_single_file(file_path: str, output_path: Path, output_format: str)
# create input.txt file for event loop and insert file_path as only line
with open("input.txt", "w") as f:
f.write(file_path)
# move reco.yaml, parton.yaml and particle.yaml if they exit to CONFIG_LOC loacation

# move reco.yaml, parton.yaml and particle.yaml if they exist to CONFIG_LOC location
config_loc = os.environ.get("CONFIG_LOC", os.getcwd())
if os.path.exists("/generated/reco.yaml"):
shutil.copyfile(
"/generated/reco.yaml",
os.path.join(os.environ.get("CONFIG_LOC"), "reco.yaml"),
os.path.join(config_loc, "reco.yaml"),
)
if os.path.exists("/generated/parton.yaml"):
shutil.copyfile(
"/generated/parton.yaml",
os.path.join(os.environ.get("CONFIG_LOC"), "parton.yaml"),
os.path.join(config_loc, "parton.yaml"),
)
if os.path.exists("/generated/particle.yaml"):
shutil.copyfile(
"/generated/particle.yaml",
os.path.join(os.environ.get("CONFIG_LOC"), "particle.yaml"),
os.path.join(config_loc, "particle.yaml"),
)

generated_transformer.runTop_el()
Expand Down
17 changes: 12 additions & 5 deletions docs/deployment/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ parameters for the [rabbitMQ](https://github.com/bitnami/charts/tree/master/bitn
| `app.replicas` | Number of App pods to start. Experimental! | 1 |
| `app.auth` | Enable authentication or allow unfettered access (Python boolean string) | `false` |
| `app.oauthMetadataURL` | OpenID Connect provider well known configuration endpoint URL | - |
| `app.oauthClientID` | OpenID Connect application Client ID | - |
| `app.oauthClientSecret` | OpenID Connect application Client Secret | - |
| `app.oauthClientID` | OpenID Connect application Client ID | - |
| `app.oauthClientSecret` | OpenID Connect application Client Secret | - |
| `app.adminEmail` | Email address for initial admin user | <admin@example.com> |
| `app.tokenExpires` | Seconds until the ServiceX API tokens (JWT refresh tokens) expire | False (never) |
| `app.authExpires` | Seconds until the JWT access tokens expire | 21600 (six hours) |
Expand Down Expand Up @@ -75,6 +75,13 @@ parameters for the [rabbitMQ](https://github.com/bitnami/charts/tree/master/bitn
| `codegen.atlasr21.enabled` | Deploy the ATLAS FuncADL Release 21 code generator? - also all of the code gen settings above are available | true |
| `codegen.atlasr22.enabled` | Deploy the ATLAS FuncADL Release 22 code generator? - also all of the code gen settings above are available | true |
| `codegen.python.enabled` | Deploy the python uproot code generator? - also all of the code gen settings, above are available | true |
| `codegen.topcp.enabled` | Deploy the TopCP code generator? | true |
| `codegen.topcp.image` | TopCP ode generator image | `sslhep/servicex_code_gen_topcp` |
| `codegen.topcp.pullPolicy` | TopCP code generator image pull policy | Always |
| `codegen.topcp.tag` | TopCP code generator image tag | develop |
| `codegen.topcp.defaultScienceContainerImage` | The default image used by a TopCP transformer container | sslhep/servicex_science_image_topcp |
| `codegen.topcp.defaultScienceContainerTag` | The default tag used by a TopCP transformer container | 2.17.0-25.2.45 |
| `codegen.topcp.allowedImages` | A list of strings, of which one must be a valid prefix of a submitted custom TopCP docker image | - "sslhep/servicex_science_image_topcp:" |
| `x509Secrets.image` | X509 Secret Service image name | `sslhep/x509-secrets` |
| `x509Secrets.tag` | X509 Secret Service image tag | `latest` |
| `x509Secrets.pullPolicy` | X509 Secret Service image pull policy | `Always` |
Expand All @@ -94,9 +101,9 @@ parameters for the [rabbitMQ](https://github.com/bitnami/charts/tree/master/bitn
| `minio.apiIngress.enabled` | Should minio chart deploy an ingress to the service? | false |
| `minio.apiIngress.hostname` | Hostname associate with ingress controller | nil |
| `transformer.cachePrefix` | Prefix string to stick in front of file paths. Useful for XCache. If `transformer.cacheVPSSite` is also set, this will be ignored | nil |
| `transformer.cacheVPSSite` | Specify a Virtual Placement Service site whose XCaches we should use. Will update automatically if list changes. If set, takes priority over `transformer.cachePrefix` | nil |
| `transformer.cacheVPSCheckInterval` | How frequency should the Virtual Placement Service be consulted for the list of XCaches (in seconds) | 1800 |
| `transformer.cacheVPSLivenessURL` | URL from which Virtual Placement Service site info can be obtained | https://vps.cern.ch/liveness |
| `transformer.cacheVPSSite` | Specify a Virtual Placement Service site whose XCaches we should use. Will update automatically if list changes. If set, takes priority over `transformer.cachePrefix` | nil |
| `transformer.cacheVPSCheckInterval` | How frequency should the Virtual Placement Service be consulted for the list of XCaches (in seconds) | 1800 |
| `transformer.cacheVPSLivenessURL` | URL from which Virtual Placement Service site info can be obtained | https://vps.cern.ch/liveness |
| `transformer.autoscaler.enabled` | Enable/disable horizontal pod autoscaler for transformers | True |
| `transformer.autoscaler.cpuScaleThreshold` | CPU percentage threshold for pod scaling | 30 |
| `transformer.autoscaler.minReplicas` | Minimum number of transformer pods per request | 1 |
Expand Down
5 changes: 5 additions & 0 deletions helm/servicex/templates/app/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ data:
CODE_GEN_IMAGES = { {{ join "," $code_gen_images }} }
{{- end }}

{{- if .Values.codeGen.topcp.enabled }}
# TopCP custom image configuration
TOPCP_ALLOWED_IMAGES = {{ .Values.codeGen.topcp.allowedImages | toJson | quote }}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need this in the App config?

{{- end }}

{{- $didFinders := list }}
{{- if .Values.didFinder.CERNOpenData.enabled }}
{{- $didFinders = append $didFinders "cernopendata" }}
Expand Down
4 changes: 4 additions & 0 deletions helm/servicex/templates/codegen/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ spec:
env:
- name: INSTANCE_NAME
value: {{ $.Release.Name }}
{{- if eq $codeGenName "topcp" }}
- name: TOPCP_ALLOWED_IMAGES
value: {{ $.Values.codeGen.topcp.allowedImages | toJson | quote }}
{{- end }}
- name: TRANSFORMER_SCIENCE_IMAGE
value: {{ .defaultScienceContainerImage }}:{{ .defaultScienceContainerTag }}
{{- $compressionAlgorithm := .compressionAlgorithm | default "ZSTD" }}
Expand Down
4 changes: 2 additions & 2 deletions helm/servicex/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ codeGen:
tag: develop
defaultScienceContainerImage: sslhep/servicex_science_image_topcp
defaultScienceContainerTag: 2.17.0-25.2.45
allowedImages:
- "sslhep/servicex_science_image_topcp:"

didFinder:
CERNOpenData:
Expand Down Expand Up @@ -175,7 +177,6 @@ postgresql:
image:
repository: bitnamilegacy/os-shell
tag: 12-debian-12-r51

global:
postgresql:
auth:
Expand All @@ -200,7 +201,6 @@ rabbitmq:
image:
repository: bitnamilegacy/os-shell
tag: 12-debian-12-r51

extraConfiguration: |-
consumer_timeout = 3600000

Expand Down
8 changes: 7 additions & 1 deletion servicex_app/servicex_app/code_gen_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from typing import Optional

import requests
from requests_toolbelt.multipart import decoder

Expand All @@ -43,7 +45,11 @@ def post_request(self, post_url, post_obj):
return result

def generate_code_for_selection(
self, request_record: TransformRequest, namespace: str, user_codegen_name: str
self,
request_record: TransformRequest,
namespace: str,
user_codegen_name: str,
custom_image: Optional[str] = None,
Copy link
Contributor

@BenGalewsky BenGalewsky Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why iscustom_image still here?

) -> tuple[str, str, str, str]:
"""
Generates the C++ code for a request's selection string.
Expand Down
Loading
Loading