mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-11 17:12:51 +00:00
Add a loader test.
This commit is contained in:
@@ -4,10 +4,6 @@
|
|||||||
package git
|
package git
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"os/exec"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
"sigs.k8s.io/kustomize/api/filesys"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,84 +14,29 @@ type Cloner func(repoSpec *RepoSpec) error
|
|||||||
// to say, some remote API, to obtain a local clone of
|
// to say, some remote API, to obtain a local clone of
|
||||||
// a remote repo.
|
// a remote repo.
|
||||||
func ClonerUsingGitExec(repoSpec *RepoSpec) error {
|
func ClonerUsingGitExec(repoSpec *RepoSpec) error {
|
||||||
gitProgram, err := exec.LookPath("git")
|
r, err := newCmdRunner()
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "no 'git' program on path")
|
|
||||||
}
|
|
||||||
repoSpec.Dir, err = filesys.NewTmpConfirmedDir()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
repoSpec.Dir = r.dir
|
||||||
cmd := exec.Command(
|
if err = r.run("init"); err != nil {
|
||||||
gitProgram,
|
return err
|
||||||
"init",
|
|
||||||
repoSpec.Dir.String())
|
|
||||||
out, err := cmd.CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error initializing git repo: %s", out)
|
|
||||||
return errors.Wrapf(
|
|
||||||
err,
|
|
||||||
"trouble initializing git repo in %s",
|
|
||||||
repoSpec.Dir.String())
|
|
||||||
}
|
}
|
||||||
|
if err = r.run(
|
||||||
cmd = exec.Command(
|
"remote", "add", "origin", repoSpec.CloneSpec()); err != nil {
|
||||||
gitProgram,
|
return err
|
||||||
"remote",
|
|
||||||
"add",
|
|
||||||
"origin",
|
|
||||||
repoSpec.CloneSpec())
|
|
||||||
cmd.Dir = repoSpec.Dir.String()
|
|
||||||
out, err = cmd.CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error adding remote: %s", out)
|
|
||||||
return errors.Wrapf(err, "trouble adding remote %s", repoSpec.CloneSpec())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ref := "HEAD"
|
ref := "HEAD"
|
||||||
if repoSpec.Ref != "" {
|
if repoSpec.Ref != "" {
|
||||||
ref = repoSpec.Ref
|
ref = repoSpec.Ref
|
||||||
}
|
}
|
||||||
|
if err = r.run("fetch", "--depth=1", "origin", ref); err != nil {
|
||||||
cmd = exec.Command(
|
return err
|
||||||
gitProgram,
|
|
||||||
"fetch",
|
|
||||||
"--depth=1",
|
|
||||||
"origin",
|
|
||||||
ref)
|
|
||||||
cmd.Dir = repoSpec.Dir.String()
|
|
||||||
out, err = cmd.CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error fetching ref: %s", out)
|
|
||||||
return errors.Wrapf(err, "trouble fetching %s", ref)
|
|
||||||
}
|
}
|
||||||
|
if err = r.run("checkout", "FETCH_HEAD"); err != nil {
|
||||||
cmd = exec.Command(
|
return err
|
||||||
gitProgram,
|
|
||||||
"checkout",
|
|
||||||
"FETCH_HEAD")
|
|
||||||
cmd.Dir = repoSpec.Dir.String()
|
|
||||||
out, err = cmd.CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error checking out ref: %s", out)
|
|
||||||
return errors.Wrapf(err, "trouble checking out %s", ref)
|
|
||||||
}
|
}
|
||||||
|
return r.run("submodule", "update", "--init", "--recursive")
|
||||||
cmd = exec.Command(
|
|
||||||
gitProgram,
|
|
||||||
"submodule",
|
|
||||||
"update",
|
|
||||||
"--init",
|
|
||||||
"--recursive")
|
|
||||||
cmd.Dir = repoSpec.Dir.String()
|
|
||||||
out, err = cmd.CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error fetching submodules: %s", out)
|
|
||||||
return errors.Wrapf(err, "trouble fetching submodules for %s", repoSpec.CloneSpec())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DoNothingCloner returns a cloner that only sets
|
// DoNothingCloner returns a cloner that only sets
|
||||||
|
|||||||
65
api/internal/git/gitrunner.go
Normal file
65
api/internal/git/gitrunner.go
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
// Copyright 2020 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package git
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"sigs.k8s.io/kustomize/api/filesys"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Arbitrary, but non-infinite, timeout for running commands.
|
||||||
|
const defaultDuration = 27 * time.Second
|
||||||
|
|
||||||
|
// gitRunner runs the external git binary.
|
||||||
|
type gitRunner struct {
|
||||||
|
gitProgram string
|
||||||
|
duration time.Duration
|
||||||
|
dir filesys.ConfirmedDir
|
||||||
|
}
|
||||||
|
|
||||||
|
// newCmdRunner returns a gitRunner if it can find the binary.
|
||||||
|
// It also creats a temp directory for cloning repos.
|
||||||
|
func newCmdRunner() (*gitRunner, error) {
|
||||||
|
gitProgram, err := exec.LookPath("git")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "no 'git' program on path")
|
||||||
|
}
|
||||||
|
dir, err := filesys.NewTmpConfirmedDir()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &gitRunner{
|
||||||
|
gitProgram: gitProgram,
|
||||||
|
duration: defaultDuration,
|
||||||
|
dir: dir,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// run a command with a timeout.
|
||||||
|
func (r gitRunner) run(args ...string) (err error) {
|
||||||
|
ch := make(chan bool, 1)
|
||||||
|
defer close(ch)
|
||||||
|
//nolint: gosec
|
||||||
|
cmd := exec.Command(r.gitProgram, args...)
|
||||||
|
cmd.Dir = r.dir.String()
|
||||||
|
timer := time.NewTimer(r.duration)
|
||||||
|
defer timer.Stop()
|
||||||
|
go func() {
|
||||||
|
_, err = cmd.CombinedOutput()
|
||||||
|
ch <- true
|
||||||
|
}()
|
||||||
|
select {
|
||||||
|
case <-ch:
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "git cmd = '%s'", cmd.String())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
case <-timer.C:
|
||||||
|
return types.NewErrTimeOut(r.duration, cmd.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
40
api/krusty/remoteload_test.go
Normal file
40
api/krusty/remoteload_test.go
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package krusty_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"sigs.k8s.io/kustomize/api/filesys"
|
||||||
|
"sigs.k8s.io/kustomize/api/krusty"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRemoteLoad(t *testing.T) {
|
||||||
|
fSys := filesys.MakeFsOnDisk()
|
||||||
|
b := krusty.MakeKustomizer(fSys, krusty.MakeDefaultOptions())
|
||||||
|
m, err := b.Run(
|
||||||
|
"github.com/kubernetes-sigs/kustomize/examples/multibases/dev/?ref=v1.0.6")
|
||||||
|
if types.IsErrTimeout(err) {
|
||||||
|
// Don't fail on timeouts.
|
||||||
|
t.SkipNow()
|
||||||
|
}
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
yml, err := m.AsYaml()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, `apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: myapp
|
||||||
|
name: dev-myapp-pod
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx:1.7.9
|
||||||
|
name: nginx
|
||||||
|
`, string(yml))
|
||||||
|
}
|
||||||
@@ -7,11 +7,13 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/yujunz/go-getter"
|
"github.com/yujunz/go-getter"
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
"sigs.k8s.io/kustomize/api/filesys"
|
||||||
"sigs.k8s.io/kustomize/api/ifc"
|
"sigs.k8s.io/kustomize/api/ifc"
|
||||||
"sigs.k8s.io/kustomize/api/internal/git"
|
"sigs.k8s.io/kustomize/api/internal/git"
|
||||||
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type remoteTargetSpec struct {
|
type remoteTargetSpec struct {
|
||||||
@@ -28,7 +30,12 @@ type remoteTargetSpec struct {
|
|||||||
// Getter is a function that can gets resource
|
// Getter is a function that can gets resource
|
||||||
type remoteTargetGetter func(rs *remoteTargetSpec) error
|
type remoteTargetGetter func(rs *remoteTargetSpec) error
|
||||||
|
|
||||||
func newLoaderAtGetter(raw string, fSys filesys.FileSystem, referrer *fileLoader, cloner git.Cloner, getter remoteTargetGetter) (ifc.Loader, error) {
|
func newLoaderAtGetter(
|
||||||
|
raw string,
|
||||||
|
fSys filesys.FileSystem,
|
||||||
|
referrer *fileLoader,
|
||||||
|
cloner git.Cloner,
|
||||||
|
getter remoteTargetGetter) (ifc.Loader, error) {
|
||||||
rs := &remoteTargetSpec{
|
rs := &remoteTargetSpec{
|
||||||
Raw: raw,
|
Raw: raw,
|
||||||
}
|
}
|
||||||
@@ -86,7 +93,22 @@ func getRemoteTarget(rs *remoteTargetSpec) error {
|
|||||||
},
|
},
|
||||||
Options: opts,
|
Options: opts,
|
||||||
}
|
}
|
||||||
return client.Get()
|
|
||||||
|
ch := make(chan bool, 1)
|
||||||
|
defer close(ch)
|
||||||
|
d := 21 * time.Second // arbitrary
|
||||||
|
timer := time.NewTimer(d)
|
||||||
|
defer timer.Stop()
|
||||||
|
go func() {
|
||||||
|
err = client.Get()
|
||||||
|
ch <- true
|
||||||
|
}()
|
||||||
|
select {
|
||||||
|
case <-ch:
|
||||||
|
case <-timer.C:
|
||||||
|
err = types.NewErrTimeOut(d, "go-getter client.Get")
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNothing(rs *remoteTargetSpec) error {
|
func getNothing(rs *remoteTargetSpec) error {
|
||||||
|
|||||||
36
api/types/errtimeout.go
Normal file
36
api/types/errtimeout.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
// Copyright 2020 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type errTimeOut struct {
|
||||||
|
duration time.Duration
|
||||||
|
cmd string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewErrTimeOut(d time.Duration, c string) errTimeOut {
|
||||||
|
return errTimeOut{duration: d, cmd: c}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e errTimeOut) Error() string {
|
||||||
|
return fmt.Sprintf("hit %s timeout running '%s'", e.duration, e.cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsErrTimeout(err error) bool {
|
||||||
|
if err == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
_, ok := err.(errTimeOut)
|
||||||
|
if ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
_, ok = errors.Cause(err).(errTimeOut)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user