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  }