github.com/hairyhenderson/gomplate/v4@v4.0.0-pre-2.0.20240520121557-362f058f0c93/internal/tests/integration/datasources_git_test.go (about) 1 package integration 2 3 import ( 4 "bytes" 5 "os" 6 "path" 7 "path/filepath" 8 "strconv" 9 "testing" 10 "time" 11 12 "github.com/stretchr/testify/require" 13 "gotest.tools/v3/fs" 14 "gotest.tools/v3/icmd" 15 ) 16 17 func setupDatasourcesGitTest(t *testing.T) *fs.Dir { 18 t.Helper() 19 20 tmpDir := fs.NewDir(t, "gomplate-inttests", 21 fs.WithDir("repo", 22 fs.WithFiles(map[string]string{ 23 "config.json": `{"foo": {"bar": "baz"}}`, 24 "jsonfile": `{"foo": {"bar": "baz"}}`, 25 }), 26 fs.WithDir("subdir", 27 fs.WithFiles(map[string]string{ 28 "foo.txt": "hello world", 29 "bar.json": `{"qux": "quux"}`, 30 }), 31 ), 32 ), 33 ) 34 t.Cleanup(tmpDir.Remove) 35 36 repoPath := tmpDir.Join("repo") 37 38 icmd.RunCmd(icmd.Command("git", "init", repoPath), icmd.Dir(repoPath)). 39 Assert(t, icmd.Expected{Out: "Initialized empty Git repository in "}) 40 icmd.RunCmd(icmd.Command("git", "add", "config.json"), icmd.Dir(repoPath)).Assert(t, icmd.Expected{}) 41 icmd.RunCmd(icmd.Command("git", "add", "jsonfile"), icmd.Dir(repoPath)).Assert(t, icmd.Expected{}) 42 icmd.RunCmd(icmd.Command("git", "add", "subdir"), icmd.Dir(repoPath)).Assert(t, icmd.Expected{}) 43 icmd.RunCmd(icmd.Command("git", "commit", "-m", "Initial commit"), icmd.Dir(repoPath)).Assert(t, icmd.Expected{}) 44 45 return tmpDir 46 } 47 48 func startGitDaemon(t *testing.T) string { 49 t.Helper() 50 51 tmpDir := setupDatasourcesGitTest(t) 52 53 pidDir := fs.NewDir(t, "gomplate-inttests-pid") 54 t.Cleanup(pidDir.Remove) 55 56 port, addr := freeport(t) 57 gitDaemon := icmd.Command("git", "daemon", 58 "--verbose", 59 "--port="+strconv.Itoa(port), 60 "--base-path="+tmpDir.Path(), 61 "--pid-file="+pidDir.Join("git.pid"), 62 "--export-all", 63 tmpDir.Join("repo", ".git"), 64 ) 65 gitDaemon.Stdin = nil 66 gitDaemon.Stdout = &bytes.Buffer{} 67 gitDaemon.Dir = tmpDir.Path() 68 result := icmd.StartCmd(gitDaemon) 69 70 t.Cleanup(func() { 71 err := result.Cmd.Process.Kill() 72 require.NoError(t, err) 73 74 _, err = result.Cmd.Process.Wait() 75 require.NoError(t, err) 76 77 result.Assert(t, icmd.Expected{ExitCode: 0}) 78 }) 79 80 // give git time to start 81 time.Sleep(500 * time.Millisecond) 82 83 return addr 84 } 85 86 func TestDatasources_GitFileDatasource(t *testing.T) { 87 tmpDir := setupDatasourcesGitTest(t) 88 89 u := filepath.ToSlash(tmpDir.Join("repo")) 90 91 // on Windows the path will start with a volume, but we need a 'file:///' 92 // prefix for the URL to be properly interpreted 93 u = path.Join("/", u) 94 o, e, err := cmd(t, 95 "-d", "config=git+file://"+u+"//config.json", 96 "-i", `{{ (datasource "config").foo.bar }}`, 97 ).run() 98 assertSuccess(t, o, e, err, "baz") 99 100 // subpath beginning with // is an antipattern, but should work for 101 // backwards compatibility, params from subpath are used 102 o, e, err = cmd(t, 103 "-d", "repo=git+file://"+u, 104 "-i", `{{ (datasource "repo" "//jsonfile?type=application/json" ).foo.bar }}`, 105 ).run() 106 assertSuccess(t, o, e, err, "baz") 107 108 // subpath beginning with // is an antipattern, but should work for 109 // backwards compatibility 110 o, e, err = cmd(t, 111 "-d", "repo=git+file://"+u, 112 "-i", `{{ (datasource "repo" "//config.json" ).foo.bar }}`, 113 ).run() 114 assertSuccess(t, o, e, err, "baz") 115 116 // subdir in datasource URL, relative subpath 117 o, e, err = cmd(t, 118 "-d", "repo=git+file://"+u+"//subdir/", 119 "-i", `{{ include "repo" "foo.txt" }}`, 120 ).run() 121 assertSuccess(t, o, e, err, "hello world") 122 123 // ds URL ends with /, relative subpath beginning with .// is preferred 124 o, e, err = cmd(t, 125 "-d", "repo=git+file://"+u+"/", 126 "-i", `{{ include "repo" ".//subdir/foo.txt" }}`, 127 ).run() 128 assertSuccess(t, o, e, err, "hello world") 129 } 130 131 func TestDatasources_GitDatasource(t *testing.T) { 132 if isWindows { 133 t.Skip("not going to run git daemon on Windows") 134 } 135 136 addr := startGitDaemon(t) 137 138 o, e, err := cmd(t, 139 "-c", "config=git://"+addr+"/repo//config.json", 140 "-i", `{{ .config.foo.bar}}`, 141 ).run() 142 assertSuccess(t, o, e, err, "baz") 143 } 144 145 func TestDatasources_GitHTTPDatasource(t *testing.T) { 146 o, e, err := cmd(t, 147 "-c", "short=git+https://github.com/git-fixtures/basic//json/short.json", 148 "-i", `{{ .short.glossary.title}}`, 149 ).run() 150 assertSuccess(t, o, e, err, "example glossary") 151 152 // and one with a default branch of 'main' 153 o, e, err = cmd(t, 154 "-c", "data=git+https://github.com/hairyhenderson/git-fixtures.git//small_test.json", 155 "-i", `{{ .data.foo}}`, 156 ).run() 157 assertSuccess(t, o, e, err, "bar") 158 } 159 160 func TestDatasources_GitSSHDatasource(t *testing.T) { 161 if os.Getenv("SSH_AUTH_SOCK") == "" { 162 t.Skip("SSH Agent not running") 163 } 164 o, e, err := cmd(t, 165 "-c", "short=git+ssh://git@github.com/git-fixtures/basic//json/short.json", 166 "-i", `{{ .short.glossary.title}}`, 167 ).run() 168 assertSuccess(t, o, e, err, "example glossary") 169 }