-
Notifications
You must be signed in to change notification settings - Fork 702
CONSOLE-5293: Update Dockerfile.downloads for 4.22 and add RHEL 8/9 oc binaries #16455
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,8 +5,11 @@ import ( | |
| "archive/zip" | ||
| "fmt" | ||
| "io" | ||
| "net/http" | ||
| "os" | ||
| "path/filepath" | ||
| "strings" | ||
| "sync" | ||
| "text/template" | ||
|
|
||
| "gopkg.in/yaml.v3" | ||
|
|
@@ -55,6 +58,8 @@ type DownloadsServerConfig struct { | |
| Spec []ArtifactSpec | ||
| TempDir string | ||
| TemplateHTML *template.Template | ||
| // archivesReady is closed once all background archive creation goroutines complete. | ||
| archivesReady chan struct{} | ||
| } | ||
|
|
||
| const indexFileName = "index.html" | ||
|
|
@@ -210,6 +215,18 @@ func addFileToZip(zw *zip.Writer, filename string) error { | |
| return nil | ||
| } | ||
|
|
||
| // displayName returns a human-readable label like "amd64 linux" or "amd64 linux - RHEL 8". | ||
| func displayName(arch, os, basename string) string { | ||
| name := fmt.Sprintf("%s %s", arch, os) | ||
| base := strings.TrimSuffix(basename, ".exe") | ||
| if strings.HasSuffix(base, ".rhel8") { | ||
| name += " - RHEL 8" | ||
| } else if strings.HasSuffix(base, ".rhel9") { | ||
| name += " - RHEL 9" | ||
| } | ||
| return name | ||
| } | ||
|
|
||
| func configureArchivePath(pathToTargetFile string) string { | ||
| if filepath.Ext(pathToTargetFile) == ".exe" { | ||
| // Remove the .exe extension from the path | ||
|
|
@@ -323,29 +340,66 @@ func (downloadsConfig *DownloadsServerConfig) generateDirFileContents() ([]ListI | |
| return nil, err | ||
| } | ||
|
|
||
| err = createArchive(artifactPath, ".tar") | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| err = createArchive(artifactPath, ".zip") | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| pathToArchive := configureArchivePath(artifactPath) | ||
| // append new entry in the list of links to artifacts | ||
| relPath := filepath.Join(spec.Arch, spec.OperatingSystem, basename) | ||
| relArchivePath := configureArchivePath(relPath) | ||
| content = append(content, ListItemLink{ | ||
| Type: Binary, | ||
| URL: artifactPath, | ||
| Name: fmt.Sprintf("%s %s", spec.Arch, spec.OperatingSystem), | ||
| TarURL: fmt.Sprintf("%s.tar", pathToArchive), | ||
| ZipURL: fmt.Sprintf("%s.zip", pathToArchive), | ||
| URL: relPath, | ||
| Name: displayName(spec.Arch, spec.OperatingSystem, basename), | ||
| TarURL: fmt.Sprintf("%s.tar", relArchivePath), | ||
| ZipURL: fmt.Sprintf("%s.zip", relArchivePath), | ||
| }) | ||
| } | ||
|
|
||
| return content, nil | ||
| } | ||
|
|
||
| // CreateArchivesInBackground spawns goroutines to create tar and zip archives | ||
| // for every artifact concurrently. It closes archivesReady when all archives | ||
| // have been written so that Handler() can unblock waiting requests. | ||
| func (c *DownloadsServerConfig) CreateArchivesInBackground() { | ||
| c.archivesReady = make(chan struct{}) | ||
| var wg sync.WaitGroup | ||
|
|
||
| for _, spec := range c.Spec { | ||
| basename := filepath.Base(spec.Path) | ||
| artifactPath := filepath.Join(c.TempDir, spec.Arch, spec.OperatingSystem, basename) | ||
|
|
||
| wg.Add(2) | ||
| go func(p string) { | ||
| defer wg.Done() | ||
| if err := createArchive(p, ".tar"); err != nil { | ||
| klog.Errorf("Failed to create tar archive for %s: %v", p, err) | ||
| } | ||
| }(artifactPath) | ||
| go func(p string) { | ||
| defer wg.Done() | ||
| if err := createArchive(p, ".zip"); err != nil { | ||
| klog.Errorf("Failed to create zip archive for %s: %v", p, err) | ||
| } | ||
| }(artifactPath) | ||
| } | ||
|
|
||
| go func() { | ||
| wg.Wait() | ||
| close(c.archivesReady) | ||
| klog.Info("All archives created successfully") | ||
| }() | ||
|
Comment on lines
+383
to
+387
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Success message logged unconditionally, even when archive creation fails. If any Consider tracking failure state and adjusting the final log accordingly. 🛠️ Proposed fix func (c *DownloadsServerConfig) CreateArchivesInBackground() {
c.archivesReady = make(chan struct{})
var wg sync.WaitGroup
+ var errCount int32
+ var errMu sync.Mutex
for _, spec := range c.Spec {
basename := filepath.Base(spec.Path)
artifactPath := filepath.Join(c.TempDir, spec.Arch, spec.OperatingSystem, basename)
wg.Add(2)
go func(p string) {
defer wg.Done()
if err := createArchive(p, ".tar"); err != nil {
klog.Errorf("Failed to create tar archive for %s: %v", p, err)
+ errMu.Lock()
+ errCount++
+ errMu.Unlock()
}
}(artifactPath)
go func(p string) {
defer wg.Done()
if err := createArchive(p, ".zip"); err != nil {
klog.Errorf("Failed to create zip archive for %s: %v", p, err)
+ errMu.Lock()
+ errCount++
+ errMu.Unlock()
}
}(artifactPath)
}
go func() {
wg.Wait()
close(c.archivesReady)
- klog.Info("All archives created successfully")
+ if errCount > 0 {
+ klog.Warningf("Archive creation completed with %d failures", errCount)
+ } else {
+ klog.Info("All archives created successfully")
+ }
}()
}🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| // Handler returns an http.Handler that serves files from TempDir. Requests for | ||
| // .tar or .zip archives block until background archive creation is complete. | ||
| func (c *DownloadsServerConfig) Handler() http.Handler { | ||
| fs := http.FileServer(http.Dir(c.TempDir)) | ||
| return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
| ext := filepath.Ext(r.URL.Path) | ||
| if ext == ".tar" || ext == ".zip" { | ||
| <-c.archivesReady | ||
| } | ||
| fs.ServeHTTP(w, r) | ||
| }) | ||
| } | ||
|
|
||
| // setupArtifactsDirectory creates the root HTML file and directories, files and archives for artifacts | ||
| func (artifactsConfig *DownloadsServerConfig) setupArtifactsDirectory() error { | ||
| // symlink file in the temporary directory that points to the openshift license | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: openshift/console
Length of output: 639
🏁 Script executed:
Repository: openshift/console
Length of output: 439
🏁 Script executed:
Repository: openshift/console
Length of output: 2300
🏁 Script executed:
Repository: openshift/console-operator
Length of output: 767
🏁 Script executed:
Repository: openshift/console
Length of output: 997
🌐 Web query:
registry.access.redhat.com/ubi9/ubi-minimal latest stable versions tags💡 Result:
As of May 15, 2026, the latest stable version of the Red Hat Universal Base Image 9 Minimal (ubi9-minimal) is 9.7 [1][2]. The Red Hat Container Registry uses a tagging system that includes both major/minor version tags and specific build-based tags [1]. You can access the image using the following primary tags: - latest: Always points to the most recent stable release of the image [1]. - 9.7: Points to the current stable minor release [1]. - 9.7-: Points to a specific, immutable build of the 9.7 release (e.g., 9.7-1778562320) [1]. Additionally, Red Hat provides corresponding source images for these tags, which can be accessed by appending -source to the tag (e.g., 9.7-source) [1][2]. To view the most up-to-date list of available tags, you can check the Red Hat Ecosystem Catalog [2] or the official Red Hat repository on Docker Hub [1][3]. For programmatic access or to mirror images, it is recommended to use the skopeo tool to list tags directly from the registry [2][4].
Citations:
Replace mutable
:latesttag on Line 17 with a stable version tag.Line 17 uses
registry.access.redhat.com/ubi9/ubi-minimal:latest, which is mutable and inconsistent with the versioned approach elsewhere in the Dockerfile. Replace with a stable version tag like9.7to ensure reproducible builds and align with the versioned tags used on lines 1 and 3.Suggested change
🤖 Prompt for AI Agents
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually a good point. Do we need to use a stable version for the UBI image to prevent unexpected build failures if the image under the
latesttag is updated?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
@TheRealJon, yes — the concern is legitimate and worth addressing before merge. Here's the full breakdown:Why
:latestis risky here::latestcould eventually advance to a new minor (e.g., UBI 9.8) or, in a future UBI 10 era, even a major version — neither of which is intentional here.What other OpenShift projects do:
In the openshift/assisted-service project, the final stage uses UBI9-minimal with an explicit SHA256 digest for reproducibility, which aligns with the project's objective of transitioning to UBI-minimal base images. For example:
FROM registry.access.redhat.com/ubi9/ubi-minimal:latest@sha256:<digest>.Options, ordered by preference:
ubi9/ubi-minimal:9.7@sha256:...ubi9/ubi-minimal:9.7:latest(current)ubi9/ubi-minimal:latestRecommended fix:
Or for the strongest guarantee (aligning with how other OpenShift repos handle this):
FROM registry.access.redhat.com/ubi9/ubi-minimal:9.7@sha256:<current-digest>You can get the current digest via:
Note: If this Dockerfile is built by ART as part of the OCP release payload, ART typically substitutes base images automatically. However, since this image pulls from
registry.access.redhat.com(a public registry) rather thanregistry.ci.openshift.org, it's safest to pin it explicitly here rather than rely on ART substitution.🏁 Script executed:
Repository: openshift/console
Length of output: 2409
🏁 Script executed:
Repository: openshift/console
Length of output: 45
@TheRealJon— the script output confirms the concern:Dockerfile.downloadsis the only production Dockerfile in the repo using an unpinned:latesttag. Every other production image (Dockerfile,Dockerfile.dev) consistently uses versioned tags fromregistry.ci.openshift.org, e.g.ocp/4.22:base-rhel9.So yes, this is worth fixing before merge. The minimum fix is pinning to a stable minor version:
For the strongest reproducibility guarantee, you can also pin the digest. To get the current digest, run locally:
That said, since the
COPYinstructions in this Dockerfile don't install any packages from the base image (it's purely a runtime shell), the blast radius of a UBI 9.x minor update is very low in practice. But aligning with the repo's established convention of using versioned tags is still the right call for build reproducibility and audit trails.Would you like me to open a follow-up issue to track this if you'd prefer to address it in a separate PR?
🏁 Script executed:
Length of output: 96
🏁 Script executed:
Repository: openshift/console
Length of output: 45
Got the digest. Here's the fully pinned suggestion for the strongest reproducibility guarantee:
This locks the build to the exact image layer that is current as of today. When Red Hat releases UBI 9.8 or a patch update to 9.7, this Dockerfile won't silently pick it up — you'd need to consciously update the digest, which is the desired behavior for a reproducible, auditable build.
If the team prefers to track minor updates automatically without needing digest bumps, the simpler
9.7tag (without the digest) is still a meaningful improvement over:latestand aligns with the versioned-tag convention used everywhere else in the repo.