Skip to content

feat(frontend): manage curated computing-unit images from the admin page - #8518

Open
tanishqgandhi1908 wants to merge 3 commits into
apache:mainfrom
tanishqgandhi1908:pr/curated-images-admin-page
Open

feat(frontend): manage curated computing-unit images from the admin page#8518
tanishqgandhi1908 wants to merge 3 commits into
apache:mainfrom
tanishqgandhi1908:pr/curated-images-admin-page

Conversation

@tanishqgandhi1908

Copy link
Copy Markdown
Contributor

What changes were proposed in this PR?

Admin → CU Images, the page for managing the images #8475 made registrable.

Images are listed newest first, each with the digest a unit will actually run, and four actions: Add, Log, Refresh, Remove. A row shows PENDING, VALIDATING, READY or FAILED. The list polls while a check is running and goes quiet once nothing is.

The images list

Log is the point of the page. It is where a refused image explains itself — a tag that does not exist, an image that is not a computing-unit image — and says what to do instead.

The log of a refused image

A deployment with curated images switched off is told so plainly. The API answers 503 on every endpoint there, so the page can do nothing either way; saying that beats an error an administrator cannot tell from a broken deployment.

A deployment with the feature switched off

Also routes /api/cu-image to the computing-unit manager in the dev proxy. Without it a local frontend reaches the webserver instead and every call 404s. Production already routes through the gateway, added in #8475.

Any related issues, documentation, discussions?

Closes #8470
Part of #8466

Stacked on #8475, whose API this consumes, so GitHub shows that commit here too until it merges. This PR's own change is one commit over it, frontend only.

How was this PR tested?

Nine tests for the page, plus the whole thing run against a real backend.

Case What it pins
digest shown the pinned digest reaches the page, not just the tag
feature off 503 becomes an explanation, not an error
no poll when off an idle switched-off page makes no requests
polls, then stops requests while a check runs, none once it settles
newest first ordered by time, not by name
blank fields no request is made
Refresh while checking disabled
status colours READY, FAILED and in-progress are distinguishable
yarn --cwd frontend format:ci     clean
yarn --cwd frontend run build:ci  0 errors
yarn --cwd frontend run test:ci   29 passed (9 new, plus dashboard.component.spec)

The polling tests were mutation-checked: removing the filter fails exactly those two.

Against a real stack (bin/local-dev.sh up, with the computing-unit manager talking to minikube):

register alpine:3.20                    -> FAILED in 8s, digest sha256:d9e853e8...
  log: "Its start command is: [/bin/sh]"
register texera-cu-sklearn:1.0          -> READY in 15s, digest sha256:7e0a8816...
  matches skopeo inspect independently
refresh                                 -> attempt 1 -> 2, back to READY
remove                                  -> 204
duplicate reference / name / blank name -> 400, each naming the reason
a Docker Hub page address               -> normalised to owner/name:latest
REGULAR user: GET 200, POST/DELETE/log  -> 403

Driven through the page itself: typed into the Add form, clicked Add, the row appeared VALIDATING and reached its outcome with no further interaction. Once settled, 0 requests over 20 idle seconds. The screenshots above are that stack, not a mock.

Was this PR authored or co-authored using generative AI tooling?

Generated-by: Claude Code (Claude Opus 5)

An administrator registers an image reference from a public registry,
and a computing unit can then be started from it. Off by default until
the UI to manage these ships.

Texera reads the image's manifest and config blob -- a few kilobytes,
never the layers -- to check its start command runs
computing-unit-master, which means it was built FROM the Texera
computing-unit image, and to resolve the digest behind the reference. A
misspelled, private or unsuitable image is refused in seconds, in front
of the administrator, rather than when a user's unit will not start.

The row records owner/name@sha256:..., and that is what units run, so a
tag its owner moves later cannot change what already ran. Nothing is
copied and no registry is added: units pull the reference the same way
the deployment's own image is already pulled.

Uniqueness is enforced by the database, not only checked in the
service. Two administrators registering the same link at the same
moment both pass a read-then-write check and produce two rows for one
image.

A curated image was supplied by an administrator and reviewed by
nobody, so a unit started from one runs as a non-root user with no
privilege escalation and no capabilities. Curated images only -- the
deployment's own image is its operator's choice, and one that has
replaced it with an image needing root would break on upgrade.

The first unit on each node waits for the image to download, about 80
seconds for a 3 GB one, while later units there start at once.
Pre-pulling ready images onto nodes is a follow-up.
Admin -> CU Images lists the registered images newest first, with the
digest a unit will actually run, and offers Add, Log, Refresh and
Remove. A row shows PENDING, VALIDATING, READY or FAILED; the list
polls while a check is running and goes quiet once nothing is. Log is
where a refused image explains itself -- a tag that does not exist, an
image that is not a computing-unit image -- and what to do instead.

A deployment with curated images switched off is told so plainly. The
API answers 503 on every endpoint there, so the page can do nothing
either way; saying it beats an error an administrator cannot tell from
a broken deployment.

Also routes /api/cu-image to the computing-unit manager in the dev
proxy. Without it a local frontend reaches the webserver instead and
every call 404s; production already routes through the gateway.
@github-actions github-actions Bot added ddl-change Changes to the TexeraDB DDL frontend Changes related to the frontend GUI infra common platform Non-amber Scala service paths labels Sep 11, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Automated Reviewer Suggestions

Based on the git blame history of the changed files, we recommend the following reviewers:

  • Contributors with relevant context: @zyratlo, @aicam, @aglinxinyuan
    You can notify them by mentioning @zyratlo, @aicam, @aglinxinyuan in a comment.

@codecov-commenter

codecov-commenter commented Sep 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 41.40351% with 334 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.63%. Comparing base (ec3a9dd) to head (3e21950).
⚠️ Report is 10 commits behind head on main.

Files with missing lines Patch % Lines
...texera/service/resource/CuratedImageResource.scala 22.85% 182 Missing and 7 partials ⚠️
...he/texera/service/util/ImageValidationClient.scala 41.26% 73 Missing and 1 partial ⚠️
...mponent/admin/cu-image/admin-cu-image.component.ts 56.16% 28 Missing and 4 partials ⚠️
...ache/texera/common/config/CuratedImageConfig.scala 0.00% 12 Missing ⚠️
...onent/admin/cu-image/admin-cu-image.component.html 84.61% 12 Missing ⚠️
.../apache/texera/service/util/KubernetesClient.scala 33.33% 5 Missing and 1 partial ⚠️
...rvice/resource/ComputingUnitManagingResource.scala 16.66% 5 Missing ⚠️
...shboard/service/admin/cu-image/cu-image.service.ts 63.63% 4 Missing ⚠️

❌ Your patch status has failed because the patch coverage (41.40%) is below the target coverage (60.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #8518      +/-   ##
============================================
+ Coverage     93.94%   94.63%   +0.68%     
+ Complexity     4827      461    -4366     
============================================
  Files          1209      592     -617     
  Lines         49705    34013   -15692     
  Branches       6074     4210    -1864     
============================================
- Hits          46695    32187   -14508     
+ Misses         1522     1252     -270     
+ Partials       1488      574     -914     
Flag Coverage Δ *Carryforward flag
access-control-service 80.18% <ø> (ø)
agent-service 99.32% <ø> (ø) Carriedforward from 3ba2f2b
amber 89.80% <20.00%> (-0.12%) ⬇️ Carriedforward from 3ba2f2b
computing-unit-managing-service 55.04% <29.19%> (-20.02%) ⬇️
config-service 87.12% <ø> (ø)
file-service 83.65% <ø> (ø) Carriedforward from 3ba2f2b
frontend 95.98% <71.42%> (-0.80%) ⬇️ Carriedforward from 3ba2f2b
notebook-migration-service 83.73% <ø> (ø)
pyamber 98.47% <ø> (ø) Carriedforward from 3ba2f2b
workflow-compiling-service 74.09% <ø> (-3.10%) ⬇️ Carriedforward from 3ba2f2b

*This pull request uses carry forward flags. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

⚠️ Benchmark changes need a look

🟢 5 better · 🔴 3 worse · ⚪ 7 noise (<±5%) · 0 without baseline

Compared against main 069cd20 benchmarked on this same runner, so the delta is largely free of cross-runner hardware noise. The "7d avg" column still reflects the gh-pages dashboard. Treat <±5% as noise unless repeated.

Dashboard · Run

config throughput MB/s latency max Δ latest / 7d
🔴 bs=10 sw=10 sl=64 462 0.282 20,967/30,233/30,233 us 🟢 -19.4% / 🔴 +93.2%
🟢 bs=100 sw=10 sl=64 975 0.595 99,408/142,470/142,470 us 🟢 -8.7% / 🔴 +36.2%
🔴 bs=1000 sw=10 sl=64 1,105 0.674 894,446/1,069,733/1,069,733 us 🔴 +15.9% / 🔴 +7.1%
Baseline details

Latest main 069cd20 from same runner

config metric PR latest main 7d avg Δ latest Δ 7d
bs=10 sw=10 sl=64 throughput 462 tuples/sec 474 tuples/sec 794.98 tuples/sec -2.5% -41.9%
bs=10 sw=10 sl=64 MB/s 0.282 MB/s 0.289 MB/s 0.485 MB/s -2.4% -41.9%
bs=10 sw=10 sl=64 p50 20,967 us 19,873 us 12,443 us +5.5% +68.5%
bs=10 sw=10 sl=64 p95 30,233 us 37,531 us 15,648 us -19.4% +93.2%
bs=10 sw=10 sl=64 p99 30,233 us 37,531 us 19,794 us -19.4% +52.7%
bs=100 sw=10 sl=64 throughput 975 tuples/sec 904 tuples/sec 1,034 tuples/sec +7.9% -5.7%
bs=100 sw=10 sl=64 MB/s 0.595 MB/s 0.552 MB/s 0.631 MB/s +7.8% -5.7%
bs=100 sw=10 sl=64 p50 99,408 us 108,860 us 97,860 us -8.7% +1.6%
bs=100 sw=10 sl=64 p95 142,470 us 138,864 us 104,570 us +2.6% +36.2%
bs=100 sw=10 sl=64 p99 142,470 us 138,864 us 117,811 us +2.6% +20.9%
bs=1000 sw=10 sl=64 throughput 1,105 tuples/sec 1,130 tuples/sec 1,066 tuples/sec -2.2% +3.7%
bs=1000 sw=10 sl=64 MB/s 0.674 MB/s 0.69 MB/s 0.651 MB/s -2.3% +3.6%
bs=1000 sw=10 sl=64 p50 894,446 us 881,725 us 958,266 us +1.4% -6.7%
bs=1000 sw=10 sl=64 p95 1,069,733 us 923,181 us 998,734 us +15.9% +7.1%
bs=1000 sw=10 sl=64 p99 1,069,733 us 923,181 us 1,032,953 us +15.9% +3.6%
Raw CSV
config_idx,batch_size,schema_width,string_len,num_batches,total_ms,total_tuples,total_bytes,tuples_per_sec,mb_per_sec,lat_p50_us,lat_p95_us,lat_p99_us
0,10,10,64,20,433.18,200,128000,462,0.282,20966.85,30233.42,30233.42
1,100,10,64,20,2051.52,2000,1280000,975,0.595,99407.57,142469.86,142469.86
2,1000,10,64,20,18100.21,20000,12800000,1105,0.674,894445.72,1069732.80,1069732.80

…submit

Two from review.

An error from the request inside switchMap reached the subscriber,
which ends the subscription for good -- so one hiccup while a check was
running left the row VALIDATING forever, with Refresh disabled in that
state and only a reload to recover. Caught inside the projection now,
as the deployment-version poller already does.

Enter in either field calls add() directly, where the Add button's
disabled state does not apply, so two quick presses sent the same image
twice and the second tripped the unique name constraint right after a
successful add.

Both regressions are pinned by tests that fail without the fix.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

common ddl-change Changes to the TexeraDB DDL frontend Changes related to the frontend GUI infra platform Non-amber Scala service paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Manage curated images from the admin page

2 participants