diff --git a/pkg/kubelet/rkt/fake_rkt_interface_test.go b/pkg/kubelet/rkt/fake_rkt_interface_test.go index 740701a331b..e254b521b61 100644 --- a/pkg/kubelet/rkt/fake_rkt_interface_test.go +++ b/pkg/kubelet/rkt/fake_rkt_interface_test.go @@ -194,7 +194,7 @@ func newFakeRktCli() *fakeRktCli { } } -func (f *fakeRktCli) RunCommand(args ...string) (result []string, err error) { +func (f *fakeRktCli) RunCommand(config *Config, args ...string) (result []string, err error) { f.Lock() defer f.Unlock() cmd := append([]string{"rkt"}, args...) diff --git a/pkg/kubelet/rkt/image.go b/pkg/kubelet/rkt/image.go index 3515b073ad3..afdbe94ee92 100644 --- a/pkg/kubelet/rkt/image.go +++ b/pkg/kubelet/rkt/image.go @@ -23,6 +23,7 @@ import ( "io/ioutil" "os" "path" + "path/filepath" "sort" "strings" @@ -62,13 +63,20 @@ func (r *Runtime) PullImage(image kubecontainer.ImageSpec, pullSecrets []api.Sec glog.V(1).Infof("Pulling image %s without credentials", img) } - // Let's update a json. - // TODO(yifan): Find a way to feed this to rkt. - if err := r.writeDockerAuthConfig(img, creds); err != nil { + userConfigDir, err := ioutil.TempDir("", "rktnetes-user-config-dir-") + if err != nil { + return fmt.Errorf("rkt: Cannot create a temporary user-config directory: %v", err) + } + defer os.RemoveAll(userConfigDir) + + config := *r.config + config.UserConfigDir = userConfigDir + + if err := r.writeDockerAuthConfig(img, creds, userConfigDir); err != nil { return err } - if _, err := r.cli.RunCommand("fetch", dockerPrefix+img); err != nil { + if _, err := r.cli.RunCommand(&config, "fetch", dockerPrefix+img); err != nil { glog.Errorf("Failed to fetch: %v", err) return err } @@ -104,7 +112,7 @@ func (r *Runtime) RemoveImage(image kubecontainer.ImageSpec) error { if err != nil { return err } - if _, err := r.cli.RunCommand("image", "rm", imageID); err != nil { + if _, err := r.cli.RunCommand(nil, "image", "rm", imageID); err != nil { return err } return nil @@ -186,7 +194,7 @@ func (r *Runtime) getImageManifest(image string) (*appcschema.ImageManifest, err // TODO(yifan): This is very racy, unefficient, and unsafe, we need to provide // different namespaces. See: https://github.com/coreos/rkt/issues/836. -func (r *Runtime) writeDockerAuthConfig(image string, credsSlice []credentialprovider.LazyAuthConfiguration) error { +func (r *Runtime) writeDockerAuthConfig(image string, credsSlice []credentialprovider.LazyAuthConfiguration, userConfigDir string) error { if len(credsSlice) == 0 { return nil } @@ -204,15 +212,7 @@ func (r *Runtime) writeDockerAuthConfig(image string, credsSlice []credentialpro registry = strings.Split(image, "/")[0] } - configDir := r.config.UserConfigDir - if configDir == "" { - configDir = r.config.LocalConfigDir - } - if configDir == "" { - return fmt.Errorf("No user or local config dir is specified") - } - - authDir := path.Join(configDir, "auth.d") + authDir := filepath.Join(userConfigDir, "auth.d") if _, err := os.Stat(authDir); os.IsNotExist(err) { if err := os.MkdirAll(authDir, 0600); err != nil { glog.Errorf("rkt: Cannot create auth dir: %v", err) diff --git a/pkg/kubelet/rkt/rkt.go b/pkg/kubelet/rkt/rkt.go index 9e06ddf82a6..d67b3a8cdfc 100644 --- a/pkg/kubelet/rkt/rkt.go +++ b/pkg/kubelet/rkt/rkt.go @@ -167,9 +167,9 @@ type podGetter interface { // cliInterface wrapps the command line calls for testing purpose. type cliInterface interface { - // args are the arguments given to the 'rkt' command, - // e.g. args can be 'rm ${UUID}'. - RunCommand(args ...string) (result []string, err error) + // RunCommand creates rkt commands and runs it with the given config. + // If the config is nil, it will use the one inferred from rkt API service. + RunCommand(config *Config, args ...string) (result []string, err error) } // New creates the rkt container runtime which implements the container runtime interface. @@ -263,9 +263,11 @@ func New( return rkt, nil } -func (r *Runtime) buildCommand(args ...string) *exec.Cmd { - allArgs := append(r.config.buildGlobalOptions(), args...) - return exec.Command(r.config.Path, allArgs...) +func buildCommand(config *Config, args ...string) *exec.Cmd { + cmd := exec.Command(config.Path) + cmd.Args = append(cmd.Args, config.buildGlobalOptions()...) + cmd.Args = append(cmd.Args, args...) + return cmd } // convertToACName converts a string into ACName. @@ -278,13 +280,18 @@ func convertToACName(name string) appctypes.ACName { // RunCommand invokes rkt binary with arguments and returns the result // from stdout in a list of strings. Each string in the list is a line. -func (r *Runtime) RunCommand(args ...string) ([]string, error) { - glog.V(4).Info("rkt: Run command:", args) +// If config is non-nil, it will use the given config instead of the config +// inferred from rkt API service. +func (r *Runtime) RunCommand(config *Config, args ...string) ([]string, error) { + if config == nil { + config = r.config + } + glog.V(4).Infof("rkt: Run command: %q with config: %+v", args, config) var stdout, stderr bytes.Buffer - cmd := r.buildCommand(args...) - cmd.Stdout = &stdout - cmd.Stderr = &stderr + + cmd := buildCommand(config, args...) + cmd.Stdout, cmd.Stderr = &stdout, &stderr if err := cmd.Run(); err != nil { return nil, fmt.Errorf("failed to run %v: %v\nstdout: %v\nstderr: %v", args, err, stdout.String(), stderr.String()) } @@ -895,7 +902,7 @@ func serviceFilePath(serviceName string) string { // generateRunCommand crafts a 'rkt run-prepared' command with necessary parameters. func (r *Runtime) generateRunCommand(pod *api.Pod, uuid, netnsName string) (string, error) { - runPrepared := r.buildCommand("run-prepared").Args + runPrepared := buildCommand(r.config, "run-prepared").Args // Network namespace set up in kubelet; rkt networking not used runPrepared = append(runPrepared, "--net=host") @@ -1019,7 +1026,7 @@ func (r *Runtime) preparePod(pod *api.Pod, podIP string, pullSecrets []api.Secre } prepareCmd := r.preparePodArgs(manifest, manifestFile.Name()) - output, err := r.RunCommand(prepareCmd...) + output, err := r.cli.RunCommand(nil, prepareCmd...) if err != nil { return "", nil, err } @@ -1826,7 +1833,7 @@ func (r *Runtime) removePod(uuid string) error { // Network may not be around anymore so errors are ignored r.cleanupPodNetworkFromServiceFile(serviceFile) - if _, err := r.cli.RunCommand("rm", uuid); err != nil { + if _, err := r.cli.RunCommand(nil, "rm", uuid); err != nil { errlist = append(errlist, fmt.Errorf("rkt: Failed to remove pod %q: %v", uuid, err)) } @@ -1866,7 +1873,7 @@ func (r *Runtime) ExecInContainer(containerID kubecontainer.ContainerID, cmd []s } args := []string{"enter", fmt.Sprintf("--app=%s", id.appName), id.uuid} args = append(args, cmd...) - command := r.buildCommand(args...) + command := buildCommand(r.config, args...) if tty { p, err := kubecontainer.StartPty(command)