Unverified Commit 3e4268f5 authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #62394 from jsafrane/revert-git-changes

Automatic merge from submit-queue (batch tested with PRs 60476, 62462, 61391, 62535, 62394). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Revert "git: Use VolumeHost.GetExec() to execute stuff in volume plugins" This reverts commit c578542a (PR #51098). The PR added support for containerized git, on the other hand it required git 1.8.5. This breaks git volumes on older distros (CentOS 7, Ubuntu 14.04) that have old git. Git volumes are getting deprecated (https://github.com/kubernetes/kubernetes/issues/60999) so we should restore it to the last working state and not touch it any longer. **Release note**: ```release-note gitRepo volumes in pods no longer require git 1.8.5 or newer, older git versions are supported too now. ``` I'd like to cherry-pick it into 1.10. /sig storage
parents 073ff709 d7615282
...@@ -14,12 +14,12 @@ go_library( ...@@ -14,12 +14,12 @@ go_library(
], ],
importpath = "k8s.io/kubernetes/pkg/volume/git_repo", importpath = "k8s.io/kubernetes/pkg/volume/git_repo",
deps = [ deps = [
"//pkg/util/mount:go_default_library",
"//pkg/util/strings:go_default_library", "//pkg/util/strings:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
], ],
) )
...@@ -28,13 +28,14 @@ go_test( ...@@ -28,13 +28,14 @@ go_test(
srcs = ["git_repo_test.go"], srcs = ["git_repo_test.go"],
embed = [":go_default_library"], embed = [":go_default_library"],
deps = [ deps = [
"//pkg/util/mount:go_default_library",
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/empty_dir:go_default_library", "//pkg/volume/empty_dir:go_default_library",
"//pkg/volume/testing:go_default_library", "//pkg/volume/testing:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
"//vendor/k8s.io/utils/exec/testing:go_default_library",
], ],
) )
......
...@@ -24,10 +24,10 @@ import ( ...@@ -24,10 +24,10 @@ import (
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/kubernetes/pkg/util/mount"
utilstrings "k8s.io/kubernetes/pkg/util/strings" utilstrings "k8s.io/kubernetes/pkg/util/strings"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
volumeutil "k8s.io/kubernetes/pkg/volume/util" volumeutil "k8s.io/kubernetes/pkg/volume/util"
"k8s.io/utils/exec"
) )
// This is the primary entrypoint for volume plugins. // This is the primary entrypoint for volume plugins.
...@@ -100,8 +100,7 @@ func (plugin *gitRepoPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, opts vol ...@@ -100,8 +100,7 @@ func (plugin *gitRepoPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, opts vol
source: spec.Volume.GitRepo.Repository, source: spec.Volume.GitRepo.Repository,
revision: spec.Volume.GitRepo.Revision, revision: spec.Volume.GitRepo.Revision,
target: spec.Volume.GitRepo.Directory, target: spec.Volume.GitRepo.Directory,
mounter: plugin.host.GetMounter(plugin.GetPluginName()), exec: exec.New(),
exec: plugin.host.GetExec(plugin.GetPluginName()),
opts: opts, opts: opts,
}, nil }, nil
} }
...@@ -150,8 +149,7 @@ type gitRepoVolumeMounter struct { ...@@ -150,8 +149,7 @@ type gitRepoVolumeMounter struct {
source string source string
revision string revision string
target string target string
mounter mount.Interface exec exec.Interface
exec mount.Exec
opts volume.VolumeOptions opts volume.VolumeOptions
} }
...@@ -197,7 +195,7 @@ func (b *gitRepoVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { ...@@ -197,7 +195,7 @@ func (b *gitRepoVolumeMounter) SetUpAt(dir string, fsGroup *int64) error {
if len(b.target) != 0 { if len(b.target) != 0 {
args = append(args, b.target) args = append(args, b.target)
} }
if output, err := b.execGit(args, dir); err != nil { if output, err := b.execCommand("git", args, dir); err != nil {
return fmt.Errorf("failed to exec 'git %s': %s: %v", return fmt.Errorf("failed to exec 'git %s': %s: %v",
strings.Join(args, " "), output, err) strings.Join(args, " "), output, err)
} }
...@@ -227,10 +225,10 @@ func (b *gitRepoVolumeMounter) SetUpAt(dir string, fsGroup *int64) error { ...@@ -227,10 +225,10 @@ func (b *gitRepoVolumeMounter) SetUpAt(dir string, fsGroup *int64) error {
return fmt.Errorf("unexpected directory contents: %v", files) return fmt.Errorf("unexpected directory contents: %v", files)
} }
if output, err := b.execGit([]string{"checkout", b.revision}, subdir); err != nil { if output, err := b.execCommand("git", []string{"checkout", b.revision}, subdir); err != nil {
return fmt.Errorf("failed to exec 'git checkout %s': %s: %v", b.revision, output, err) return fmt.Errorf("failed to exec 'git checkout %s': %s: %v", b.revision, output, err)
} }
if output, err := b.execGit([]string{"reset", "--hard"}, subdir); err != nil { if output, err := b.execCommand("git", []string{"reset", "--hard"}, subdir); err != nil {
return fmt.Errorf("failed to exec 'git reset --hard': %s: %v", output, err) return fmt.Errorf("failed to exec 'git reset --hard': %s: %v", output, err)
} }
...@@ -244,10 +242,10 @@ func (b *gitRepoVolumeMounter) getMetaDir() string { ...@@ -244,10 +242,10 @@ func (b *gitRepoVolumeMounter) getMetaDir() string {
return path.Join(b.plugin.host.GetPodPluginDir(b.podUID, utilstrings.EscapeQualifiedNameForDisk(gitRepoPluginName)), b.volName) return path.Join(b.plugin.host.GetPodPluginDir(b.podUID, utilstrings.EscapeQualifiedNameForDisk(gitRepoPluginName)), b.volName)
} }
func (b *gitRepoVolumeMounter) execGit(args []string, dir string) ([]byte, error) { func (b *gitRepoVolumeMounter) execCommand(command string, args []string, dir string) ([]byte, error) {
// run git -C <dir> <args> cmd := b.exec.Command(command, args...)
fullArgs := append([]string{"-C", dir}, args...) cmd.SetDir(dir)
return b.exec.Run("git", fullArgs...) return cmd.CombinedOutput()
} }
// gitRepoVolumeUnmounter cleans git repo volumes. // gitRepoVolumeUnmounter cleans git repo volumes.
......
...@@ -28,16 +28,11 @@ import ( ...@@ -28,16 +28,11 @@ import (
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/empty_dir" "k8s.io/kubernetes/pkg/volume/empty_dir"
volumetest "k8s.io/kubernetes/pkg/volume/testing" volumetest "k8s.io/kubernetes/pkg/volume/testing"
) "k8s.io/utils/exec"
fakeexec "k8s.io/utils/exec/testing"
const (
gitUrl = "https://github.com/kubernetes/kubernetes.git"
revision = "2a30ce65c5ab586b98916d83385c5983edd353a1"
gitRepositoryName = "kubernetes"
) )
func newTestHost(t *testing.T) (string, volume.VolumeHost) { func newTestHost(t *testing.T) (string, volume.VolumeHost) {
...@@ -67,18 +62,23 @@ func TestCanSupport(t *testing.T) { ...@@ -67,18 +62,23 @@ func TestCanSupport(t *testing.T) {
} }
// Expected command // Expected command
type expectedCommand []string type expectedCommand struct {
// The git command
type testScenario struct { cmd []string
name string // The dir of git command is executed
vol *v1.Volume dir string
repositoryDir string
expecteds []expectedCommand
isExpectedFailure bool
} }
func TestPlugin(t *testing.T) { func TestPlugin(t *testing.T) {
scenarios := []testScenario{ gitUrl := "https://github.com/kubernetes/kubernetes.git"
revision := "2a30ce65c5ab586b98916d83385c5983edd353a1"
scenarios := []struct {
name string
vol *v1.Volume
expecteds []expectedCommand
isExpectedFailure bool
}{
{ {
name: "target-dir", name: "target-dir",
vol: &v1.Volume{ vol: &v1.Volume{
...@@ -91,11 +91,19 @@ func TestPlugin(t *testing.T) { ...@@ -91,11 +91,19 @@ func TestPlugin(t *testing.T) {
}, },
}, },
}, },
repositoryDir: "target_dir",
expecteds: []expectedCommand{ expecteds: []expectedCommand{
[]string{"git", "-C", "volume-dir", "clone", gitUrl, "target_dir"}, {
[]string{"git", "-C", "volume-dir/target_dir", "checkout", revision}, cmd: []string{"git", "clone", gitUrl, "target_dir"},
[]string{"git", "-C", "volume-dir/target_dir", "reset", "--hard"}, dir: "",
},
{
cmd: []string{"git", "checkout", revision},
dir: "/target_dir",
},
{
cmd: []string{"git", "reset", "--hard"},
dir: "/target_dir",
},
}, },
isExpectedFailure: false, isExpectedFailure: false,
}, },
...@@ -110,9 +118,11 @@ func TestPlugin(t *testing.T) { ...@@ -110,9 +118,11 @@ func TestPlugin(t *testing.T) {
}, },
}, },
}, },
repositoryDir: "target_dir",
expecteds: []expectedCommand{ expecteds: []expectedCommand{
[]string{"git", "-C", "volume-dir", "clone", gitUrl, "target_dir"}, {
cmd: []string{"git", "clone", gitUrl, "target_dir"},
dir: "",
},
}, },
isExpectedFailure: false, isExpectedFailure: false,
}, },
...@@ -126,9 +136,11 @@ func TestPlugin(t *testing.T) { ...@@ -126,9 +136,11 @@ func TestPlugin(t *testing.T) {
}, },
}, },
}, },
repositoryDir: "kubernetes",
expecteds: []expectedCommand{ expecteds: []expectedCommand{
[]string{"git", "-C", "volume-dir", "clone", gitUrl}, {
cmd: []string{"git", "clone", gitUrl},
dir: "",
},
}, },
isExpectedFailure: false, isExpectedFailure: false,
}, },
...@@ -144,11 +156,19 @@ func TestPlugin(t *testing.T) { ...@@ -144,11 +156,19 @@ func TestPlugin(t *testing.T) {
}, },
}, },
}, },
repositoryDir: "kubernetes",
expecteds: []expectedCommand{ expecteds: []expectedCommand{
[]string{"git", "-C", "volume-dir", "clone", gitUrl}, {
[]string{"git", "-C", "volume-dir/kubernetes", "checkout", revision}, cmd: []string{"git", "clone", gitUrl},
[]string{"git", "-C", "volume-dir/kubernetes", "reset", "--hard"}, dir: "",
},
{
cmd: []string{"git", "checkout", revision},
dir: "/kubernetes",
},
{
cmd: []string{"git", "reset", "--hard"},
dir: "/kubernetes",
},
}, },
isExpectedFailure: false, isExpectedFailure: false,
}, },
...@@ -164,11 +184,19 @@ func TestPlugin(t *testing.T) { ...@@ -164,11 +184,19 @@ func TestPlugin(t *testing.T) {
}, },
}, },
}, },
repositoryDir: "",
expecteds: []expectedCommand{ expecteds: []expectedCommand{
[]string{"git", "-C", "volume-dir", "clone", gitUrl, "."}, {
[]string{"git", "-C", "volume-dir", "checkout", revision}, cmd: []string{"git", "clone", gitUrl, "."},
[]string{"git", "-C", "volume-dir", "reset", "--hard"}, dir: "",
},
{
cmd: []string{"git", "checkout", revision},
dir: "",
},
{
cmd: []string{"git", "reset", "--hard"},
dir: "",
},
}, },
isExpectedFailure: false, isExpectedFailure: false,
}, },
...@@ -186,7 +214,12 @@ func TestPlugin(t *testing.T) { ...@@ -186,7 +214,12 @@ func TestPlugin(t *testing.T) {
} }
func doTestPlugin(scenario testScenario, t *testing.T) []error { func doTestPlugin(scenario struct {
name string
vol *v1.Volume
expecteds []expectedCommand
isExpectedFailure bool
}, t *testing.T) []error {
allErrs := []error{} allErrs := []error{}
plugMgr := volume.VolumePluginMgr{} plugMgr := volume.VolumePluginMgr{}
...@@ -278,42 +311,73 @@ func doTestPlugin(scenario testScenario, t *testing.T) []error { ...@@ -278,42 +311,73 @@ func doTestPlugin(scenario testScenario, t *testing.T) []error {
return allErrs return allErrs
} }
func doTestSetUp(scenario testScenario, mounter volume.Mounter) []error { func doTestSetUp(scenario struct {
name string
vol *v1.Volume
expecteds []expectedCommand
isExpectedFailure bool
}, mounter volume.Mounter) []error {
expecteds := scenario.expecteds expecteds := scenario.expecteds
allErrs := []error{} allErrs := []error{}
var commandLog []expectedCommand // Construct combined outputs from expected commands
execCallback := func(cmd string, args ...string) ([]byte, error) { var fakeOutputs []fakeexec.FakeCombinedOutputAction
if len(args) < 2 { var fcmd fakeexec.FakeCmd
return nil, fmt.Errorf("expected at least 2 arguments, got %q", args) for _, expected := range expecteds {
} if expected.cmd[1] == "clone" {
if args[0] != "-C" { fakeOutputs = append(fakeOutputs, func() ([]byte, error) {
return nil, fmt.Errorf("expected the first argument to be \"-C\", got %q", args[0]) // git clone, it creates new dir/files
} os.MkdirAll(path.Join(fcmd.Dirs[0], expected.dir), 0750)
// command is 'git -C <dir> <command> <args> return []byte{}, nil
gitDir := args[1] })
gitCommand := args[2] } else {
if gitCommand == "clone" { // git checkout || git reset, they create nothing
// Clone creates a directory fakeOutputs = append(fakeOutputs, func() ([]byte, error) {
if scenario.repositoryDir != "" { return []byte{}, nil
os.MkdirAll(path.Join(gitDir, scenario.repositoryDir), 0750) })
}
} }
// add the command to log with de-randomized gitDir
args[1] = strings.Replace(gitDir, mounter.GetPath(), "volume-dir", 1)
cmdline := append([]string{cmd}, args...)
commandLog = append(commandLog, cmdline)
return []byte{}, nil
} }
fcmd = fakeexec.FakeCmd{
CombinedOutputScript: fakeOutputs,
}
// Construct fake exec outputs from fcmd
var fakeAction []fakeexec.FakeCommandAction
for i := 0; i < len(expecteds); i++ {
fakeAction = append(fakeAction, func(cmd string, args ...string) exec.Cmd {
return fakeexec.InitFakeCmd(&fcmd, cmd, args...)
})
}
fake := fakeexec.FakeExec{
CommandScript: fakeAction,
}
g := mounter.(*gitRepoVolumeMounter) g := mounter.(*gitRepoVolumeMounter)
g.mounter = &mount.FakeMounter{} g.exec = &fake
g.exec = mount.NewFakeExec(execCallback)
g.SetUp(nil) g.SetUp(nil)
if !reflect.DeepEqual(expecteds, commandLog) { if fake.CommandCalls != len(expecteds) {
allErrs = append(allErrs,
fmt.Errorf("unexpected command calls in scenario: expected %d, saw: %d", len(expecteds), fake.CommandCalls))
}
var expectedCmds [][]string
for _, expected := range expecteds {
expectedCmds = append(expectedCmds, expected.cmd)
}
if !reflect.DeepEqual(expectedCmds, fcmd.CombinedOutputLog) {
allErrs = append(allErrs,
fmt.Errorf("unexpected commands: %v, expected: %v", fcmd.CombinedOutputLog, expectedCmds))
}
var expectedPaths []string
for _, expected := range expecteds {
expectedPaths = append(expectedPaths, g.GetPath()+expected.dir)
}
if len(fcmd.Dirs) != len(expectedPaths) || !reflect.DeepEqual(expectedPaths, fcmd.Dirs) {
allErrs = append(allErrs, allErrs = append(allErrs,
fmt.Errorf("unexpected commands: %v, expected: %v", commandLog, expecteds)) fmt.Errorf("unexpected directories: %v, expected: %v", fcmd.Dirs, expectedPaths))
} }
return allErrs return allErrs
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment