Compare commits

..

2 Commits

Author SHA1 Message Date
2b27cc57e3 render context: add asset_download_token 2025-07-27 12:40:01 +02:00
7f1193cdda dlset: allow globs in name, short kind 2025-07-27 12:08:45 +02:00
4 changed files with 42 additions and 42 deletions

View File

@ -8,7 +8,6 @@ import (
"math/rand" "math/rand"
"path" "path"
"reflect" "reflect"
"strconv"
"strings" "strings"
"github.com/cespare/xxhash" "github.com/cespare/xxhash"
@ -291,14 +290,6 @@ func (ctx *renderContext) templateFuncs(ctxMap map[string]any) map[string]any {
"host_download_token": func() (s string) { "host_download_token": func() (s string) {
return "{{ host_download_token }}" return "{{ host_download_token }}"
}, },
"asset_download_token": func(args ...string) (s string) {
argsStr := new(strings.Builder)
for _, arg := range args {
argsStr.WriteByte(' ')
argsStr.WriteString(strconv.Quote(arg))
}
return "{{ asset_download_token" + argsStr.String() + " }}"
},
"hosts_of_group": func() (hosts []any) { "hosts_of_group": func() (hosts []any) {
hosts = make([]any, 0) hosts = make([]any, 0)

View File

@ -1,15 +0,0 @@
package main
func htmlHeader(title string) string {
return `<!doctype html>
<html>
<head>
<title>` + title + `</title>
<style>@import url('/ui/style.css');@import url('/ui/app.css');</style>
</head>
<body><h1>` + title + `</h1>
`
}
var htmlFooter = `</body>
</html>`

View File

@ -17,11 +17,6 @@ import (
"m.cluseau.fr/go/httperr" "m.cluseau.fr/go/httperr"
) )
func globMatch(pattern, value string) bool {
ok, _ := filepath.Match(pattern, value)
return ok
}
type DownloadSet struct { type DownloadSet struct {
Expiry time.Time Expiry time.Time
Items []DownloadSetItem Items []DownloadSetItem
@ -29,7 +24,7 @@ type DownloadSet struct {
func (s DownloadSet) Contains(kind, name, asset string) bool { func (s DownloadSet) Contains(kind, name, asset string) bool {
for _, item := range s.Items { for _, item := range s.Items {
if item.Kind == kind && globMatch(item.Name, name) && if item.Kind == kind && item.Name == name &&
slices.Contains(item.Assets, asset) { slices.Contains(item.Assets, asset) {
return true return true
} }
@ -246,13 +241,28 @@ func wsDownloadSet(req *restful.Request, resp *restful.Response) {
set, err := getDlSet(req) set, err := getDlSet(req)
if err != nil { if err != nil {
resp.WriteHeader(err.Status) resp.WriteHeader(err.Status)
resp.Write([]byte(htmlHeader(err.Error()))) resp.Write([]byte(`<!doctype html>
resp.Write([]byte(htmlFooter)) <html>
<head>
<title>` + err.Error() + `</title>
<style src="/ui/style.css"/>
<style src="/ui/app.css"/>
</head>
<body><h1>` + err.Error() + `</h1></body>
</html>`))
return return
} }
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
buf.WriteString(htmlHeader("Download set")) buf.WriteString(`<!doctype html>
<html>
<head>
<title>Download set</title>
<style src="/ui/style.css"/>
<style src="/ui/app.css"/>
</head>
<body><h1>Download set</h1>
`)
cfg, err2 := readConfig() cfg, err2 := readConfig()
if err2 != nil { if err2 != nil {
@ -265,13 +275,13 @@ func wsDownloadSet(req *restful.Request, resp *restful.Response) {
switch item.Kind { switch item.Kind {
case "cluster": case "cluster":
for _, c := range cfg.Clusters { for _, c := range cfg.Clusters {
if globMatch(item.Name, c.Name) { if ok, _ := filepath.Match(item.Name, c.Name); ok {
names = append(names, c.Name) names = append(names, c.Name)
} }
} }
case "host": case "host":
for _, h := range cfg.Hosts { for _, h := range cfg.Hosts {
if globMatch(item.Name, h.Name) { if ok, _ := filepath.Match(item.Name, h.Name); ok {
names = append(names, h.Name) names = append(names, h.Name)
} }
} }
@ -287,6 +297,6 @@ func wsDownloadSet(req *restful.Request, resp *restful.Response) {
} }
} }
buf.WriteString(htmlFooter) buf.WriteString("</body></html>")
buf.WriteTo(resp) buf.WriteTo(resp)
} }

View File

@ -180,20 +180,34 @@ func wsDownloadPage(req *restful.Request, resp *restful.Response) {
spec, ok := wState.Get().Downloads[token] spec, ok := wState.Get().Downloads[token]
if !ok { if !ok {
resp.WriteHeader(http.StatusNotFound) resp.WriteHeader(http.StatusNotFound)
resp.Write([]byte(htmlHeader("Token not found"))) resp.Write([]byte(`<!doctype html>
resp.Write([]byte(htmlFooter)) <html>
<head>
<title>Token not found</title>
<style src="/ui/style.css"/>
<style src="/ui/app.css"/>
</head>
<body><h1>Token not found</h1></body>
</html>`))
return return
} }
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
buf.WriteString(htmlHeader(fmt.Sprintf("Token assets: %s %s", spec.Kind, spec.Name))) fmt.Fprintf(buf, `<!doctype html>
<html>
<head>
<title>Token assets: %s %s</title>
<style src="/ui/style.css"/>
<style src="/ui/app.css"/>
</head>
<body><h1>Token assets: %s %s</h1>
<ul>
`, spec.Kind, spec.Name, spec.Kind, spec.Name)
buf.WriteString("<ul>")
for _, asset := range spec.Assets { for _, asset := range spec.Assets {
fmt.Fprintf(buf, "<li><a href=\"%s\" download>%s</a></li>\n", asset, asset) fmt.Fprintf(buf, "<li><a href=\"%s\" download>%s</a></li>\n", asset, asset)
} }
buf.WriteString("</ul>")
buf.WriteString(htmlFooter) buf.WriteString("</ul></body></html>")
buf.WriteTo(resp) buf.WriteTo(resp)
} }