2014-11-23 15:47:25 +00:00
|
|
|
/*
|
2015-05-01 16:19:44 +00:00
|
|
|
Copyright 2014 The Kubernetes Authors All rights reserved.
|
2014-11-23 15:47:25 +00:00
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package git_repo
|
|
|
|
|
|
|
|
import (
|
2015-10-10 10:10:45 +00:00
|
|
|
"fmt"
|
2014-11-23 15:47:25 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
"reflect"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
2015-08-05 22:03:47 +00:00
|
|
|
"k8s.io/kubernetes/pkg/api"
|
|
|
|
"k8s.io/kubernetes/pkg/types"
|
|
|
|
"k8s.io/kubernetes/pkg/util/exec"
|
|
|
|
"k8s.io/kubernetes/pkg/volume"
|
|
|
|
"k8s.io/kubernetes/pkg/volume/empty_dir"
|
2016-02-29 21:31:42 +00:00
|
|
|
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
2014-11-23 15:47:25 +00:00
|
|
|
)
|
|
|
|
|
2015-12-10 10:07:17 +00:00
|
|
|
func newTestHost(t *testing.T) (string, volume.VolumeHost) {
|
2014-11-23 15:47:25 +00:00
|
|
|
tempDir, err := ioutil.TempDir("/tmp", "git_repo_test.")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("can't make a temp rootdir: %v", err)
|
|
|
|
}
|
2016-02-29 21:31:42 +00:00
|
|
|
return tempDir, volumetest.NewFakeVolumeHost(tempDir, nil, empty_dir.ProbeVolumePlugins())
|
2014-11-23 15:47:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestCanSupport(t *testing.T) {
|
2015-03-19 05:18:31 +00:00
|
|
|
plugMgr := volume.VolumePluginMgr{}
|
2015-12-10 10:07:17 +00:00
|
|
|
_, host := newTestHost(t)
|
|
|
|
plugMgr.InitPlugins(ProbeVolumePlugins(), host)
|
2014-11-23 15:47:25 +00:00
|
|
|
|
|
|
|
plug, err := plugMgr.FindPluginByName("kubernetes.io/git-repo")
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("Can't find the plugin by name")
|
|
|
|
}
|
|
|
|
if plug.Name() != "kubernetes.io/git-repo" {
|
|
|
|
t.Errorf("Wrong name: %s", plug.Name())
|
|
|
|
}
|
2015-08-12 19:11:03 +00:00
|
|
|
if !plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{}}}}) {
|
2014-11-23 15:47:25 +00:00
|
|
|
t.Errorf("Expected true")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-10 10:10:45 +00:00
|
|
|
// Expected command
|
|
|
|
type expectedCommand struct {
|
|
|
|
// The git command
|
|
|
|
cmd []string
|
|
|
|
// The dir of git command is executed
|
|
|
|
dir string
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPlugin(t *testing.T) {
|
2015-12-11 20:27:24 +00:00
|
|
|
gitUrl := "https://github.com/kubernetes/kubernetes.git"
|
2015-10-10 10:10:45 +00:00
|
|
|
revision := "2a30ce65c5ab586b98916d83385c5983edd353a1"
|
|
|
|
|
|
|
|
scenarios := []struct {
|
|
|
|
name string
|
|
|
|
vol *api.Volume
|
|
|
|
expecteds []expectedCommand
|
|
|
|
isExpectedFailure bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "target-dir",
|
|
|
|
vol: &api.Volume{
|
|
|
|
Name: "vol1",
|
|
|
|
VolumeSource: api.VolumeSource{
|
|
|
|
GitRepo: &api.GitRepoVolumeSource{
|
|
|
|
Repository: gitUrl,
|
|
|
|
Revision: revision,
|
|
|
|
Directory: "target_dir",
|
|
|
|
},
|
|
|
|
},
|
2014-11-23 15:47:25 +00:00
|
|
|
},
|
2015-10-10 10:10:45 +00:00
|
|
|
expecteds: []expectedCommand{
|
|
|
|
{
|
|
|
|
cmd: []string{"git", "clone", gitUrl, "target_dir"},
|
|
|
|
dir: "",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cmd: []string{"git", "checkout", revision},
|
|
|
|
dir: "/target_dir",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cmd: []string{"git", "reset", "--hard"},
|
|
|
|
dir: "/target_dir",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
isExpectedFailure: false,
|
2014-11-23 15:47:25 +00:00
|
|
|
},
|
2015-10-10 10:10:45 +00:00
|
|
|
{
|
|
|
|
name: "target-dir-no-revision",
|
|
|
|
vol: &api.Volume{
|
|
|
|
Name: "vol1",
|
|
|
|
VolumeSource: api.VolumeSource{
|
|
|
|
GitRepo: &api.GitRepoVolumeSource{
|
|
|
|
Repository: gitUrl,
|
|
|
|
Directory: "target_dir",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expecteds: []expectedCommand{
|
|
|
|
{
|
|
|
|
cmd: []string{"git", "clone", gitUrl, "target_dir"},
|
|
|
|
dir: "",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
isExpectedFailure: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "only-git-clone",
|
|
|
|
vol: &api.Volume{
|
|
|
|
Name: "vol1",
|
|
|
|
VolumeSource: api.VolumeSource{
|
|
|
|
GitRepo: &api.GitRepoVolumeSource{
|
|
|
|
Repository: gitUrl,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expecteds: []expectedCommand{
|
|
|
|
{
|
|
|
|
cmd: []string{"git", "clone", gitUrl},
|
|
|
|
dir: "",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
isExpectedFailure: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no-target-dir",
|
|
|
|
vol: &api.Volume{
|
|
|
|
Name: "vol1",
|
|
|
|
VolumeSource: api.VolumeSource{
|
|
|
|
GitRepo: &api.GitRepoVolumeSource{
|
|
|
|
Repository: gitUrl,
|
|
|
|
Revision: revision,
|
|
|
|
Directory: "",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expecteds: []expectedCommand{
|
|
|
|
{
|
|
|
|
cmd: []string{"git", "clone", gitUrl},
|
|
|
|
dir: "",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cmd: []string{"git", "checkout", revision},
|
|
|
|
dir: "/kubernetes",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cmd: []string{"git", "reset", "--hard"},
|
|
|
|
dir: "/kubernetes",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
isExpectedFailure: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "current-dir",
|
|
|
|
vol: &api.Volume{
|
|
|
|
Name: "vol1",
|
|
|
|
VolumeSource: api.VolumeSource{
|
|
|
|
GitRepo: &api.GitRepoVolumeSource{
|
|
|
|
Repository: gitUrl,
|
|
|
|
Revision: revision,
|
|
|
|
Directory: ".",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expecteds: []expectedCommand{
|
|
|
|
{
|
|
|
|
cmd: []string{"git", "clone", gitUrl, "."},
|
|
|
|
dir: "",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cmd: []string{"git", "checkout", revision},
|
|
|
|
dir: "",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cmd: []string{"git", "reset", "--hard"},
|
|
|
|
dir: "",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
isExpectedFailure: false,
|
2014-11-23 15:47:25 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2015-10-10 10:10:45 +00:00
|
|
|
for _, scenario := range scenarios {
|
|
|
|
allErrs := doTestPlugin(scenario, t)
|
|
|
|
if len(allErrs) == 0 && scenario.isExpectedFailure {
|
|
|
|
t.Errorf("Unexpected success for scenario: %s", scenario.name)
|
|
|
|
}
|
|
|
|
if len(allErrs) > 0 && !scenario.isExpectedFailure {
|
|
|
|
t.Errorf("Unexpected failure for scenario: %s - %+v", scenario.name, allErrs)
|
|
|
|
}
|
2014-11-23 15:47:25 +00:00
|
|
|
}
|
2015-10-10 10:10:45 +00:00
|
|
|
|
2014-11-23 15:47:25 +00:00
|
|
|
}
|
|
|
|
|
2015-10-10 10:10:45 +00:00
|
|
|
func doTestPlugin(scenario struct {
|
|
|
|
name string
|
|
|
|
vol *api.Volume
|
|
|
|
expecteds []expectedCommand
|
|
|
|
isExpectedFailure bool
|
|
|
|
}, t *testing.T) []error {
|
|
|
|
allErrs := []error{}
|
|
|
|
|
2015-03-19 05:18:31 +00:00
|
|
|
plugMgr := volume.VolumePluginMgr{}
|
2015-12-10 10:07:17 +00:00
|
|
|
rootDir, host := newTestHost(t)
|
|
|
|
plugMgr.InitPlugins(ProbeVolumePlugins(), host)
|
2014-11-23 15:47:25 +00:00
|
|
|
|
|
|
|
plug, err := plugMgr.FindPluginByName("kubernetes.io/git-repo")
|
|
|
|
if err != nil {
|
2015-10-10 10:10:45 +00:00
|
|
|
allErrs = append(allErrs,
|
|
|
|
fmt.Errorf("Can't find the plugin by name"))
|
|
|
|
return allErrs
|
2014-11-23 15:47:25 +00:00
|
|
|
}
|
2015-05-11 00:12:57 +00:00
|
|
|
pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}}
|
2015-10-10 10:10:45 +00:00
|
|
|
builder, err := plug.NewBuilder(volume.NewSpecFromVolume(scenario.vol), pod, volume.VolumeOptions{RootContext: ""})
|
|
|
|
|
2014-11-23 15:47:25 +00:00
|
|
|
if err != nil {
|
2015-10-10 10:10:45 +00:00
|
|
|
allErrs = append(allErrs,
|
|
|
|
fmt.Errorf("Failed to make a new Builder: %v", err))
|
|
|
|
return allErrs
|
2014-11-23 15:47:25 +00:00
|
|
|
}
|
|
|
|
if builder == nil {
|
2015-10-10 10:10:45 +00:00
|
|
|
allErrs = append(allErrs,
|
|
|
|
fmt.Errorf("Got a nil Builder"))
|
|
|
|
return allErrs
|
2014-11-23 15:47:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
path := builder.GetPath()
|
2015-12-10 10:07:17 +00:00
|
|
|
suffix := fmt.Sprintf("pods/poduid/volumes/kubernetes.io~git-repo/%v", scenario.vol.Name)
|
|
|
|
if !strings.HasSuffix(path, suffix) {
|
2015-10-10 10:10:45 +00:00
|
|
|
allErrs = append(allErrs,
|
|
|
|
fmt.Errorf("Got unexpected path: %s", path))
|
|
|
|
return allErrs
|
2014-11-23 15:47:25 +00:00
|
|
|
}
|
|
|
|
|
2015-10-10 10:10:45 +00:00
|
|
|
// Test setUp()
|
|
|
|
setUpErrs := doTestSetUp(scenario, builder)
|
|
|
|
allErrs = append(allErrs, setUpErrs...)
|
|
|
|
|
2014-11-23 15:47:25 +00:00
|
|
|
if _, err := os.Stat(path); err != nil {
|
|
|
|
if os.IsNotExist(err) {
|
2015-10-10 10:10:45 +00:00
|
|
|
allErrs = append(allErrs,
|
|
|
|
fmt.Errorf("SetUp() failed, volume path not created: %s", path))
|
|
|
|
return allErrs
|
2014-11-23 15:47:25 +00:00
|
|
|
} else {
|
2015-10-10 10:10:45 +00:00
|
|
|
allErrs = append(allErrs,
|
|
|
|
fmt.Errorf("SetUp() failed: %v", err))
|
|
|
|
return allErrs
|
2014-11-23 15:47:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-14 07:32:37 +00:00
|
|
|
// gitRepo volume should create its own empty wrapper path
|
2015-12-10 10:07:17 +00:00
|
|
|
podWrapperMetadataDir := fmt.Sprintf("%v/pods/poduid/plugins/kubernetes.io~empty-dir/wrapped_%v", rootDir, scenario.vol.Name)
|
|
|
|
|
|
|
|
if _, err := os.Stat(podWrapperMetadataDir); err != nil {
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
allErrs = append(allErrs,
|
|
|
|
fmt.Errorf("SetUp() failed, empty-dir wrapper path is not created: %s", podWrapperMetadataDir))
|
|
|
|
} else {
|
|
|
|
allErrs = append(allErrs,
|
|
|
|
fmt.Errorf("SetUp() failed: %v", err))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-14 09:51:40 +00:00
|
|
|
cleaner, err := plug.NewCleaner("vol1", types.UID("poduid"))
|
2014-11-23 15:47:25 +00:00
|
|
|
if err != nil {
|
2015-10-10 10:10:45 +00:00
|
|
|
allErrs = append(allErrs,
|
|
|
|
fmt.Errorf("Failed to make a new Cleaner: %v", err))
|
|
|
|
return allErrs
|
2014-11-23 15:47:25 +00:00
|
|
|
}
|
|
|
|
if cleaner == nil {
|
2015-10-10 10:10:45 +00:00
|
|
|
allErrs = append(allErrs,
|
|
|
|
fmt.Errorf("Got a nil Cleaner"))
|
|
|
|
return allErrs
|
2014-11-23 15:47:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := cleaner.TearDown(); err != nil {
|
2015-10-10 10:10:45 +00:00
|
|
|
allErrs = append(allErrs,
|
|
|
|
fmt.Errorf("Expected success, got: %v", err))
|
|
|
|
return allErrs
|
2014-11-23 15:47:25 +00:00
|
|
|
}
|
|
|
|
if _, err := os.Stat(path); err == nil {
|
2015-10-10 10:10:45 +00:00
|
|
|
allErrs = append(allErrs,
|
|
|
|
fmt.Errorf("TearDown() failed, volume path still exists: %s", path))
|
2014-11-23 15:47:25 +00:00
|
|
|
} else if !os.IsNotExist(err) {
|
2015-10-10 10:10:45 +00:00
|
|
|
allErrs = append(allErrs,
|
|
|
|
fmt.Errorf("SetUp() failed: %v", err))
|
|
|
|
}
|
|
|
|
return allErrs
|
|
|
|
}
|
|
|
|
|
|
|
|
func doTestSetUp(scenario struct {
|
|
|
|
name string
|
|
|
|
vol *api.Volume
|
|
|
|
expecteds []expectedCommand
|
|
|
|
isExpectedFailure bool
|
|
|
|
}, builder volume.Builder) []error {
|
|
|
|
expecteds := scenario.expecteds
|
|
|
|
allErrs := []error{}
|
|
|
|
|
|
|
|
// Construct combined outputs from expected commands
|
|
|
|
var fakeOutputs []exec.FakeCombinedOutputAction
|
|
|
|
var fcmd exec.FakeCmd
|
|
|
|
for _, expected := range expecteds {
|
|
|
|
if expected.cmd[1] == "clone" {
|
|
|
|
fakeOutputs = append(fakeOutputs, func() ([]byte, error) {
|
|
|
|
// git clone, it creates new dir/files
|
|
|
|
os.MkdirAll(path.Join(fcmd.Dirs[0], expected.dir), 0750)
|
|
|
|
return []byte{}, nil
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
// git checkout || git reset, they create nothing
|
|
|
|
fakeOutputs = append(fakeOutputs, func() ([]byte, error) {
|
|
|
|
return []byte{}, nil
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fcmd = exec.FakeCmd{
|
|
|
|
CombinedOutputScript: fakeOutputs,
|
|
|
|
}
|
|
|
|
|
|
|
|
// Construct fake exec outputs from fcmd
|
|
|
|
var fakeAction []exec.FakeCommandAction
|
|
|
|
for i := 0; i < len(expecteds); i++ {
|
|
|
|
fakeAction = append(fakeAction, func(cmd string, args ...string) exec.Cmd {
|
|
|
|
return exec.InitFakeCmd(&fcmd, cmd, args...)
|
|
|
|
})
|
|
|
|
|
2014-11-23 15:47:25 +00:00
|
|
|
}
|
2015-10-10 10:10:45 +00:00
|
|
|
fake := exec.FakeExec{
|
|
|
|
CommandScript: fakeAction,
|
|
|
|
}
|
|
|
|
|
|
|
|
g := builder.(*gitRepoVolumeBuilder)
|
|
|
|
g.exec = &fake
|
|
|
|
|
2015-12-18 15:55:11 +00:00
|
|
|
g.SetUp(nil)
|
2015-10-10 10:10:45 +00:00
|
|
|
|
|
|
|
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,
|
|
|
|
fmt.Errorf("unexpected directories: %v, expected: %v", fcmd.Dirs, expectedPaths))
|
|
|
|
}
|
|
|
|
|
|
|
|
return allErrs
|
2014-11-23 15:47:25 +00:00
|
|
|
}
|