terraform/internal/getmodules/git_getter_test.go

828 lines
20 KiB
Go

package getmodules
import (
"bytes"
"encoding/base64"
"io/ioutil"
"net/url"
"os"
"os/exec"
"path/filepath"
"reflect"
"runtime"
"strings"
"testing"
getter "github.com/hashicorp/go-getter"
urlhelper "github.com/hashicorp/go-getter/helper/url"
)
var testHasGit bool
func init() {
if _, err := exec.LookPath("git"); err == nil {
testHasGit = true
}
}
func TestGitGetter_impl(t *testing.T) {
var _ getter.Getter = new(gitGetter)
}
func TestGitGetter(t *testing.T) {
if !testHasGit {
t.Skip("git not found, skipping")
}
g := new(gitGetter)
dst := tempDir(t)
repo := testGitRepo(t, "basic")
repo.commitFile("foo.txt", "hello")
// With a dir that doesn't exist
if err := g.Get(dst, repo.url); err != nil {
t.Fatalf("err: %s", err)
}
// Verify the main file exists
mainPath := filepath.Join(dst, "foo.txt")
if _, err := os.Stat(mainPath); err != nil {
t.Fatalf("err: %s", err)
}
}
func TestGitGetter_branch(t *testing.T) {
if !testHasGit {
t.Skip("git not found, skipping")
}
g := new(gitGetter)
dst := tempDir(t)
repo := testGitRepo(t, "branch")
repo.git("checkout", "-b", "test-branch")
repo.commitFile("branch.txt", "branch")
q := repo.url.Query()
q.Add("ref", "test-branch")
repo.url.RawQuery = q.Encode()
if err := g.Get(dst, repo.url); err != nil {
t.Fatalf("err: %s", err)
}
// Verify the main file exists
mainPath := filepath.Join(dst, "branch.txt")
if _, err := os.Stat(mainPath); err != nil {
t.Fatalf("err: %s", err)
}
// Get again should work
if err := g.Get(dst, repo.url); err != nil {
t.Fatalf("err: %s", err)
}
// Verify the main file exists
mainPath = filepath.Join(dst, "branch.txt")
if _, err := os.Stat(mainPath); err != nil {
t.Fatalf("err: %s", err)
}
}
func TestGitGetter_commitID(t *testing.T) {
if !testHasGit {
t.Skip("git not found, skipping")
}
g := new(gitGetter)
dst := tempDir(t)
// We're going to create different content on the main branch vs.
// another branch here, so that below we can recognize if we
// correctly cloned the commit actually requested (from the
// "other branch"), not the one at HEAD.
repo := testGitRepo(t, "commit_id")
repo.git("checkout", "-b", "main-branch")
repo.commitFile("wrong.txt", "Nope")
repo.git("checkout", "-b", "other-branch")
repo.commitFile("hello.txt", "Yep")
commitID, err := repo.latestCommit()
if err != nil {
t.Fatal(err)
}
// Return to the main branch so that HEAD of this repository
// will be that, rather than "test-branch".
repo.git("checkout", "main-branch")
q := repo.url.Query()
q.Add("ref", commitID)
repo.url.RawQuery = q.Encode()
t.Logf("Getting %s", repo.url)
if err := g.Get(dst, repo.url); err != nil {
t.Fatalf("err: %s", err)
}
// Verify the main file exists
mainPath := filepath.Join(dst, "hello.txt")
if _, err := os.Stat(mainPath); err != nil {
t.Fatalf("err: %s", err)
}
// Get again should work
if err := g.Get(dst, repo.url); err != nil {
t.Fatalf("err: %s", err)
}
// Verify the main file exists
mainPath = filepath.Join(dst, "hello.txt")
if _, err := os.Stat(mainPath); err != nil {
t.Fatalf("err: %s", err)
}
}
func TestGitGetter_remoteWithoutMaster(t *testing.T) {
if !testHasGit {
t.Log("git not found, skipping")
t.Skip()
}
g := new(gitGetter)
dst := tempDir(t)
repo := testGitRepo(t, "branch")
repo.git("checkout", "-b", "test-branch")
repo.commitFile("branch.txt", "branch")
q := repo.url.Query()
repo.url.RawQuery = q.Encode()
if err := g.Get(dst, repo.url); err != nil {
t.Fatalf("err: %s", err)
}
// Verify the main file exists
mainPath := filepath.Join(dst, "branch.txt")
if _, err := os.Stat(mainPath); err != nil {
t.Fatalf("err: %s", err)
}
// Get again should work
if err := g.Get(dst, repo.url); err != nil {
t.Fatalf("err: %s", err)
}
// Verify the main file exists
mainPath = filepath.Join(dst, "branch.txt")
if _, err := os.Stat(mainPath); err != nil {
t.Fatalf("err: %s", err)
}
}
func TestGitGetter_shallowClone(t *testing.T) {
if !testHasGit {
t.Log("git not found, skipping")
t.Skip()
}
g := new(gitGetter)
dst := tempDir(t)
repo := testGitRepo(t, "upstream")
repo.commitFile("upstream.txt", "0")
repo.commitFile("upstream.txt", "1")
// Specifiy a clone depth of 1
q := repo.url.Query()
q.Add("depth", "1")
repo.url.RawQuery = q.Encode()
if err := g.Get(dst, repo.url); err != nil {
t.Fatalf("err: %s", err)
}
// Assert rev-list count is '1'
cmd := exec.Command("git", "rev-list", "HEAD", "--count")
cmd.Dir = dst
b, err := cmd.Output()
if err != nil {
t.Fatalf("err: %s", err)
}
out := strings.TrimSpace(string(b))
if out != "1" {
t.Fatalf("expected rev-list count to be '1' but got %v", out)
}
}
func TestGitGetter_shallowCloneWithTag(t *testing.T) {
if !testHasGit {
t.Log("git not found, skipping")
t.Skip()
}
g := new(gitGetter)
dst := tempDir(t)
repo := testGitRepo(t, "upstream")
repo.commitFile("v1.0.txt", "0")
repo.git("tag", "v1.0")
repo.commitFile("v1.1.txt", "1")
// Specifiy a clone depth of 1 with a tag
q := repo.url.Query()
q.Add("ref", "v1.0")
q.Add("depth", "1")
repo.url.RawQuery = q.Encode()
if err := g.Get(dst, repo.url); err != nil {
t.Fatalf("err: %s", err)
}
// Assert rev-list count is '1'
cmd := exec.Command("git", "rev-list", "HEAD", "--count")
cmd.Dir = dst
b, err := cmd.Output()
if err != nil {
t.Fatalf("err: %s", err)
}
out := strings.TrimSpace(string(b))
if out != "1" {
t.Fatalf("expected rev-list count to be '1' but got %v", out)
}
// Verify the v1.0 file exists
mainPath := filepath.Join(dst, "v1.0.txt")
if _, err := os.Stat(mainPath); err != nil {
t.Fatalf("err: %s", err)
}
// Verify the v1.1 file does not exists
mainPath = filepath.Join(dst, "v1.1.txt")
if _, err := os.Stat(mainPath); err == nil {
t.Fatalf("expected v1.1 file to not exist")
}
}
func TestGitGetter_shallowCloneWithCommitID(t *testing.T) {
if !testHasGit {
t.Log("git not found, skipping")
t.Skip()
}
g := new(gitGetter)
dst := tempDir(t)
repo := testGitRepo(t, "upstream")
repo.commitFile("v1.0.txt", "0")
repo.git("tag", "v1.0")
repo.commitFile("v1.1.txt", "1")
commitID, err := repo.latestCommit()
if err != nil {
t.Fatal(err)
}
// Specify a clone depth of 1 with a naked commit ID
// This is intentionally invalid: shallow clone always requires a named ref.
q := repo.url.Query()
q.Add("ref", commitID[:8])
q.Add("depth", "1")
repo.url.RawQuery = q.Encode()
t.Logf("Getting %s", repo.url)
err = g.Get(dst, repo.url)
if err == nil {
t.Fatalf("success; want error")
}
// We use a heuristic to generate an extra hint in the error message if
// it looks like the user was trying to combine ref=COMMIT with depth.
if got, want := err.Error(), "(note that setting 'depth' requires 'ref' to be a branch or tag name)"; !strings.Contains(got, want) {
t.Errorf("missing error message hint\ngot: %s\nwant substring: %s", got, want)
}
}
func TestGitGetter_branchUpdate(t *testing.T) {
if !testHasGit {
t.Skip("git not found, skipping")
}
g := new(gitGetter)
dst := tempDir(t)
// First setup the state with a fresh branch
repo := testGitRepo(t, "branch-update")
repo.git("checkout", "-b", "test-branch")
repo.commitFile("branch.txt", "branch")
// Get the "test-branch" branch
q := repo.url.Query()
q.Add("ref", "test-branch")
repo.url.RawQuery = q.Encode()
if err := g.Get(dst, repo.url); err != nil {
t.Fatalf("err: %s", err)
}
// Verify the main file exists
mainPath := filepath.Join(dst, "branch.txt")
if _, err := os.Stat(mainPath); err != nil {
t.Fatalf("err: %s", err)
}
// Commit an update to the branch
repo.commitFile("branch-update.txt", "branch-update")
// Get again should work
if err := g.Get(dst, repo.url); err != nil {
t.Fatalf("err: %s", err)
}
// Verify the main file exists
mainPath = filepath.Join(dst, "branch-update.txt")
if _, err := os.Stat(mainPath); err != nil {
t.Fatalf("err: %s", err)
}
}
func TestGitGetter_tag(t *testing.T) {
if !testHasGit {
t.Skip("git not found, skipping")
}
g := new(gitGetter)
dst := tempDir(t)
repo := testGitRepo(t, "tag")
repo.commitFile("tag.txt", "tag")
repo.git("tag", "v1.0")
q := repo.url.Query()
q.Add("ref", "v1.0")
repo.url.RawQuery = q.Encode()
if err := g.Get(dst, repo.url); err != nil {
t.Fatalf("err: %s", err)
}
// Verify the main file exists
mainPath := filepath.Join(dst, "tag.txt")
if _, err := os.Stat(mainPath); err != nil {
t.Fatalf("err: %s", err)
}
// Get again should work
if err := g.Get(dst, repo.url); err != nil {
t.Fatalf("err: %s", err)
}
// Verify the main file exists
mainPath = filepath.Join(dst, "tag.txt")
if _, err := os.Stat(mainPath); err != nil {
t.Fatalf("err: %s", err)
}
}
func TestGitGetter_GetFile(t *testing.T) {
if !testHasGit {
t.Skip("git not found, skipping")
}
g := new(gitGetter)
dst := tempTestFile(t)
defer os.RemoveAll(filepath.Dir(dst))
repo := testGitRepo(t, "file")
repo.commitFile("file.txt", "hello")
// Download the file
repo.url.Path = filepath.Join(repo.url.Path, "file.txt")
if err := g.GetFile(dst, repo.url); err != nil {
t.Fatalf("err: %s", err)
}
// Verify the main file exists
if _, err := os.Stat(dst); err != nil {
t.Fatalf("err: %s", err)
}
assertContents(t, dst, "hello")
}
func TestGitGetter_gitVersion(t *testing.T) {
if !testHasGit {
t.Skip("git not found, skipping")
}
if runtime.GOOS == "windows" {
t.Skip("skipping on windows since the test requires sh")
}
dir, err := ioutil.TempDir("", "go-getter")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
script := filepath.Join(dir, "git")
err = ioutil.WriteFile(
script,
[]byte("#!/bin/sh\necho \"git version 2.0 (Some Metadata Here)\n\""),
0700)
if err != nil {
t.Fatal(err)
}
defer func(v string) {
os.Setenv("PATH", v)
}(os.Getenv("PATH"))
os.Setenv("PATH", dir)
// Asking for a higher version throws an error
if err := checkGitVersion("2.3"); err == nil {
t.Fatal("expect git version error")
}
// Passes when version is satisfied
if err := checkGitVersion("1.9"); err != nil {
t.Fatal(err)
}
}
func TestGitGetter_sshKey(t *testing.T) {
if !testHasGit {
t.Skip("git not found, skipping")
}
g := new(gitGetter)
dst := tempDir(t)
encodedKey := base64.StdEncoding.EncodeToString([]byte(testGitToken))
// avoid getting locked by a github authenticity validation prompt
os.Setenv("GIT_SSH_COMMAND", "ssh -o StrictHostKeyChecking=no -o IdentitiesOnly=yes")
defer os.Setenv("GIT_SSH_COMMAND", "")
u, err := urlhelper.Parse("ssh://git@github.com/hashicorp/test-private-repo" +
"?sshkey=" + encodedKey)
if err != nil {
t.Fatal(err)
}
if err := g.Get(dst, u); err != nil {
t.Fatalf("err: %s", err)
}
readmePath := filepath.Join(dst, "README.md")
if _, err := os.Stat(readmePath); err != nil {
t.Fatalf("err: %s", err)
}
}
func TestGitGetter_sshSCPStyle(t *testing.T) {
if !testHasGit {
t.Skip("git not found, skipping")
}
g := new(gitGetter)
dst := tempDir(t)
encodedKey := base64.StdEncoding.EncodeToString([]byte(testGitToken))
// avoid getting locked by a github authenticity validation prompt
os.Setenv("GIT_SSH_COMMAND", "ssh -o StrictHostKeyChecking=no -o IdentitiesOnly=yes")
defer os.Setenv("GIT_SSH_COMMAND", "")
// This test exercises the combination of the git detector and the
// git getter, to make sure that together they make scp-style URLs work.
client := &getter.Client{
Src: "git@github.com:hashicorp/test-private-repo?sshkey=" + encodedKey,
Dst: dst,
Pwd: ".",
Mode: getter.ClientModeDir,
Detectors: []getter.Detector{
new(getter.GitDetector),
},
Getters: map[string]getter.Getter{
"git": g,
},
}
if err := client.Get(); err != nil {
t.Fatalf("client.Get failed: %s", err)
}
readmePath := filepath.Join(dst, "README.md")
if _, err := os.Stat(readmePath); err != nil {
t.Fatalf("err: %s", err)
}
}
func TestGitGetter_sshExplicitPort(t *testing.T) {
if !testHasGit {
t.Skip("git not found, skipping")
}
g := new(gitGetter)
dst := tempDir(t)
encodedKey := base64.StdEncoding.EncodeToString([]byte(testGitToken))
// avoid getting locked by a github authenticity validation prompt
os.Setenv("GIT_SSH_COMMAND", "ssh -o StrictHostKeyChecking=no -o IdentitiesOnly=yes")
defer os.Setenv("GIT_SSH_COMMAND", "")
// This test exercises the combination of the git detector and the
// git getter, to make sure that together they make scp-style URLs work.
client := &getter.Client{
Src: "git::ssh://git@github.com:22/hashicorp/test-private-repo?sshkey=" + encodedKey,
Dst: dst,
Pwd: ".",
Mode: getter.ClientModeDir,
Detectors: []getter.Detector{
new(getter.GitDetector),
},
Getters: map[string]getter.Getter{
"git": g,
},
}
if err := client.Get(); err != nil {
t.Fatalf("client.Get failed: %s", err)
}
readmePath := filepath.Join(dst, "README.md")
if _, err := os.Stat(readmePath); err != nil {
t.Fatalf("err: %s", err)
}
}
func TestGitGetter_sshSCPStyleInvalidScheme(t *testing.T) {
if !testHasGit {
t.Skip("git not found, skipping")
}
g := new(gitGetter)
dst := tempDir(t)
encodedKey := base64.StdEncoding.EncodeToString([]byte(testGitToken))
// avoid getting locked by a github authenticity validation prompt
os.Setenv("GIT_SSH_COMMAND", "ssh -o StrictHostKeyChecking=no -o IdentitiesOnly=yes")
defer os.Setenv("GIT_SSH_COMMAND", "")
// This test exercises the combination of the git detector and the
// git getter, to make sure that together they make scp-style URLs work.
client := &getter.Client{
Src: "git::ssh://git@github.com:hashicorp/test-private-repo?sshkey=" + encodedKey,
Dst: dst,
Pwd: ".",
Mode: getter.ClientModeDir,
Detectors: []getter.Detector{
new(getter.GitDetector),
},
Getters: map[string]getter.Getter{
"git": g,
},
}
err := client.Get()
if err == nil {
t.Fatalf("get succeeded; want error")
}
got := err.Error()
want1, want2 := `invalid source string`, `invalid port number "hashicorp"`
if !(strings.Contains(got, want1) || strings.Contains(got, want2)) {
t.Fatalf("wrong error\ngot: %s\nwant: %q or %q", got, want1, want2)
}
}
func TestGitGetter_submodule(t *testing.T) {
if !testHasGit {
t.Skip("git not found, skipping")
}
g := new(gitGetter)
dst := tempDir(t)
relpath := func(basepath, targpath string) string {
relpath, err := filepath.Rel(basepath, targpath)
if err != nil {
t.Fatal(err)
}
return strings.Replace(relpath, `\`, `/`, -1)
// on windows git still prefers relatives paths
// containing `/` for submodules
}
// Set up the grandchild
gc := testGitRepo(t, "grandchild")
gc.commitFile("grandchild.txt", "grandchild")
// Set up the child
c := testGitRepo(t, "child")
c.commitFile("child.txt", "child")
c.git("submodule", "add", "-f", relpath(c.dir, gc.dir))
c.git("commit", "-m", "Add grandchild submodule")
// Set up the parent
p := testGitRepo(t, "parent")
p.commitFile("parent.txt", "parent")
p.git("submodule", "add", "-f", relpath(p.dir, c.dir))
p.git("commit", "-m", "Add child submodule")
// Clone the root repository
if err := g.Get(dst, p.url); err != nil {
t.Fatalf("err: %s", err)
}
// Check that the files exist
for _, path := range []string{
filepath.Join(dst, "parent.txt"),
filepath.Join(dst, "child", "child.txt"),
filepath.Join(dst, "child", "grandchild", "grandchild.txt"),
} {
if _, err := os.Stat(path); err != nil {
t.Fatalf("err: %s", err)
}
}
}
func TestGitGetter_setupGitEnv_sshKey(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("skipping on windows since the test requires sh")
}
cmd := exec.Command("/bin/sh", "-c", "echo $GIT_SSH_COMMAND")
setupGitEnv(cmd, "/tmp/foo.pem")
out, err := cmd.Output()
if err != nil {
t.Fatal(err)
}
actual := strings.TrimSpace(string(out))
if actual != "ssh -i /tmp/foo.pem" {
t.Fatalf("unexpected GIT_SSH_COMMAND: %q", actual)
}
}
func TestGitGetter_setupGitEnvWithExisting_sshKey(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skipf("skipping on windows since the test requires sh")
return
}
// start with an existing ssh command configuration
os.Setenv("GIT_SSH_COMMAND", "ssh -o StrictHostKeyChecking=no -o IdentitiesOnly=yes")
defer os.Setenv("GIT_SSH_COMMAND", "")
cmd := exec.Command("/bin/sh", "-c", "echo $GIT_SSH_COMMAND")
setupGitEnv(cmd, "/tmp/foo.pem")
out, err := cmd.Output()
if err != nil {
t.Fatal(err)
}
actual := strings.TrimSpace(string(out))
if actual != "ssh -o StrictHostKeyChecking=no -o IdentitiesOnly=yes -i /tmp/foo.pem" {
t.Fatalf("unexpected GIT_SSH_COMMAND: %q", actual)
}
}
// gitRepo is a helper struct which controls a single temp git repo.
type gitRepo struct {
t *testing.T
url *url.URL
dir string
}
// testGitRepo creates a new test git repository.
func testGitRepo(t *testing.T, name string) *gitRepo {
t.Helper()
dir, err := ioutil.TempDir("", "go-getter")
if err != nil {
t.Fatal(err)
}
dir = filepath.Join(dir, name)
if err := os.Mkdir(dir, 0700); err != nil {
t.Fatal(err)
}
r := &gitRepo{
t: t,
dir: dir,
}
url, err := urlhelper.Parse("file://" + r.dir)
if err != nil {
t.Fatal(err)
}
r.url = url
t.Logf("initializing git repo in %s", dir)
r.git("init")
r.git("config", "user.name", "go-getter")
r.git("config", "user.email", "go-getter@hashicorp.com")
return r
}
// git runs a git command against the repo.
func (r *gitRepo) git(args ...string) {
cmd := exec.Command("git", args...)
cmd.Dir = r.dir
bfr := bytes.NewBuffer(nil)
cmd.Stderr = bfr
if err := cmd.Run(); err != nil {
r.t.Fatal(err, bfr.String())
}
}
// commitFile writes and commits a text file to the repo.
func (r *gitRepo) commitFile(file, content string) {
path := filepath.Join(r.dir, file)
if err := ioutil.WriteFile(path, []byte(content), 0600); err != nil {
r.t.Fatal(err)
}
r.git("add", file)
r.git("commit", "-m", "Adding "+file)
}
// latestCommit returns the full commit id of the latest commit on the current
// branch.
func (r *gitRepo) latestCommit() (string, error) {
cmd := exec.Command("git", "rev-parse", "HEAD")
cmd.Dir = r.dir
rawOut, err := cmd.Output()
if err != nil {
return "", err
}
rawOut = bytes.TrimSpace(rawOut)
return string(rawOut), nil
}
// This is a read-only deploy key for an empty test repository.
// Note: This is split over multiple lines to avoid being disabled by key
// scanners automatically.
var testGitToken = `-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA9cHsxCl3Jjgu9DHpwvmfFOl1XEdY+ShHDR/cMnzJ5ddk5/oV
Wy6EWatvyHZfRSZMwzv4PtKeUPm6iXjqWp4xdWU9khlPzozyj+U9Fq70TRVUW9E5
T1XdQVwJE421yffr4VMMwu60wBqjI1epapH2i2inYvw9Zl9X2MXq0+jTvFvDerbT
mDtfStDPljenELAIZtWVETSvbI46gALwbxbM2292ZUIL4D6jRz0aZMmyy/twYv8r
9WGJLwmYzU518Ie7zqKW/mCTdTrV0WRiDj0MeRaPgrGY9amuHE4r9iG/cJkwpKAO
Ccz0Hs6i89u9vZnTqZU9V7weJqRAQcMjXXR6yQIDAQABAoIBAQDBzICKnGxiTlHw
rd+6qqChnAy5jWYDbZjCJ8q8YZ3RS08+g/8NXZxvHftTqM0uOaq1FviHig3gq15H
hHvCpBc6jXDFYoKFzq6FfO/0kFkE5HoWweIgxwRow0xBCDJAJ+ryUEyy+Ay/pQHb
IAjwilRS0V+WdnVw4mTjBAhPvb4jPOo97Yfy3PYUyx2F3newkqXOZy+zx3G/ANoa
ncypfMGyy76sfCWKqw4J1gVkVQLwbB6gQkXUFGYwY9sRrxbG93kQw76Flc/E/s52
62j4v1IM0fq0t/St+Y/+s6Lkw` + `aqt3ft1nsqWcRaVDdqvMfkzgJGXlw0bGzJG5MEQ
AIBq3dHRAoGBAP8OeG/DKG2Z1VmSfzuz1pas1fbZ+F7venOBrjez3sKlb3Pyl2aH
mt2wjaTUi5v10VrHgYtOEdqyhQeUSYydWXIBKNMag0NLLrfFUKZK+57wrHWFdFjn
VgpsdkLSNTOZpC8gA5OaJ+36IcOPfGqyyP9wuuRoaYnVT1KEzqLa9FEFAoGBAPaq
pglwhil2rxjJE4zq0afQLNpAfi7Xqcrepij+xvJIcIj7nawxXuPxqRFxONE/h3yX
zkybO8wLdbHX9Iw/wc1j50Uf1Z5gHdLf7/hQJoWKpz1RnkWRy6CYON8v1tpVp0tb
OAajR/kZnzebq2mfa7pyy5zDCX++2kp/dcFwHf31AoGAE8oupBVTZLWj7TBFuP8q
LkS40U92Sv9v09iDCQVmylmFvUxcXPM2m+7f/qMTNgWrucxzC7kB/6MMWVszHbrz
vrnCTibnemgx9sZTjKOSxHFOIEw7i85fSa3Cu0qOIDPSnmlwfZpfcMKQrhjLAYhf
uhooFiLX1X78iZ2OXup4PHUCgYEAsmBrm83sp1V1gAYBBlnVbXakyNv0pCk/Vz61
iFXeRt1NzDGxLxGw3kQnED8BaIh5kQcyn8Fud7sdzJMv/LAqlT4Ww60mzNYTGyjo
H3jOsqm3ESfRvduWFreeAQBWbiOczGjV1i8D4EbAFfWT+tjXjchwKBf+6Yt5zn/o
Bw/uEHUCgYAFs+JPOR25oRyBs7ujrMo/OY1z/eXTVVgZxY+tYGe1FJqDeFyR7ytK
+JBB1MuDwQKGm2wSIXdCzTNoIx2B9zTseiPTwT8G7vqNFhXoIaTBp4P2xIQb45mJ
7GkTsMBHwpSMOXgX9Weq3v5xOJ2WxVtjENmd6qzxcYCO5lP15O17hA==
-----END RSA PRIVATE KEY-----`
func assertContents(t *testing.T, path string, contents string) {
data, err := ioutil.ReadFile(path)
if err != nil {
t.Fatalf("err: %s", err)
}
if !reflect.DeepEqual(data, []byte(contents)) {
t.Fatalf("bad. expected:\n\n%s\n\nGot:\n\n%s", contents, string(data))
}
}
func tempDir(t *testing.T) string {
dir, err := ioutil.TempDir("", "tf")
if err != nil {
t.Fatalf("err: %s", err)
}
if err := os.RemoveAll(dir); err != nil {
t.Fatalf("err: %s", err)
}
return dir
}
func tempTestFile(t *testing.T) string {
dir := tempDir(t)
return filepath.Join(dir, "foo")
}