Skip to content

Commit a4a2391

Browse files
mprycclaude
andcommitted
Upstream: <carry>: Use clean binary names in download server
Replace versioned binary names (oadp-vmdp_${VERSION}_${os}_${arch}) with clean names (oadp-vmdp_${os}_${arch}) so users can directly curl/wget binaries without version/commit hash in the filename. Switch from single sha256sum.txt to per-file .sha256 sidecar checksums. Add LICENSE as a downloadable file on the download server page. Similar to migtools/oadp-cli#174 Co-authored-by: Claude <noreply@anthropic.com> Signed-off-by: Michal Pryc <mpryc@redhat.com>
1 parent 17b230f commit a4a2391

4 files changed

Lines changed: 39 additions & 38 deletions

File tree

Containerfile.download

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,16 @@ RUN go mod download && go mod verify
5252
COPY . .
5353

5454
# Build oadp-vmdp binaries for all target platforms as direct executables
55-
# Binaries are statically linked so no archive wrapping is needed
56-
# SHA256 checksums are generated for integrity verification
55+
# with clean names (no version/commit hash) for direct curl/wget download.
56+
# Per-file SHA256 checksums are generated for integrity verification.
5757
RUN mkdir -p /archives && \
5858
for platform in linux/amd64 linux/arm64 windows/amd64 windows/arm64; do \
5959
os=$(echo $platform | cut -d'/' -f1); \
6060
arch=$(echo $platform | cut -d'/' -f2); \
6161
if [ "$os" = "windows" ]; then \
62-
out_name="oadp-vmdp_${VERSION}_${os}_${arch}.exe"; \
62+
out_name="oadp-vmdp_${os}_${arch}.exe"; \
6363
else \
64-
out_name="oadp-vmdp_${VERSION}_${os}_${arch}"; \
64+
out_name="oadp-vmdp_${os}_${arch}"; \
6565
fi; \
6666
echo "Building oadp-vmdp for ${os}/${arch}..."; \
6767
CGO_ENABLED=0 GOOS=$os GOARCH=$arch \
@@ -73,8 +73,9 @@ RUN mkdir -p /archives && \
7373
-X github.com/kopia/kopia/repo.BuildGitHubRepo=github.com/openshift/oadp-vmdp" \
7474
-o /archives/$out_name \
7575
. ; \
76+
sha256sum /archives/$out_name > /archives/$out_name.sha256; \
7677
done && \
77-
cd /archives && sha256sum oadp-vmdp_* > sha256sum.txt && \
78+
cp LICENSE /archives/LICENSE && \
7879
rm -rf /root/.cache/go-build /tmp/*
7980

8081
# Build the download server for the TARGET platform (the arch this container will run on)

cmd/downloads/server.go

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import (
1515
)
1616

1717
const (
18-
checksumFile = "sha256sum.txt"
1918
binaryPrefix = "oadp-vmdp_"
19+
licenseFile = "LICENSE"
2020
bytesPerMB = 1024 * 1024
2121
minPlatformParts = 3
2222
readTimeout = 10 * time.Second
@@ -82,7 +82,7 @@ func main() {
8282
}
8383
}
8484

85-
// listBinaryFiles returns all downloadable files (excludes sha256sum.txt and .sha256 sidecars).
85+
// listBinaryFiles returns all downloadable binaries (excludes .sha256 sidecars and LICENSE).
8686
func listBinaryFiles() ([]string, error) {
8787
entries, err := os.ReadDir(archiveDir)
8888
if err != nil {
@@ -99,49 +99,31 @@ func listBinaryFiles() ([]string, error) {
9999
name := e.Name()
100100

101101
if strings.HasPrefix(name, binaryPrefix) &&
102-
!strings.HasSuffix(name, ".sha256") &&
103-
name != checksumFile {
102+
!strings.HasSuffix(name, ".sha256") {
104103
files = append(files, filepath.Join(archiveDir, name))
105104
}
106105
}
107106

108107
return files, nil
109108
}
110109

111-
// readChecksum reads a SHA256 checksum from a .sha256 sidecar file or
112-
// falls back to looking up the filename in sha256sum.txt.
110+
// readChecksum reads a SHA256 checksum from a per-file .sha256 sidecar file.
113111
func readChecksum(filePath string) string {
114-
// Try per-file .sha256 sidecar first (oadp-cli style).
115112
data, err := os.ReadFile(filePath + ".sha256") //nolint:gosec // path is constructed from archiveDir constant
116-
if err == nil {
117-
fields := strings.Fields(string(data))
118-
if len(fields) > 0 {
119-
return fields[0]
120-
}
121-
}
122-
123-
// Fall back to sha256sum.txt.
124-
sumFile := filepath.Join(filepath.Dir(filePath), checksumFile)
125-
126-
data, err = os.ReadFile(sumFile) //nolint:gosec // path is constructed from archiveDir constant
127113
if err != nil {
128114
return ""
129115
}
130116

131-
base := filepath.Base(filePath)
132-
133-
for line := range strings.SplitSeq(strings.TrimSpace(string(data)), "\n") {
134-
fields := strings.Fields(line)
135-
if len(fields) == 2 && fields[1] == base {
136-
return fields[0]
137-
}
117+
fields := strings.Fields(string(data))
118+
if len(fields) > 0 {
119+
return fields[0]
138120
}
139121

140122
return ""
141123
}
142124

143125
// parsePlatform extracts OS and architecture from a filename like
144-
// oadp-vmdp_v1.0.0_linux_amd64 or oadp-vmdp_v1.0.0_windows_arm64.exe.
126+
// oadp-vmdp_linux_amd64 or oadp-vmdp_windows_arm64.exe.
145127
func parsePlatform(filename string) (string, string) {
146128
name := strings.TrimSuffix(filename, ".exe")
147129

@@ -160,6 +142,11 @@ func listBinaries(w http.ResponseWriter, _ *http.Request) {
160142
return
161143
}
162144

145+
hasLicense := false
146+
if _, err := os.Stat(filepath.Join(archiveDir, licenseFile)); err == nil {
147+
hasLicense = true
148+
}
149+
163150
var linuxFiles, windowsFiles []archiveFile
164151

165152
for _, file := range files {
@@ -187,7 +174,8 @@ func listBinaries(w http.ResponseWriter, _ *http.Request) {
187174
data := struct {
188175
LinuxFiles []archiveFile
189176
WindowsFiles []archiveFile
190-
}{linuxFiles, windowsFiles}
177+
HasLicense bool
178+
}{linuxFiles, windowsFiles, hasLicense}
191179

192180
w.Header().Set("Content-Type", "text/html")
193181

@@ -199,13 +187,13 @@ func listBinaries(w http.ResponseWriter, _ *http.Request) {
199187
func downloadBinary(w http.ResponseWriter, r *http.Request) {
200188
filename := filepath.Base(r.URL.Path[len("/download/"):])
201189

202-
// Security: only allow known file prefixes and the checksum file.
190+
// Security: only allow known file prefixes and the LICENSE file.
203191
if filepath.Dir(filename) != "." {
204192
http.Error(w, "Invalid filename", http.StatusBadRequest)
205193
return
206194
}
207195

208-
if !strings.HasPrefix(filename, binaryPrefix) && filename != checksumFile {
196+
if !strings.HasPrefix(filename, binaryPrefix) && filename != licenseFile {
209197
http.Error(w, "Invalid filename", http.StatusBadRequest)
210198
return
211199
}
@@ -219,7 +207,7 @@ func downloadBinary(w http.ResponseWriter, r *http.Request) {
219207

220208
w.Header().Set("Content-Disposition", "attachment; filename="+filename)
221209

222-
if filename == checksumFile {
210+
if filename == licenseFile {
223211
w.Header().Set("Content-Type", "text/plain")
224212
} else {
225213
w.Header().Set("Content-Type", "application/octet-stream")

cmd/downloads/templates/index.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,16 @@
7272
</div>
7373
{{end}}
7474

75+
{{if .HasLicense}}
76+
<div class="section">
77+
<div class="section-header">License</div>
78+
<div style="padding: 0.85rem 1.25rem; display: flex; align-items: center; justify-content: space-between;">
79+
<span style="font-size: 0.9rem;">LICENSE</span>
80+
<a class="download-btn" href="/download/LICENSE">View License</a>
81+
</div>
82+
</div>
83+
{{end}}
84+
7585
<div class="install-section">
7686
<h3>Installation</h3>
7787

konflux.Dockerfile

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ ARG BUILD_DATE=unknown
1616
ARG BUILDTAGS=
1717

1818
# Build oadp-vmdp binaries for all target platforms as direct executables
19+
# with clean names (no version/commit hash) for direct curl/wget download.
1920
RUN mkdir -p /archives && \
2021
for platform in linux/amd64 linux/arm64 windows/amd64 windows/arm64; do \
2122
os=$(echo $platform | cut -d'/' -f1); \
2223
arch=$(echo $platform | cut -d'/' -f2); \
2324
if [ "$os" = "windows" ]; then \
24-
out_name="oadp-vmdp_${VERSION}_${os}_${arch}.exe"; \
25+
out_name="oadp-vmdp_${os}_${arch}.exe"; \
2526
else \
26-
out_name="oadp-vmdp_${VERSION}_${os}_${arch}"; \
27+
out_name="oadp-vmdp_${os}_${arch}"; \
2728
fi; \
2829
echo "Building oadp-vmdp for ${os}/${arch}..."; \
2930
CGO_ENABLED=0 GOOS=$os GOARCH=$arch \
@@ -35,8 +36,9 @@ RUN mkdir -p /archives && \
3536
-X github.com/kopia/kopia/repo.BuildGitHubRepo=github.com/openshift/oadp-vmdp" \
3637
-o /archives/$out_name \
3738
. ; \
39+
sha256sum /archives/$out_name > /archives/$out_name.sha256; \
3840
done && \
39-
cd /archives && sha256sum oadp-vmdp_* > sha256sum.txt && \
41+
cp LICENSE /archives/LICENSE && \
4042
rm -rf /root/.cache/go-build /tmp/*
4143

4244
# Build the download server (FIPS-compliant)

0 commit comments

Comments
 (0)