Add directory in GitRepo and updated tests.
Update validate and gitRepo Update generated code
This commit is contained in:
parent
f4ea77bede
commit
70a9c0bf56
@ -13251,8 +13251,7 @@
|
|||||||
"id": "v1.GitRepoVolumeSource",
|
"id": "v1.GitRepoVolumeSource",
|
||||||
"description": "GitRepoVolumeSource represents a volume that is pulled from git when the pod is created.",
|
"description": "GitRepoVolumeSource represents a volume that is pulled from git when the pod is created.",
|
||||||
"required": [
|
"required": [
|
||||||
"repository",
|
"repository"
|
||||||
"revision"
|
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"repository": {
|
"repository": {
|
||||||
@ -13262,6 +13261,10 @@
|
|||||||
"revision": {
|
"revision": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Commit hash for the specified revision."
|
"description": "Commit hash for the specified revision."
|
||||||
|
},
|
||||||
|
"directory": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Target directory name. Must not contain or start with '..'. If '.' is supplied, the volume directory will be the git repository. Otherwise, if specified, the volume will contain the git repository in the subdirectory with the given name."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -3244,8 +3244,7 @@
|
|||||||
"id": "v1.GitRepoVolumeSource",
|
"id": "v1.GitRepoVolumeSource",
|
||||||
"description": "GitRepoVolumeSource represents a volume that is pulled from git when the pod is created.",
|
"description": "GitRepoVolumeSource represents a volume that is pulled from git when the pod is created.",
|
||||||
"required": [
|
"required": [
|
||||||
"repository",
|
"repository"
|
||||||
"revision"
|
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"repository": {
|
"repository": {
|
||||||
@ -3255,6 +3254,10 @@
|
|||||||
"revision": {
|
"revision": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Commit hash for the specified revision."
|
"description": "Commit hash for the specified revision."
|
||||||
|
},
|
||||||
|
"directory": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Target directory name. Must not contain or start with '..'. If '.' is supplied, the volume directory will be the git repository. Otherwise, if specified, the volume will contain the git repository in the subdirectory with the given name."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1436,7 +1436,14 @@ Both these may change in the future. Incoming requests are matched against the h
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">revision</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">revision</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Commit hash for the specified revision.</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Commit hash for the specified revision.</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">directory</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Target directory name. Must not contain or start with <em>..</em>. If <em>.</em> is supplied, the volume directory will be the git repository. Otherwise, if specified, the volume will contain the git repository in the subdirectory with the given name.</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
||||||
<td class="tableblock halign-left valign-top"></td>
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -4261,7 +4268,7 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
|
|||||||
</div>
|
</div>
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<div id="footer-text">
|
<div id="footer-text">
|
||||||
Last updated 2015-11-20 03:20:06 UTC
|
Last updated 2015-11-29 16:46:22 UTC
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@ -1321,7 +1321,14 @@ Examples:<br>
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">revision</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">revision</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Commit hash for the specified revision.</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Commit hash for the specified revision.</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">directory</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Target directory name. Must not contain or start with <em>..</em>. If <em>.</em> is supplied, the volume directory will be the git repository. Otherwise, if specified, the volume will contain the git repository in the subdirectory with the given name.</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
||||||
<td class="tableblock halign-left valign-top"></td>
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -6894,7 +6901,7 @@ The resulting set of endpoints can be viewed as:<br>
|
|||||||
</div>
|
</div>
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<div id="footer-text">
|
<div id="footer-text">
|
||||||
Last updated 2015-11-20 03:19:59 UTC
|
Last updated 2015-11-29 16:46:14 UTC
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@ -587,6 +587,7 @@ func deepCopy_api_GCEPersistentDiskVolumeSource(in GCEPersistentDiskVolumeSource
|
|||||||
func deepCopy_api_GitRepoVolumeSource(in GitRepoVolumeSource, out *GitRepoVolumeSource, c *conversion.Cloner) error {
|
func deepCopy_api_GitRepoVolumeSource(in GitRepoVolumeSource, out *GitRepoVolumeSource, c *conversion.Cloner) error {
|
||||||
out.Repository = in.Repository
|
out.Repository = in.Repository
|
||||||
out.Revision = in.Revision
|
out.Revision = in.Revision
|
||||||
|
out.Directory = in.Directory
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -502,7 +502,12 @@ type GitRepoVolumeSource struct {
|
|||||||
// Repository URL
|
// Repository URL
|
||||||
Repository string `json:"repository"`
|
Repository string `json:"repository"`
|
||||||
// Commit hash, this is optional
|
// Commit hash, this is optional
|
||||||
Revision string `json:"revision"`
|
Revision string `json:"revision,omitempty"`
|
||||||
|
// Clone target, this is optional
|
||||||
|
// Must not contain or start with '..'. If '.' is supplied, the volume directory will be the
|
||||||
|
// git repository. Otherwise, if specified, the volume will contain the git repository in
|
||||||
|
// the subdirectory with the given name.
|
||||||
|
Directory string `json:"directory,omitempty"`
|
||||||
// TODO: Consider credentials here.
|
// TODO: Consider credentials here.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -826,6 +826,7 @@ func autoconvert_api_GitRepoVolumeSource_To_v1_GitRepoVolumeSource(in *api.GitRe
|
|||||||
}
|
}
|
||||||
out.Repository = in.Repository
|
out.Repository = in.Repository
|
||||||
out.Revision = in.Revision
|
out.Revision = in.Revision
|
||||||
|
out.Directory = in.Directory
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3851,6 +3852,7 @@ func autoconvert_v1_GitRepoVolumeSource_To_api_GitRepoVolumeSource(in *GitRepoVo
|
|||||||
}
|
}
|
||||||
out.Repository = in.Repository
|
out.Repository = in.Repository
|
||||||
out.Revision = in.Revision
|
out.Revision = in.Revision
|
||||||
|
out.Directory = in.Directory
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -623,6 +623,7 @@ func deepCopy_v1_GCEPersistentDiskVolumeSource(in GCEPersistentDiskVolumeSource,
|
|||||||
func deepCopy_v1_GitRepoVolumeSource(in GitRepoVolumeSource, out *GitRepoVolumeSource, c *conversion.Cloner) error {
|
func deepCopy_v1_GitRepoVolumeSource(in GitRepoVolumeSource, out *GitRepoVolumeSource, c *conversion.Cloner) error {
|
||||||
out.Repository = in.Repository
|
out.Repository = in.Repository
|
||||||
out.Revision = in.Revision
|
out.Revision = in.Revision
|
||||||
|
out.Directory = in.Directory
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -673,7 +673,12 @@ type GitRepoVolumeSource struct {
|
|||||||
// Repository URL
|
// Repository URL
|
||||||
Repository string `json:"repository"`
|
Repository string `json:"repository"`
|
||||||
// Commit hash for the specified revision.
|
// Commit hash for the specified revision.
|
||||||
Revision string `json:"revision"`
|
Revision string `json:"revision,omitempty"`
|
||||||
|
// Target directory name.
|
||||||
|
// Must not contain or start with '..'. If '.' is supplied, the volume directory will be the
|
||||||
|
// git repository. Otherwise, if specified, the volume will contain the git repository in
|
||||||
|
// the subdirectory with the given name.
|
||||||
|
Directory string `json:"directory,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SecretVolumeSource adapts a Secret into a VolumeSource.
|
// SecretVolumeSource adapts a Secret into a VolumeSource.
|
||||||
|
@ -416,6 +416,7 @@ var map_GitRepoVolumeSource = map[string]string{
|
|||||||
"": "GitRepoVolumeSource represents a volume that is pulled from git when the pod is created.",
|
"": "GitRepoVolumeSource represents a volume that is pulled from git when the pod is created.",
|
||||||
"repository": "Repository URL",
|
"repository": "Repository URL",
|
||||||
"revision": "Commit hash for the specified revision.",
|
"revision": "Commit hash for the specified revision.",
|
||||||
|
"directory": "Target directory name. Must not contain or start with '..'. If '.' is supplied, the volume directory will be the git repository. Otherwise, if specified, the volume will contain the git repository in the subdirectory with the given name.",
|
||||||
}
|
}
|
||||||
|
|
||||||
func (GitRepoVolumeSource) SwaggerDoc() map[string]string {
|
func (GitRepoVolumeSource) SwaggerDoc() map[string]string {
|
||||||
|
@ -440,9 +440,12 @@ func validateHostPathVolumeSource(hostPath *api.HostPathVolumeSource) validation
|
|||||||
|
|
||||||
func validateGitRepoVolumeSource(gitRepo *api.GitRepoVolumeSource) validation.ErrorList {
|
func validateGitRepoVolumeSource(gitRepo *api.GitRepoVolumeSource) validation.ErrorList {
|
||||||
allErrs := validation.ErrorList{}
|
allErrs := validation.ErrorList{}
|
||||||
if gitRepo.Repository == "" {
|
if len(gitRepo.Repository) == 0 {
|
||||||
allErrs = append(allErrs, validation.NewRequiredError("repository"))
|
allErrs = append(allErrs, validation.NewRequiredError("repository"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pathErrs := validateVolumeSourcePath(gitRepo.Directory, "directory")
|
||||||
|
allErrs = append(allErrs, pathErrs...)
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -570,23 +573,34 @@ func validateDownwardAPIVolumeSource(downwardAPIVolume *api.DownwardAPIVolumeSou
|
|||||||
if len(downwardAPIVolumeFile.Path) == 0 {
|
if len(downwardAPIVolumeFile.Path) == 0 {
|
||||||
allErrs = append(allErrs, validation.NewRequiredError("path"))
|
allErrs = append(allErrs, validation.NewRequiredError("path"))
|
||||||
}
|
}
|
||||||
if path.IsAbs(downwardAPIVolumeFile.Path) {
|
allErrs = append(allErrs, validateVolumeSourcePath(downwardAPIVolumeFile.Path, "path")...)
|
||||||
allErrs = append(allErrs, validation.NewForbiddenError("path", "must not be an absolute path"))
|
|
||||||
}
|
|
||||||
items := strings.Split(downwardAPIVolumeFile.Path, string(os.PathSeparator))
|
|
||||||
for _, item := range items {
|
|
||||||
if item == ".." {
|
|
||||||
allErrs = append(allErrs, validation.NewInvalidError("path", downwardAPIVolumeFile.Path, "must not contain \"..\"."))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(items[0], "..") && len(items[0]) > 2 {
|
|
||||||
allErrs = append(allErrs, validation.NewInvalidError("path", downwardAPIVolumeFile.Path, "must not start with \"..\"."))
|
|
||||||
}
|
|
||||||
allErrs = append(allErrs, validateObjectFieldSelector(&downwardAPIVolumeFile.FieldRef, &validDownwardAPIFieldPathExpressions).Prefix("FieldRef")...)
|
allErrs = append(allErrs, validateObjectFieldSelector(&downwardAPIVolumeFile.FieldRef, &validDownwardAPIFieldPathExpressions).Prefix("FieldRef")...)
|
||||||
}
|
}
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This validate will make sure targetPath:
|
||||||
|
// 1. is not abs path
|
||||||
|
// 2. does not contain '..'
|
||||||
|
// 3. does not start with '..'
|
||||||
|
func validateVolumeSourcePath(targetPath string, field string) validation.ErrorList {
|
||||||
|
allErrs := validation.ErrorList{}
|
||||||
|
if path.IsAbs(targetPath) {
|
||||||
|
allErrs = append(allErrs, validation.NewForbiddenError(field, "must not be an absolute path"))
|
||||||
|
}
|
||||||
|
// TODO assume OS of api server & nodes are the same for now
|
||||||
|
items := strings.Split(targetPath, string(os.PathSeparator))
|
||||||
|
|
||||||
|
for _, item := range items {
|
||||||
|
if item == ".." {
|
||||||
|
allErrs = append(allErrs, validation.NewInvalidError(field, targetPath, "must not contain \"..\""))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(items[0], "..") && len(items[0]) > 2 {
|
||||||
|
allErrs = append(allErrs, validation.NewInvalidError(field, targetPath, "must not start with \"..\""))
|
||||||
|
}
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
func validateRBD(rbd *api.RBDVolumeSource) validation.ErrorList {
|
func validateRBD(rbd *api.RBDVolumeSource) validation.ErrorList {
|
||||||
allErrs := validation.ErrorList{}
|
allErrs := validation.ErrorList{}
|
||||||
if len(rbd.CephMonitors) == 0 {
|
if len(rbd.CephMonitors) == 0 {
|
||||||
|
@ -453,7 +453,8 @@ func TestValidateVolumes(t *testing.T) {
|
|||||||
{Name: "empty", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
|
{Name: "empty", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
|
||||||
{Name: "gcepd", VolumeSource: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false}}},
|
{Name: "gcepd", VolumeSource: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false}}},
|
||||||
{Name: "awsebs", VolumeSource: api.VolumeSource{AWSElasticBlockStore: &api.AWSElasticBlockStoreVolumeSource{VolumeID: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false}}},
|
{Name: "awsebs", VolumeSource: api.VolumeSource{AWSElasticBlockStore: &api.AWSElasticBlockStoreVolumeSource{VolumeID: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false}}},
|
||||||
{Name: "gitrepo", VolumeSource: api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{Repository: "my-repo", Revision: "hashstring"}}},
|
{Name: "gitrepo", VolumeSource: api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{Repository: "my-repo", Revision: "hashstring", Directory: "target"}}},
|
||||||
|
{Name: "gitrepodot", VolumeSource: api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{Repository: "my-repo", Directory: "."}}},
|
||||||
{Name: "iscsidisk", VolumeSource: api.VolumeSource{ISCSI: &api.ISCSIVolumeSource{TargetPortal: "127.0.0.1", IQN: "iqn.2015-02.example.com:test", Lun: 1, FSType: "ext4", ReadOnly: false}}},
|
{Name: "iscsidisk", VolumeSource: api.VolumeSource{ISCSI: &api.ISCSIVolumeSource{TargetPortal: "127.0.0.1", IQN: "iqn.2015-02.example.com:test", Lun: 1, FSType: "ext4", ReadOnly: false}}},
|
||||||
{Name: "secret", VolumeSource: api.VolumeSource{Secret: &api.SecretVolumeSource{SecretName: "my-secret"}}},
|
{Name: "secret", VolumeSource: api.VolumeSource{Secret: &api.SecretVolumeSource{SecretName: "my-secret"}}},
|
||||||
{Name: "glusterfs", VolumeSource: api.VolumeSource{Glusterfs: &api.GlusterfsVolumeSource{EndpointsName: "host1", Path: "path", ReadOnly: false}}},
|
{Name: "glusterfs", VolumeSource: api.VolumeSource{Glusterfs: &api.GlusterfsVolumeSource{EndpointsName: "host1", Path: "path", ReadOnly: false}}},
|
||||||
@ -505,6 +506,9 @@ func TestValidateVolumes(t *testing.T) {
|
|||||||
emptyMon := api.VolumeSource{RBD: &api.RBDVolumeSource{CephMonitors: []string{}, RBDImage: "bar", FSType: "ext4"}}
|
emptyMon := api.VolumeSource{RBD: &api.RBDVolumeSource{CephMonitors: []string{}, RBDImage: "bar", FSType: "ext4"}}
|
||||||
emptyImage := api.VolumeSource{RBD: &api.RBDVolumeSource{CephMonitors: []string{"foo"}, RBDImage: "", FSType: "ext4"}}
|
emptyImage := api.VolumeSource{RBD: &api.RBDVolumeSource{CephMonitors: []string{"foo"}, RBDImage: "", FSType: "ext4"}}
|
||||||
emptyCephFSMon := api.VolumeSource{CephFS: &api.CephFSVolumeSource{Monitors: []string{}}}
|
emptyCephFSMon := api.VolumeSource{CephFS: &api.CephFSVolumeSource{Monitors: []string{}}}
|
||||||
|
startsWithDots := api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{Repository: "foo", Directory: "..dots/bar"}}
|
||||||
|
containsDots := api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{Repository: "foo", Directory: "dots/../bar"}}
|
||||||
|
absPath := api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{Repository: "foo", Directory: "/abstarget"}}
|
||||||
emptyPathName := api.VolumeSource{DownwardAPI: &api.DownwardAPIVolumeSource{Items: []api.DownwardAPIVolumeFile{{Path: "",
|
emptyPathName := api.VolumeSource{DownwardAPI: &api.DownwardAPIVolumeSource{Items: []api.DownwardAPIVolumeFile{{Path: "",
|
||||||
FieldRef: api.ObjectFieldSelector{
|
FieldRef: api.ObjectFieldSelector{
|
||||||
APIVersion: "v1",
|
APIVersion: "v1",
|
||||||
@ -553,12 +557,15 @@ func TestValidateVolumes(t *testing.T) {
|
|||||||
"empty cephfs mon": {[]api.Volume{{Name: "badmon", VolumeSource: emptyCephFSMon}}, validation.ErrorTypeRequired, "[0].source.cephfs.monitors", ""},
|
"empty cephfs mon": {[]api.Volume{{Name: "badmon", VolumeSource: emptyCephFSMon}}, validation.ErrorTypeRequired, "[0].source.cephfs.monitors", ""},
|
||||||
"empty metatada path": {[]api.Volume{{Name: "emptyname", VolumeSource: emptyPathName}}, validation.ErrorTypeRequired, "[0].source.downwardApi.path", ""},
|
"empty metatada path": {[]api.Volume{{Name: "emptyname", VolumeSource: emptyPathName}}, validation.ErrorTypeRequired, "[0].source.downwardApi.path", ""},
|
||||||
"absolute path": {[]api.Volume{{Name: "absolutepath", VolumeSource: absolutePathName}}, validation.ErrorTypeForbidden, "[0].source.downwardApi.path", ""},
|
"absolute path": {[]api.Volume{{Name: "absolutepath", VolumeSource: absolutePathName}}, validation.ErrorTypeForbidden, "[0].source.downwardApi.path", ""},
|
||||||
"dot dot path": {[]api.Volume{{Name: "dotdotpath", VolumeSource: dotDotInPath}}, validation.ErrorTypeInvalid, "[0].source.downwardApi.path", "must not contain \"..\"."},
|
"dot dot path": {[]api.Volume{{Name: "dotdotpath", VolumeSource: dotDotInPath}}, validation.ErrorTypeInvalid, "[0].source.downwardApi.path", "must not contain \"..\""},
|
||||||
"dot dot file name": {[]api.Volume{{Name: "dotdotfilename", VolumeSource: dotDotPathName}}, validation.ErrorTypeInvalid, "[0].source.downwardApi.path", "must not start with \"..\"."},
|
"dot dot file name": {[]api.Volume{{Name: "dotdotfilename", VolumeSource: dotDotPathName}}, validation.ErrorTypeInvalid, "[0].source.downwardApi.path", "must not start with \"..\""},
|
||||||
"dot dot first level dirent": {[]api.Volume{{Name: "dotdotdirfilename", VolumeSource: dotDotFirstLevelDirent}}, validation.ErrorTypeInvalid, "[0].source.downwardApi.path", "must not start with \"..\"."},
|
"dot dot first level dirent": {[]api.Volume{{Name: "dotdotdirfilename", VolumeSource: dotDotFirstLevelDirent}}, validation.ErrorTypeInvalid, "[0].source.downwardApi.path", "must not start with \"..\""},
|
||||||
"empty wwn": {[]api.Volume{{Name: "badimage", VolumeSource: zeroWWN}}, validation.ErrorTypeRequired, "[0].source.fc.targetWWNs", ""},
|
"empty wwn": {[]api.Volume{{Name: "badimage", VolumeSource: zeroWWN}}, validation.ErrorTypeRequired, "[0].source.fc.targetWWNs", ""},
|
||||||
"empty lun": {[]api.Volume{{Name: "badimage", VolumeSource: emptyLun}}, validation.ErrorTypeRequired, "[0].source.fc.lun", ""},
|
"empty lun": {[]api.Volume{{Name: "badimage", VolumeSource: emptyLun}}, validation.ErrorTypeRequired, "[0].source.fc.lun", ""},
|
||||||
"slash in datasetName": {[]api.Volume{{Name: "slashinname", VolumeSource: slashInName}}, validation.ErrorTypeInvalid, "[0].source.flocker.datasetName", "must not contain '/'"},
|
"slash in datasetName": {[]api.Volume{{Name: "slashinname", VolumeSource: slashInName}}, validation.ErrorTypeInvalid, "[0].source.flocker.datasetName", "must not contain '/'"},
|
||||||
|
"starts with '..'": {[]api.Volume{{Name: "badprefix", VolumeSource: startsWithDots}}, validation.ErrorTypeInvalid, "[0].source.gitRepo.directory", "must not start with \"..\""},
|
||||||
|
"contains '..'": {[]api.Volume{{Name: "containsdots", VolumeSource: containsDots}}, validation.ErrorTypeInvalid, "[0].source.gitRepo.directory", "must not contain \"..\""},
|
||||||
|
"absolute target": {[]api.Volume{{Name: "absolutetarget", VolumeSource: absPath}}, validation.ErrorTypeForbidden, "[0].source.gitRepo.directory", ""},
|
||||||
}
|
}
|
||||||
for k, v := range errorCases {
|
for k, v := range errorCases {
|
||||||
_, errs := validateVolumes(v.V)
|
_, errs := validateVolumes(v.V)
|
||||||
|
@ -290,6 +290,7 @@ func deepCopy_api_GCEPersistentDiskVolumeSource(in api.GCEPersistentDiskVolumeSo
|
|||||||
func deepCopy_api_GitRepoVolumeSource(in api.GitRepoVolumeSource, out *api.GitRepoVolumeSource, c *conversion.Cloner) error {
|
func deepCopy_api_GitRepoVolumeSource(in api.GitRepoVolumeSource, out *api.GitRepoVolumeSource, c *conversion.Cloner) error {
|
||||||
out.Repository = in.Repository
|
out.Repository = in.Repository
|
||||||
out.Revision = in.Revision
|
out.Revision = in.Revision
|
||||||
|
out.Directory = in.Directory
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,6 +397,7 @@ func autoconvert_api_GitRepoVolumeSource_To_v1_GitRepoVolumeSource(in *api.GitRe
|
|||||||
}
|
}
|
||||||
out.Repository = in.Repository
|
out.Repository = in.Repository
|
||||||
out.Revision = in.Revision
|
out.Revision = in.Revision
|
||||||
|
out.Directory = in.Directory
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1456,6 +1457,7 @@ func autoconvert_v1_GitRepoVolumeSource_To_api_GitRepoVolumeSource(in *v1.GitRep
|
|||||||
}
|
}
|
||||||
out.Repository = in.Repository
|
out.Repository = in.Repository
|
||||||
out.Revision = in.Revision
|
out.Revision = in.Revision
|
||||||
|
out.Directory = in.Directory
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,6 +326,7 @@ func deepCopy_v1_GCEPersistentDiskVolumeSource(in v1.GCEPersistentDiskVolumeSour
|
|||||||
func deepCopy_v1_GitRepoVolumeSource(in v1.GitRepoVolumeSource, out *v1.GitRepoVolumeSource, c *conversion.Cloner) error {
|
func deepCopy_v1_GitRepoVolumeSource(in v1.GitRepoVolumeSource, out *v1.GitRepoVolumeSource, c *conversion.Cloner) error {
|
||||||
out.Repository = in.Repository
|
out.Repository = in.Repository
|
||||||
out.Revision = in.Revision
|
out.Revision = in.Revision
|
||||||
|
out.Directory = in.Directory
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"path"
|
"path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/types"
|
"k8s.io/kubernetes/pkg/types"
|
||||||
@ -66,6 +67,7 @@ func (plugin *gitRepoPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, opts vo
|
|||||||
pod: *pod,
|
pod: *pod,
|
||||||
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,
|
||||||
exec: exec.New(),
|
exec: exec.New(),
|
||||||
opts: opts,
|
opts: opts,
|
||||||
}, nil
|
}, nil
|
||||||
@ -103,6 +105,7 @@ type gitRepoVolumeBuilder struct {
|
|||||||
pod api.Pod
|
pod api.Pod
|
||||||
source string
|
source string
|
||||||
revision string
|
revision string
|
||||||
|
target string
|
||||||
exec exec.Interface
|
exec exec.Interface
|
||||||
opts volume.VolumeOptions
|
opts volume.VolumeOptions
|
||||||
}
|
}
|
||||||
@ -143,24 +146,41 @@ func (b *gitRepoVolumeBuilder) SetUpAt(dir string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if output, err := b.execCommand("git", []string{"clone", b.source}, dir); err != nil {
|
args := []string{"clone", b.source}
|
||||||
return fmt.Errorf("failed to exec 'git clone %s': %s: %v", b.source, output, err)
|
|
||||||
|
if len(b.target) != 0 {
|
||||||
|
args = append(args, b.target)
|
||||||
|
}
|
||||||
|
if output, err := b.execCommand("git", args, dir); err != nil {
|
||||||
|
return fmt.Errorf("failed to exec 'git %s': %s: %v",
|
||||||
|
strings.Join(args, " "), output, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
files, err := ioutil.ReadDir(dir)
|
files, err := ioutil.ReadDir(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(files) != 1 {
|
|
||||||
return fmt.Errorf("unexpected directory contents: %v", files)
|
|
||||||
}
|
|
||||||
if len(b.revision) == 0 {
|
if len(b.revision) == 0 {
|
||||||
// Done!
|
// Done!
|
||||||
volumeutil.SetReady(b.getMetaDir())
|
volumeutil.SetReady(b.getMetaDir())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
subdir := path.Join(dir, files[0].Name())
|
var subdir string
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case b.target == ".":
|
||||||
|
// if target dir is '.', use the current dir
|
||||||
|
subdir = path.Join(dir)
|
||||||
|
case len(files) == 1:
|
||||||
|
// if target is not '.', use the generated folder
|
||||||
|
subdir = path.Join(dir, files[0].Name())
|
||||||
|
default:
|
||||||
|
// if target is not '.', but generated many files, it's wrong
|
||||||
|
return fmt.Errorf("unexpected directory contents: %v", files)
|
||||||
|
}
|
||||||
|
|
||||||
if output, err := b.execCommand("git", []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)
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package git_repo
|
package git_repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@ -55,106 +56,308 @@ func TestCanSupport(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSetUp(plug volume.VolumePlugin, builder volume.Builder, t *testing.T) {
|
// Expected command
|
||||||
var fcmd exec.FakeCmd
|
type expectedCommand struct {
|
||||||
fcmd = exec.FakeCmd{
|
// The git command
|
||||||
CombinedOutputScript: []exec.FakeCombinedOutputAction{
|
cmd []string
|
||||||
// git clone
|
// The dir of git command is executed
|
||||||
func() ([]byte, error) {
|
dir string
|
||||||
os.MkdirAll(path.Join(fcmd.Dirs[0], "kubernetes"), 0750)
|
|
||||||
return []byte{}, nil
|
|
||||||
},
|
|
||||||
// git checkout
|
|
||||||
func() ([]byte, error) { return []byte{}, nil },
|
|
||||||
// git reset
|
|
||||||
func() ([]byte, error) { return []byte{}, nil },
|
|
||||||
},
|
|
||||||
}
|
|
||||||
fake := exec.FakeExec{
|
|
||||||
CommandScript: []exec.FakeCommandAction{
|
|
||||||
func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) },
|
|
||||||
func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) },
|
|
||||||
func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) },
|
|
||||||
},
|
|
||||||
}
|
|
||||||
g := builder.(*gitRepoVolumeBuilder)
|
|
||||||
g.exec = &fake
|
|
||||||
|
|
||||||
err := g.SetUp()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
expectedCmds := [][]string{
|
|
||||||
{"git", "clone", g.source},
|
|
||||||
{"git", "checkout", g.revision},
|
|
||||||
{"git", "reset", "--hard"},
|
|
||||||
}
|
|
||||||
if fake.CommandCalls != len(expectedCmds) {
|
|
||||||
t.Errorf("unexpected command calls: expected 3, saw: %d", fake.CommandCalls)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(expectedCmds, fcmd.CombinedOutputLog) {
|
|
||||||
t.Errorf("unexpected commands: %v, expected: %v", fcmd.CombinedOutputLog, expectedCmds)
|
|
||||||
}
|
|
||||||
expectedDirs := []string{g.GetPath(), g.GetPath() + "/kubernetes", g.GetPath() + "/kubernetes"}
|
|
||||||
if len(fcmd.Dirs) != 3 || !reflect.DeepEqual(expectedDirs, fcmd.Dirs) {
|
|
||||||
t.Errorf("unexpected directories: %v, expected: %v", fcmd.Dirs, expectedDirs)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPlugin(t *testing.T) {
|
func TestPlugin(t *testing.T) {
|
||||||
|
gitUrl := "https://github.com/GoogleCloudPlatform/kubernetes.git"
|
||||||
|
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",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func doTestPlugin(scenario struct {
|
||||||
|
name string
|
||||||
|
vol *api.Volume
|
||||||
|
expecteds []expectedCommand
|
||||||
|
isExpectedFailure bool
|
||||||
|
}, t *testing.T) []error {
|
||||||
|
allErrs := []error{}
|
||||||
|
|
||||||
plugMgr := volume.VolumePluginMgr{}
|
plugMgr := volume.VolumePluginMgr{}
|
||||||
plugMgr.InitPlugins(ProbeVolumePlugins(), newTestHost(t))
|
plugMgr.InitPlugins(ProbeVolumePlugins(), newTestHost(t))
|
||||||
|
|
||||||
plug, err := plugMgr.FindPluginByName("kubernetes.io/git-repo")
|
plug, err := plugMgr.FindPluginByName("kubernetes.io/git-repo")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Can't find the plugin by name")
|
allErrs = append(allErrs,
|
||||||
}
|
fmt.Errorf("Can't find the plugin by name"))
|
||||||
spec := &api.Volume{
|
return allErrs
|
||||||
Name: "vol1",
|
|
||||||
VolumeSource: api.VolumeSource{
|
|
||||||
GitRepo: &api.GitRepoVolumeSource{
|
|
||||||
Repository: "https://github.com/GoogleCloudPlatform/kubernetes.git",
|
|
||||||
Revision: "2a30ce65c5ab586b98916d83385c5983edd353a1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}}
|
pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}}
|
||||||
builder, err := plug.NewBuilder(volume.NewSpecFromVolume(spec), pod, volume.VolumeOptions{RootContext: ""})
|
builder, err := plug.NewBuilder(volume.NewSpecFromVolume(scenario.vol), pod, volume.VolumeOptions{RootContext: ""})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to make a new Builder: %v", err)
|
allErrs = append(allErrs,
|
||||||
|
fmt.Errorf("Failed to make a new Builder: %v", err))
|
||||||
|
return allErrs
|
||||||
}
|
}
|
||||||
if builder == nil {
|
if builder == nil {
|
||||||
t.Errorf("Got a nil Builder")
|
allErrs = append(allErrs,
|
||||||
|
fmt.Errorf("Got a nil Builder"))
|
||||||
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
path := builder.GetPath()
|
path := builder.GetPath()
|
||||||
if !strings.HasSuffix(path, "pods/poduid/volumes/kubernetes.io~git-repo/vol1") {
|
if !strings.HasSuffix(path, "pods/poduid/volumes/kubernetes.io~git-repo/vol1") {
|
||||||
t.Errorf("Got unexpected path: %s", path)
|
allErrs = append(allErrs,
|
||||||
|
fmt.Errorf("Got unexpected path: %s", path))
|
||||||
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
testSetUp(plug, builder, t)
|
// Test setUp()
|
||||||
|
setUpErrs := doTestSetUp(scenario, builder)
|
||||||
|
allErrs = append(allErrs, setUpErrs...)
|
||||||
|
|
||||||
if _, err := os.Stat(path); err != nil {
|
if _, err := os.Stat(path); err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
t.Errorf("SetUp() failed, volume path not created: %s", path)
|
allErrs = append(allErrs,
|
||||||
|
fmt.Errorf("SetUp() failed, volume path not created: %s", path))
|
||||||
|
return allErrs
|
||||||
} else {
|
} else {
|
||||||
t.Errorf("SetUp() failed: %v", err)
|
allErrs = append(allErrs,
|
||||||
|
fmt.Errorf("SetUp() failed: %v", err))
|
||||||
|
return allErrs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cleaner, err := plug.NewCleaner("vol1", types.UID("poduid"))
|
cleaner, err := plug.NewCleaner("vol1", types.UID("poduid"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to make a new Cleaner: %v", err)
|
allErrs = append(allErrs,
|
||||||
|
fmt.Errorf("Failed to make a new Cleaner: %v", err))
|
||||||
|
return allErrs
|
||||||
}
|
}
|
||||||
if cleaner == nil {
|
if cleaner == nil {
|
||||||
t.Errorf("Got a nil Cleaner")
|
allErrs = append(allErrs,
|
||||||
|
fmt.Errorf("Got a nil Cleaner"))
|
||||||
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cleaner.TearDown(); err != nil {
|
if err := cleaner.TearDown(); err != nil {
|
||||||
t.Errorf("Expected success, got: %v", err)
|
allErrs = append(allErrs,
|
||||||
|
fmt.Errorf("Expected success, got: %v", err))
|
||||||
|
return allErrs
|
||||||
}
|
}
|
||||||
if _, err := os.Stat(path); err == nil {
|
if _, err := os.Stat(path); err == nil {
|
||||||
t.Errorf("TearDown() failed, volume path still exists: %s", path)
|
allErrs = append(allErrs,
|
||||||
|
fmt.Errorf("TearDown() failed, volume path still exists: %s", path))
|
||||||
} else if !os.IsNotExist(err) {
|
} else if !os.IsNotExist(err) {
|
||||||
t.Errorf("SetUp() failed: %v", err)
|
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...)
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
fake := exec.FakeExec{
|
||||||
|
CommandScript: fakeAction,
|
||||||
|
}
|
||||||
|
|
||||||
|
g := builder.(*gitRepoVolumeBuilder)
|
||||||
|
g.exec = &fake
|
||||||
|
|
||||||
|
g.SetUp()
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user