Skip to content

Commit

Permalink
Escape systemd special chars in —docker-env
Browse files Browse the repository at this point in the history
  • Loading branch information
11janci committed Mar 27, 2019
1 parent a30092a commit 94ce57e
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 8 deletions.
15 changes: 15 additions & 0 deletions pkg/provision/buildroot.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"fmt"
"path"
"path/filepath"
"strings"
"text/template"
"time"

Expand All @@ -47,6 +48,9 @@ type BuildrootProvisioner struct {
provision.SystemdProvisioner
}

// for escaping systemd template specifiers (e.g. '%i'), which are not supported by minikube
var systemdSpecifierEscaper = strings.NewReplacer("%", "%%")

func init() {
provision.Register("Buildroot", &provision.RegisteredProvisioner{
New: NewBuildrootProvisioner,
Expand All @@ -64,6 +68,15 @@ func (p *BuildrootProvisioner) String() string {
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)
}

// GenerateDockerOptions generates the *provision.DockerOptions for this provisioner
func (p *BuildrootProvisioner) GenerateDockerOptions(dockerPort int) (*provision.DockerOptions, error) {
var engineCfg bytes.Buffer
Expand Down Expand Up @@ -127,6 +140,8 @@ WantedBy=multi-user.target
EngineOptions: p.EngineOptions,
}

escapeSystemdDirectives(engineConfigContext)

if err := t.Execute(&engineCfg, engineConfigContext); err != nil {
return nil, err
}
Expand Down
9 changes: 9 additions & 0 deletions pkg/util/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,3 +250,12 @@ func TeePrefix(prefix string, r io.Reader, w io.Writer, logger func(format strin
}
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
}
19 changes: 19 additions & 0 deletions pkg/util/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,22 @@ func TestTeePrefix(t *testing.T) {
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)
}
}
}
}
27 changes: 19 additions & 8 deletions test/integration/start_stop_delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,42 +19,44 @@ limitations under the License.
package integration

import (
"fmt"
"net"
"strings"
"testing"
"time"

"github.com/docker/machine/libmachine/state"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/test/integration/util"
)

func TestStartStop(t *testing.T) {
tests := []struct {
name string
args []string
name string
args []string
assertCustom func(t *testing.T, r *util.MinikubeRunner)
}{
{"nocache_oldest", []string{
"--cache-images=false",
fmt.Sprintf("--kubernetes-version=%s", constants.OldestKubernetesVersion),
}},
}, null},
{"feature_gates_newest_cni", []string{
"--feature-gates",
"ServerSideApply=true",
"--network-plugin=cni",
"--extra-config=kubelet.network-plugin=cni",
fmt.Sprintf("--kubernetes-version=%s", constants.NewestKubernetesVersion),
}},
}, null},
{"containerd", []string{
"--container-runtime=containerd",
"--docker-opt containerd=/var/run/containerd/containerd.sock",
}},
}, null},
{"crio_ignore_preflights", []string{
"--container-runtime=crio",
"--extra-config",
"kubeadm.ignore-preflight-errors=SystemVerification",
}},
}, null},
{"docker_env_special_char", []string{
"--docker-env TEST_VAR=encoded%40space",
}, assertDockerEnv},
}

for _, test := range tests {
Expand All @@ -70,6 +72,10 @@ func TestStartStop(t *testing.T) {
r.Start(test.args...)
r.CheckStatus(state.Running.String())

if test.assertCustom != nil {
test.assertCustom(t, &r)
}

ip := r.RunCommand("ip", true)
ip = strings.TrimRight(ip, "\n")
if net.ParseIP(ip) == nil {
Expand All @@ -93,3 +99,8 @@ func TestStartStop(t *testing.T) {
})
}
}

func assertDockerEnv(t *testing.T, r *util.MinikubeRunner) {
out, _ := r.SSH("systemctl show --property=Environment docker")
t.Fatalf("========> %s", out)
}

0 comments on commit 94ce57e

Please sign in to comment.