From f26bfa6511d4a4ede7455127b2670ad3bdda8e99 Mon Sep 17 00:00:00 2001 From: Andreas Paul Date: Fri, 4 Aug 2017 17:41:23 +0200 Subject: [PATCH] add exit_if_unreachable source config setting for #66 --- README.md | 21 ++++++++ g10k.go | 4 +- g10k_test.go | 53 +++++++++++++++++++++ git.go | 2 +- puppetfile.go | 31 +++++++++--- tests/TestConfigExitIfUnreachable.yaml | 8 ++++ tests/TestConfigExitIfUnreachableFalse.yaml | 8 ++++ 7 files changed, 119 insertions(+), 8 deletions(-) create mode 100644 tests/TestConfigExitIfUnreachable.yaml create mode 100644 tests/TestConfigExitIfUnreachableFalse.yaml diff --git a/README.md b/README.md index 0518ab3..539a174 100644 --- a/README.md +++ b/README.md @@ -246,6 +246,27 @@ go get BUILDTIME=$(date -u '+%Y-%m-%d_%H:%M:%S') && go build -ldflags "-s -w -X main.buildtime=$BUILDTIME" ``` +- abort g10k run if source repository is unreachable + +``` +--- +:cachedir: '/tmp/g10k' + +sources: + example: + remote: 'git://github.com/xorpaul/g10k-environment-unavailable.git' + basedir: '/tmp/example/' + exit_if_unreachable: true +``` + +If you then call g10k with that config file. You should get: + +``` +WARN: git repository git://github.com/xorpaul/g10k-environment-unavailable.git does not exist or is unreachable at this moment! +WARNING: Could not resolve git repository in source 'example' (git://github.com/xorpaul/g10k-environment-unavailable.git) +``` +with an exit code 1 + # execute example with debug output ``` ./g10k -debug -config test.yaml diff --git a/g10k.go b/g10k.go index b1e00b0..e417ca1 100644 --- a/g10k.go +++ b/g10k.go @@ -24,6 +24,7 @@ var ( moduleDirParam string cacheDirParam string branchParam string + configFile string config ConfigSettings wg sync.WaitGroup mutex sync.Mutex @@ -81,6 +82,7 @@ type Source struct { PrivateKey string `yaml:"private_key"` ForceForgeVersions bool `yaml:"force_forge_versions"` WarnMissingBranch bool `yaml:"warn_if_branch_is_missing"` + ExitIfUnreachable bool `yaml:"exit_if_unreachable"` } // Puppetfile contains the key value pairs from the Puppetfile @@ -156,7 +158,7 @@ func main() { flag.BoolVar(&quiet, "quiet", false, "no output, defaults to false") flag.Parse() - configFile := *configFileFlag + configFile = *configFileFlag version := *versionFlag if version { diff --git a/g10k_test.go b/g10k_test.go index c91111c..1848f7b 100644 --- a/g10k_test.go +++ b/g10k_test.go @@ -369,3 +369,56 @@ func TestModuleDirOverride(t *testing.T) { t.Error("Expected '", moduleDirParam, "' for module dir, but got", got.moduleDir) } } + +func TestResolvConfigExitIfUnreachable(t *testing.T) { + funcName := strings.Split(funcName(), ".")[len(strings.Split(funcName(), "."))-1] + config = readConfigfile("tests/TestConfigExitIfUnreachable.yaml") + purgeDir(config.CacheDir, "TestResolvConfigExitIfUnreachable()") + if os.Getenv("TEST_FOR_CRASH_"+funcName) == "1" { + resolvePuppetEnvironment("single") + return + } + + cmd := exec.Command(os.Args[0], "-test.run="+funcName+"$") + cmd.Env = append(os.Environ(), "TEST_FOR_CRASH_"+funcName+"=1") + out, err := cmd.CombinedOutput() + + exitCode := 0 + if msg, ok := err.(*exec.ExitError); ok { // there is error code + exitCode = msg.Sys().(syscall.WaitStatus).ExitStatus() + } + + if 1 != exitCode { + t.Errorf("resolvePuppetEnvironment() terminated with %v, but we expected exit status %v", exitCode, 1) + } + //fmt.Println(string(out)) + if !strings.Contains(string(out), "WARN: git repository git://github.com/xorpaul/g10k-environment-unavailable.git does not exist or is unreachable at this moment!\nWARNING: Could not resolve git repository in source 'example' (git://github.com/xorpaul/g10k-environment-unavailable.git)") { + t.Errorf("resolvePuppetEnvironment() terminated with the correct exit code, but the expected output was missing") + } +} + +func TestResolvConfigExitIfUnreachableFalse(t *testing.T) { + funcName := strings.Split(funcName(), ".")[len(strings.Split(funcName(), "."))-1] + config = readConfigfile("tests/TestConfigExitIfUnreachableFalse.yaml") + purgeDir(config.CacheDir, "TestResolvConfigExitIfUnreachableFalse()") + if os.Getenv("TEST_FOR_CRASH_"+funcName) == "1" { + resolvePuppetEnvironment("single") + return + } + + cmd := exec.Command(os.Args[0], "-test.run="+funcName+"$") + cmd.Env = append(os.Environ(), "TEST_FOR_CRASH_"+funcName+"=1") + out, err := cmd.CombinedOutput() + + exitCode := 0 + if msg, ok := err.(*exec.ExitError); ok { // there is error code + exitCode = msg.Sys().(syscall.WaitStatus).ExitStatus() + } + + if 0 != exitCode { + t.Errorf("resolvePuppetEnvironment() terminated with %v, but we expected exit status %v", exitCode, 1) + } + if !strings.Contains(string(out), "WARN: git repository git://github.com/xorpaul/g10k-environment-unavailable.git does not exist or is unreachable at this moment!\nWARNING: Could not resolve git repository in source 'example' (git://github.com/xorpaul/g10k-environment-unavailable.git)") { + t.Errorf("resolvePuppetEnvironment() terminated with the correct exit code, but the expected output was missing") + } +} diff --git a/git.go b/git.go index 8e3fb4d..c2f4097 100644 --- a/git.go +++ b/git.go @@ -110,7 +110,7 @@ func doMirrorOrUpdate(url string, workDir string, sshPrivateKey string, allowFai } if er.returnCode != 0 { - fmt.Println("WARN: git repository " + url + " does not exist or is unreachable at this moment!") + Warnf("WARN: git repository " + url + " does not exist or is unreachable at this moment!") return false } return true diff --git a/puppetfile.go b/puppetfile.go index 33d6980..67f90f1 100644 --- a/puppetfile.go +++ b/puppetfile.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "io/ioutil" "os" "strings" @@ -9,6 +10,21 @@ import ( "github.com/henvic/uiprogress" ) +// sourceSanityCheck is a validation function that checks if the given source has all neccessary attributes (basedir, remote, SSH key exists if given) +func sourceSanityCheck(source string, sa Source) { + if len(sa.PrivateKey) > 0 { + if _, err := os.Stat(sa.PrivateKey); err != nil { + Fatalf("resolvePuppetEnvironment(): could not find SSH private key " + sa.PrivateKey + " for source " + source + " in config file " + configFile + " Error: " + err.Error()) + } + } + if len(sa.Basedir) <= 0 { + Fatalf("resolvePuppetEnvironment(): config setting basedir is not set for source " + source + " in config file " + configFile) + } + if len(sa.Remote) <= 0 { + Fatalf("resolvePuppetEnvironment(): config setting remote is not set for source " + source + " in config file " + configFile) + } +} + func resolvePuppetEnvironment(envBranch string) { allPuppetfiles := make(map[string]Puppetfile) for source, sa := range config.Sources { @@ -20,12 +36,10 @@ func resolvePuppetEnvironment(envBranch string) { } sa.Basedir = checkDirAndCreate(sa.Basedir, "basedir for source "+source) - Debugf("Puppet environment: " + source + " (remote=" + sa.Remote + ", basedir=" + sa.Basedir + ", private_key=" + sa.PrivateKey + ", prefix=" + sa.Prefix + ")") - if len(sa.PrivateKey) > 0 { - if _, err := os.Stat(sa.PrivateKey); err != nil { - Fatalf("resolvePuppetEnvironment(): could not find SSH private key " + sa.PrivateKey + "error: " + err.Error()) - } - } + Debugf("Puppet environment: " + source + " (" + fmt.Sprintf("%+v", sa) + ")") + + // check for a valid source that has all neccessary attributes (basedir, remote, SSH key exists if given) + sourceSanityCheck(source, sa) workDir := config.EnvCacheDir + source + ".git" // check if sa.Basedir exists @@ -83,6 +97,11 @@ func resolvePuppetEnvironment(envBranch string) { if sa.WarnMissingBranch && !foundBranch { Warnf("WARNING: Couldn't find specified branch '" + envBranch + "' anywhere in source '" + source + "' (" + sa.Remote + ")") } + } else { + Warnf("WARNING: Could not resolve git repository in source '" + source + "' (" + sa.Remote + ")") + if sa.ExitIfUnreachable == true { + os.Exit(1) + } } }(source, sa) } diff --git a/tests/TestConfigExitIfUnreachable.yaml b/tests/TestConfigExitIfUnreachable.yaml new file mode 100644 index 0000000..44241a7 --- /dev/null +++ b/tests/TestConfigExitIfUnreachable.yaml @@ -0,0 +1,8 @@ +--- +:cachedir: '/tmp/g10k' + +sources: + example: + remote: 'git://github.com/xorpaul/g10k-environment-unavailable.git' + basedir: '/tmp/example/' + exit_if_unreachable: true diff --git a/tests/TestConfigExitIfUnreachableFalse.yaml b/tests/TestConfigExitIfUnreachableFalse.yaml new file mode 100644 index 0000000..4e63f74 --- /dev/null +++ b/tests/TestConfigExitIfUnreachableFalse.yaml @@ -0,0 +1,8 @@ +--- +:cachedir: '/tmp/g10k' + +sources: + example: + remote: 'git://github.com/xorpaul/g10k-environment-unavailable.git' + basedir: '/tmp/example/' + exit_if_unreachable: false