Merge pull request #3997 from 11janci/jjanik-docker-env-escape
Escape systemd special chars in docker-envpull/4054/head
commit
e48fdddde9
|
@ -21,6 +21,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -47,6 +48,9 @@ type BuildrootProvisioner struct {
|
||||||
provision.SystemdProvisioner
|
provision.SystemdProvisioner
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for escaping systemd template specifiers (e.g. '%i'), which are not supported by minikube
|
||||||
|
var systemdSpecifierEscaper = strings.NewReplacer("%", "%%")
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
provision.Register("Buildroot", &provision.RegisteredProvisioner{
|
provision.Register("Buildroot", &provision.RegisteredProvisioner{
|
||||||
New: NewBuildrootProvisioner,
|
New: NewBuildrootProvisioner,
|
||||||
|
@ -64,6 +68,17 @@ func (p *BuildrootProvisioner) String() string {
|
||||||
return "buildroot"
|
return "buildroot"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// escapeSystemdDirectives escapes special characters in the input variables used to create the
|
||||||
|
// systemd unit file, which would otherwise be interpreted as systemd directives. An example
|
||||||
|
// are template specifiers (e.g. '%i') which are predefined variables that get evaluated dynamically
|
||||||
|
// (see systemd man pages for more info). This is not supported by minikube, thus needs to be escaped.
|
||||||
|
func escapeSystemdDirectives(engineConfigContext *provision.EngineConfigContext) {
|
||||||
|
// escape '%' in Environment option so that it does not evaluate into a template specifier
|
||||||
|
engineConfigContext.EngineOptions.Env = util.ReplaceChars(engineConfigContext.EngineOptions.Env, systemdSpecifierEscaper)
|
||||||
|
// input might contain whitespaces, wrap it in quotes
|
||||||
|
engineConfigContext.EngineOptions.Env = util.ConcatStrings(engineConfigContext.EngineOptions.Env, "\"", "\"")
|
||||||
|
}
|
||||||
|
|
||||||
// GenerateDockerOptions generates the *provision.DockerOptions for this provisioner
|
// GenerateDockerOptions generates the *provision.DockerOptions for this provisioner
|
||||||
func (p *BuildrootProvisioner) GenerateDockerOptions(dockerPort int) (*provision.DockerOptions, error) {
|
func (p *BuildrootProvisioner) GenerateDockerOptions(dockerPort int) (*provision.DockerOptions, error) {
|
||||||
var engineCfg bytes.Buffer
|
var engineCfg bytes.Buffer
|
||||||
|
@ -127,6 +142,8 @@ WantedBy=multi-user.target
|
||||||
EngineOptions: p.EngineOptions,
|
EngineOptions: p.EngineOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
escapeSystemdDirectives(&engineConfigContext)
|
||||||
|
|
||||||
if err := t.Execute(&engineCfg, engineConfigContext); err != nil {
|
if err := t.Execute(&engineCfg, engineConfigContext); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -250,3 +250,26 @@ func TeePrefix(prefix string, r io.Reader, w io.Writer, logger func(format strin
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReplaceChars returns a copy of the src slice with each string modified by the replacer
|
||||||
|
func ReplaceChars(src []string, replacer *strings.Replacer) []string {
|
||||||
|
ret := make([]string, len(src))
|
||||||
|
for i, s := range src {
|
||||||
|
ret[i] = replacer.Replace(s)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConcatStrings concatenates each string in the src slice with prefix and postfix and returns a new slice
|
||||||
|
func ConcatStrings(src []string, prefix string, postfix string) []string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
ret := make([]string, len(src))
|
||||||
|
for i, s := range src {
|
||||||
|
buf.WriteString(prefix)
|
||||||
|
buf.WriteString(s)
|
||||||
|
buf.WriteString(postfix)
|
||||||
|
ret[i] = buf.String()
|
||||||
|
buf.Reset()
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
|
@ -197,3 +197,43 @@ func TestTeePrefix(t *testing.T) {
|
||||||
t.Errorf("log=%q, want: %q", gotLog, wantLog)
|
t.Errorf("log=%q, want: %q", gotLog, wantLog)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReplaceChars(t *testing.T) {
|
||||||
|
testData := []struct {
|
||||||
|
src []string
|
||||||
|
replacer *strings.Replacer
|
||||||
|
expectedRes []string
|
||||||
|
}{
|
||||||
|
{[]string{"abc%def", "%Y%"}, strings.NewReplacer("%", "X"), []string{"abcXdef", "XYX"}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range testData {
|
||||||
|
res := ReplaceChars(tt.src, tt.replacer)
|
||||||
|
for i, val := range res {
|
||||||
|
if val != tt.expectedRes[i] {
|
||||||
|
t.Fatalf("Expected '%s' but got '%s'", tt.expectedRes, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConcatStrings(t *testing.T) {
|
||||||
|
testData := []struct {
|
||||||
|
src []string
|
||||||
|
prefix string
|
||||||
|
postfix string
|
||||||
|
expectedRes []string
|
||||||
|
}{
|
||||||
|
{[]string{"abc", ""}, "xx", "yy", []string{"xxabcyy", "xxyy"}},
|
||||||
|
{[]string{"abc", ""}, "", "", []string{"abc", ""}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range testData {
|
||||||
|
res := ConcatStrings(tt.src, tt.prefix, tt.postfix)
|
||||||
|
for i, val := range res {
|
||||||
|
if val != tt.expectedRes[i] {
|
||||||
|
t.Fatalf("Expected '%s' but got '%s'", tt.expectedRes, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue