mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-07-18 22:40:35 +00:00
Merge pull request #132177 from pgimalac/apiserver-avoid-template-for-dce
Remove use of html/template in apiserver to avoid disabling dead code elimination
This commit is contained in:
@@ -19,7 +19,7 @@ package util
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/x509"
|
||||
"html/template"
|
||||
"html/template" //nolint:depguard
|
||||
"strings"
|
||||
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
|
||||
@@ -254,6 +254,8 @@ linters:
|
||||
deny:
|
||||
- pkg: "github.com/google/go-cmp/cmp"
|
||||
desc: "cmp is allowed only in test files"
|
||||
- pkg: "html/template"
|
||||
desc: "template is allowed only in test files as it disables dead code elimination"
|
||||
forbidigo:
|
||||
analyze-types: true
|
||||
forbid:
|
||||
|
||||
@@ -268,6 +268,8 @@ linters:
|
||||
deny:
|
||||
- pkg: "github.com/google/go-cmp/cmp"
|
||||
desc: "cmp is allowed only in test files"
|
||||
- pkg: "html/template"
|
||||
desc: "template is allowed only in test files as it disables dead code elimination"
|
||||
forbidigo:
|
||||
analyze-types: true
|
||||
forbid:
|
||||
|
||||
@@ -198,6 +198,8 @@ linters:
|
||||
deny:
|
||||
- pkg: "github.com/google/go-cmp/cmp"
|
||||
desc: "cmp is allowed only in test files"
|
||||
- pkg: "html/template"
|
||||
desc: "template is allowed only in test files as it disables dead code elimination"
|
||||
forbidigo:
|
||||
analyze-types: true
|
||||
forbid:
|
||||
|
||||
@@ -18,7 +18,7 @@ package routes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"html/template" //nolint:depguard
|
||||
"io"
|
||||
"net/http"
|
||||
"path"
|
||||
@@ -56,12 +56,15 @@ func (f DebugFlags) Install(c *mux.PathRecorderMux, flag string, handler func(ht
|
||||
func (f DebugFlags) Index(w http.ResponseWriter, r *http.Request) {
|
||||
lock.RLock()
|
||||
defer lock.RUnlock()
|
||||
if err := indexTmpl.Execute(w, registeredFlags); err != nil {
|
||||
if err := indexTmpl(w, registeredFlags); err != nil {
|
||||
klog.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
var indexTmpl = template.Must(template.New("index").Parse(`<html>
|
||||
func indexTmpl(w io.Writer, flags map[string]debugFlag) error {
|
||||
// avoid using a template to avoid disabling dead code elimination
|
||||
// https://github.com/golang/go/issues/72895
|
||||
_, err := w.Write([]byte(`<html>
|
||||
<head>
|
||||
<title>/debug/flags/</title>
|
||||
</head>
|
||||
@@ -70,15 +73,27 @@ var indexTmpl = template.Must(template.New("index").Parse(`<html>
|
||||
<br>
|
||||
flags:<br>
|
||||
<table>
|
||||
{{range .}}
|
||||
<tr>{{.Flag}}<br>
|
||||
{{end}}
|
||||
</table>
|
||||
`))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, flag := range flags {
|
||||
_, err := fmt.Fprintf(w, `<tr>%s<br>
|
||||
`, template.HTMLEscapeString(flag.Flag))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
_, err = w.Write([]byte(`</table>
|
||||
<br>
|
||||
full flags configurable<br>
|
||||
</body>
|
||||
</html>
|
||||
`))
|
||||
return err
|
||||
}
|
||||
|
||||
type debugFlag struct {
|
||||
Flag string
|
||||
|
||||
@@ -17,9 +17,8 @@ limitations under the License.
|
||||
package statusz
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"html"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"time"
|
||||
@@ -35,30 +34,11 @@ var (
|
||||
|
||||
const DefaultStatuszPath = "/statusz"
|
||||
|
||||
const (
|
||||
headerFmt = `
|
||||
const headerFmt = `
|
||||
%s statusz
|
||||
Warning: This endpoint is not meant to be machine parseable, has no formatting compatibility guarantees and is for debugging purposes only.
|
||||
`
|
||||
|
||||
dataTemplate = `
|
||||
Started{{.Delim}} {{.StartTime}}
|
||||
Up{{.Delim}} {{.Uptime}}
|
||||
Go version{{.Delim}} {{.GoVersion}}
|
||||
Binary version{{.Delim}} {{.BinaryVersion}}
|
||||
{{if .EmulationVersion}}Emulation version{{.Delim}} {{.EmulationVersion}}{{end}}
|
||||
`
|
||||
)
|
||||
|
||||
type contentFields struct {
|
||||
Delim string
|
||||
StartTime string
|
||||
Uptime string
|
||||
GoVersion string
|
||||
BinaryVersion string
|
||||
EmulationVersion string
|
||||
}
|
||||
|
||||
type mux interface {
|
||||
Handle(path string, handler http.Handler)
|
||||
}
|
||||
@@ -68,25 +48,10 @@ func NewRegistry(effectiveVersion compatibility.EffectiveVersion) statuszRegistr
|
||||
}
|
||||
|
||||
func Install(m mux, componentName string, reg statuszRegistry) {
|
||||
dataTmpl, err := initializeTemplates()
|
||||
if err != nil {
|
||||
klog.Errorf("error while parsing gotemplates: %v", err)
|
||||
return
|
||||
}
|
||||
m.Handle(DefaultStatuszPath, handleStatusz(componentName, dataTmpl, reg))
|
||||
m.Handle(DefaultStatuszPath, handleStatusz(componentName, reg))
|
||||
}
|
||||
|
||||
func initializeTemplates() (*template.Template, error) {
|
||||
d := template.New("data")
|
||||
dataTmpl, err := d.Parse(dataTemplate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dataTmpl, nil
|
||||
}
|
||||
|
||||
func handleStatusz(componentName string, dataTmpl *template.Template, reg statuszRegistry) http.HandlerFunc {
|
||||
func handleStatusz(componentName string, reg statuszRegistry) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if !httputil.AcceptableMediaType(r) {
|
||||
http.Error(w, httputil.ErrUnsupportedMediaType.Error(), http.StatusNotAcceptable)
|
||||
@@ -94,7 +59,7 @@ func handleStatusz(componentName string, dataTmpl *template.Template, reg status
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, headerFmt, componentName)
|
||||
data, err := populateStatuszData(dataTmpl, reg)
|
||||
data, err := populateStatuszData(reg)
|
||||
if err != nil {
|
||||
klog.Errorf("error while populating statusz data: %v", err)
|
||||
http.Error(w, "error while populating statusz data", http.StatusInternalServerError)
|
||||
@@ -106,31 +71,28 @@ func handleStatusz(componentName string, dataTmpl *template.Template, reg status
|
||||
}
|
||||
}
|
||||
|
||||
func populateStatuszData(tmpl *template.Template, reg statuszRegistry) (string, error) {
|
||||
if tmpl == nil {
|
||||
return "", fmt.Errorf("received nil template")
|
||||
}
|
||||
|
||||
func populateStatuszData(reg statuszRegistry) (string, error) {
|
||||
randomIndex := rand.Intn(len(delimiters))
|
||||
data := contentFields{
|
||||
Delim: delimiters[randomIndex],
|
||||
StartTime: reg.processStartTime().Format(time.UnixDate),
|
||||
Uptime: uptime(reg.processStartTime()),
|
||||
GoVersion: reg.goVersion(),
|
||||
BinaryVersion: reg.binaryVersion().String(),
|
||||
}
|
||||
delim := html.EscapeString(delimiters[randomIndex])
|
||||
startTime := html.EscapeString(reg.processStartTime().Format(time.UnixDate))
|
||||
uptime := html.EscapeString(uptime(reg.processStartTime()))
|
||||
goVersion := html.EscapeString(reg.goVersion())
|
||||
binaryVersion := html.EscapeString(reg.binaryVersion().String())
|
||||
|
||||
var emulationVersion string
|
||||
if reg.emulationVersion() != nil {
|
||||
data.EmulationVersion = reg.emulationVersion().String()
|
||||
emulationVersion = fmt.Sprintf(`Emulation version%s %s`, delim, html.EscapeString(reg.emulationVersion().String()))
|
||||
}
|
||||
|
||||
var tpl bytes.Buffer
|
||||
err := tmpl.Execute(&tpl, data)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error executing statusz template: %w", err)
|
||||
}
|
||||
status := fmt.Sprintf(`
|
||||
Started%[1]s %[2]s
|
||||
Up%[1]s %[3]s
|
||||
Go version%[1]s %[4]s
|
||||
Binary version%[1]s %[5]s
|
||||
%[6]s
|
||||
`, delim, startTime, uptime, goVersion, binaryVersion, emulationVersion)
|
||||
|
||||
return tpl.String(), nil
|
||||
return status, nil
|
||||
}
|
||||
|
||||
func uptime(t time.Time) string {
|
||||
|
||||
Reference in New Issue
Block a user