Skip to content

Add optional Cloud Object Storage region to runtime configurations - #3449

Open
NopeCharon wants to merge 2 commits into
elyra-ai:mainfrom
NopeCharon:configurable-cos-region
Open

NopeCharon wants to merge 2 commits into
elyra-ai:mainfrom
NopeCharon:configurable-cos-region

Conversation

@NopeCharon

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

Elyra never passes a region to the minio client. Without one, the client sends a GetBucketLocation request to find the bucket's region before it reads or writes objects. Some S3-compatible providers require a region and fail these requests, so Elyra can't connect to them (#3173).

This PR adds an optional Cloud Object Storage Region (cos_region) property to the Kubeflow Pipelines and Apache Airflow runtime configurations and uses it everywhere Elyra creates a minio client:

  • Runtime configuration schemas (elyra/metadata/schemas/kfp.json, airflow.json): a new optional cos_region string in the Cloud Object Storage category. The metadata editor and elyra-metadata create/update ... --cos_region pick it up from the schema. The pattern only accepts names that the minio client accepts as a region (letters, digits, - and _, up to 63 characters, not starting or ending with - or _). An invalid value is therefore reported when the configuration is saved, not later when a pipeline runs.
  • CosClient (elyra/util/cos.py): passes the configured region to the minio client. This client checks connectivity, creates the bucket and uploads node dependencies during submit/export. If the bucket doesn't exist yet, it is created in that region.
  • Generic nodes: the KFP processor (_compose_container_command_args) and the Airflow processor (BootscriptBuilder) add --cos-region '<region>' to the bootstrapper command. Both bootstrappers accept the new optional --cos-region argument and pass it to their minio client.

If no region is configured, behavior doesn't change: no argument is added, and the client still looks up the region itself. Existing runtime configurations need no migration. The new keyword arguments of _compose_container_command_args and BootscriptBuilder are optional and come last, so existing callers keep working.

The user guide (runtime-conf.md) documents the new setting.

How was this pull request tested?

New tests (each fails without the change):

  • test_schema.py: the kfp and airflow schemas accept regions such as us-east-1, garage and Region_1, and reject "", us east 1, leading/trailing - or _, and names longer than 63 characters. The property is not required.
  • test_cos.py: CosClient passes the configured region to the minio client, or None if no region (or an empty one) is configured.
  • test_kfp_processor.py: _compose_container_command_args adds --cos-region only when a region is given. The compiled one-generic-node pipeline test also runs with a runtime configuration that sets cos_region. It checks that the compiled container args include --cos-region 'us-east-1', and that they don't include it when no region is configured.
  • test_processor_airflow.py: every generic operation in the generated Airflow DAG gets --cos-region only if the runtime configuration sets one.
  • test_airflow_operator.py: BootscriptBuilder with and without cos_region.
  • kfp/test_bootstrapper.py and airflow/test_bootstrapper.py: --cos-region is parsed, and is optional. The bootstrapper's minio client is created with the given region, or None.

Locally (Python 3.12): test_schema.py, test_cos.py, test_airflow_operator.py, airflow/test_bootstrapper.py, test_processor_airflow.py, test_kfp_processor.py, test_validation.py and test_metadata_app.py pass. The new and changed tests in kfp/test_bootstrapper.py also pass. I couldn't run the rest of that module locally, because its fixture needs the S3 test container on port 9000. flake8 and black --check are clean.

End to end, against a SeaweedFS S3 server (the image the bootstrapper tests use):

  • elyra-metadata create runtimes --schema_name kfp ... --cos_region us-east-1 saves the region. --cos_region "bad region" fails schema validation.
  • CosClient with cos_region set creates the bucket and uploads and downloads an object, using the configured region. Without cos_region, the client still looks the region up from the service, as before.
  • The KFP bootstrapper's NotebookFileOp, given --cos-region us-east-1, downloads the object from the bucket.

Fixes #3173

Developer's Certificate of Origin 1.1

   By making a contribution to this project, I certify that:

   (a) The contribution was created in whole or in part by me and I
       have the right to submit it under the Apache License 2.0; or

   (b) The contribution is based upon previous work that, to the best
       of my knowledge, is covered under an appropriate open source
       license and I have the right under that license to submit that
       work with modifications, whether created in whole or in part
       by me, under the same open source license (unless I am
       permitted to submit under a different license), as indicated
       in the file; or

   (c) The contribution was provided directly to me by some other
       person who certified (a), (b) or (c) and I have not modified
       it.

   (d) I understand and agree that this project and the contribution
       are public and that a record of the contribution (including all
       personal information I submit with it, including my sign-off) is
       maintained indefinitely and may be redistributed consistent with
       this project or the open source license(s) involved.

Elyra never passed a region to the minio client, so the client asks
the object storage service for the bucket's region with a
GetBucketLocation request before it reads or writes objects. Some
S3-compatible providers require a region and fail these requests, so
Elyra could not connect to them at all.

Add an optional 'cos_region' property to the Kubeflow Pipelines and
Apache Airflow runtime configuration schemas. When it is set:

- CosClient, which verifies connectivity, creates the bucket and
  uploads pipeline dependencies, passes the region to the minio client
  (a missing bucket is created in that region).
- The KFP and Airflow processors add '--cos-region' to the bootstrapper
  command line of generic nodes, and both bootstrappers pass the value
  to their minio client.

When it is not set, nothing changes: no argument is added and the
client still looks up the region itself. The schema only accepts
names that the minio client accepts as a region.

Fixes elyra-ai#3173

Signed-off-by: NopeCharon <115794254+NopeCharon@users.noreply.github.com>
@codecov

codecov Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.07%. Comparing base (3b1af5f) to head (3bf82a1).
⚠️ Report is 5 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #3449      +/-   ##
==========================================
+ Coverage   84.81%   85.07%   +0.26%     
==========================================
  Files         159      159              
  Lines       19296    19392      +96     
  Branches      503      504       +1     
==========================================
+ Hits        16365    16497     +132     
+ Misses       2891     2856      -35     
+ Partials       40       39       -1     
Flag Coverage Δ
integration-editors 48.08% <ø> (-0.07%) ⬇️
integration-misc 25.64% <ø> (-0.02%) ⬇️
integration-pipeline 47.58% <ø> (-0.04%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
elyra/airflow/bootstrapper.py 35.22% <100.00%> (+7.67%) ⬆️
elyra/airflow/operator.py 97.95% <100.00%> (+0.13%) ⬆️
elyra/kfp/bootstrapper.py 78.65% <100.00%> (+0.05%) ⬆️
elyra/pipeline/airflow/airflow_processor.py 84.98% <100.00%> (+0.04%) ⬆️
elyra/pipeline/kfp/kfp_processor.py 66.73% <100.00%> (+0.19%) ⬆️
elyra/tests/airflow/test_airflow_operator.py 100.00% <100.00%> (ø)
elyra/tests/airflow/test_bootstrapper.py 100.00% <100.00%> (ø)
elyra/tests/kfp/test_bootstrapper.py 87.23% <100.00%> (+0.36%) ⬆️
elyra/tests/metadata/test_schema.py 100.00% <100.00%> (ø)
...a/tests/pipeline/airflow/test_processor_airflow.py 97.97% <100.00%> (+0.08%) ⬆️
... and 4 more

... and 5 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@lresende

lresende commented Nov 1, 2026

Copy link
Copy Markdown
Member

The cos_region pattern in kfp.json:148 and airflow.json:149 lets a trailing newline through. Elyra validates the schema with Python's re module (through jsonschema), where $ also matches right before a final \n, so "us-east-1\n" passes server-side validation even though the PR description says invalid values are caught when the configuration is saved. The metadata editor's JavaScript regex rejects it, but the CLI, REST and import paths would save it, and the newline would then end up in the quoted --cos-region argument of the generated KFP component and Airflow DAG. Could you replace the trailing $ with (?![\s\S]), which works the same way in both Python and JavaScript? Neither \Z nor \z does, since JavaScript supports neither. In test_schema.py, please add "us-east-1\n" to the rejected values: it passes today and will fail until the pattern is fixed. As a smaller point, the sibling properties keep their regex simple and put length limits in maxLength. Writing it as ^a-zA-Z0-9?(?![\s\S]) plus "maxLength": 63 would match that style and give users a clearer error when the name is too long.

Comment thread elyra/metadata/schemas/airflow.json Outdated
"title": "Cloud Object Storage Region",
"description": "The Cloud Object Storage region. If not specified, the region is determined by querying the Cloud Object Storage service.",
"type": "string",
"pattern": "^[a-zA-Z0-9]([a-zA-Z0-9_-]{0,61}[a-zA-Z0-9])?$",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
"pattern": "^[a-zA-Z0-9]([a-zA-Z0-9_-]{0,61}[a-zA-Z0-9])?$",
"pattern": "^[a-zA-Z0-9]([a-zA-Z0-9_-]{0,61}[a-zA-Z0-9])?(?![\\s\\S])",

@NopeCharon NopeCharon Nov 2, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 3bf82a1. The pattern now ends with (?![\s\S]) and the 63 character limit moved to maxLength, as you suggested in the main comment.

Comment thread elyra/metadata/schemas/kfp.json Outdated
"title": "Cloud Object Storage Region",
"description": "The Cloud Object Storage region. If not specified, the region is determined by querying the Cloud Object Storage service.",
"type": "string",
"pattern": "^[a-zA-Z0-9]([a-zA-Z0-9_-]{0,61}[a-zA-Z0-9])?$",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
"pattern": "^[a-zA-Z0-9]([a-zA-Z0-9_-]{0,61}[a-zA-Z0-9])?$",
"pattern": "^[a-zA-Z0-9]([a-zA-Z0-9_-]{0,61}[a-zA-Z0-9])?(?![\\s\\S])",

@NopeCharon NopeCharon Nov 2, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 3bf82a1. The pattern now ends with (?![\s\S]) and the 63 character limit moved to maxLength, as you suggested in the main comment.

Python's re lets $ match before a final newline, so a region such as
"us-east-1\n" passed server-side schema validation. End the cos_region
pattern with (?![\s\S]), which behaves the same in Python and
JavaScript, and move the length limit into maxLength like the
neighbouring properties.

Signed-off-by: NopeCharon <115794254+NopeCharon@users.noreply.github.com>
@NopeCharon

NopeCharon commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor Author

Fixed in 3bf82a1: both schemas now use ^[a-zA-Z0-9]([a-zA-Z0-9_-]*[a-zA-Z0-9])?(?![\s\S]) with "maxLength": 63, and test_schema.py rejects "us-east-1\n".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Introduce Option to make S3 Region configurable

2 participants