// Copyright (C) The Arvados Authors. All rights reserved. // // SPDX-License-Identifier: AGPL-3.0 package crunchrun import ( "io/ioutil" "net/url" "os" "path/filepath" "git.arvados.org/arvados.git/lib/config" "git.arvados.org/arvados.git/sdk/go/arvados" "git.arvados.org/arvados.git/sdk/go/arvadostest" "git.arvados.org/arvados.git/sdk/go/ctxlog" check "gopkg.in/check.v1" git_client "gopkg.in/src-d/go-git.v4/plumbing/transport/client" git_http "gopkg.in/src-d/go-git.v4/plumbing/transport/http" ) type GitMountSuite struct { tmpdir string } var _ = check.Suite(&GitMountSuite{}) func (s *GitMountSuite) SetUpTest(c *check.C) { s.useTestGitServer(c) var err error s.tmpdir, err = ioutil.TempDir("", "") c.Assert(err, check.IsNil) } func (s *GitMountSuite) TearDownTest(c *check.C) { err := os.RemoveAll(s.tmpdir) c.Check(err, check.IsNil) } // Commit fd3531f is crunch-run-tree-test func (s *GitMountSuite) TestextractTree(c *check.C) { gm := gitMount{ Path: "/", UUID: arvadostest.Repository2UUID, Commit: "fd3531f42995344f36c30b79f55f27b502f3d344", } err := gm.extractTree(&ArvTestClient{}, s.tmpdir, arvadostest.ActiveToken) c.Check(err, check.IsNil) fnm := filepath.Join(s.tmpdir, "dir1/dir2/file with mode 0644") data, err := ioutil.ReadFile(fnm) c.Check(err, check.IsNil) c.Check(data, check.DeepEquals, []byte{0, 1, 2, 3}) fi, err := os.Stat(fnm) c.Check(err, check.IsNil) if err == nil { c.Check(fi.Mode(), check.Equals, os.FileMode(0644)) } fnm = filepath.Join(s.tmpdir, "dir1/dir2/file with mode 0755") data, err = ioutil.ReadFile(fnm) c.Check(err, check.IsNil) c.Check(string(data), check.DeepEquals, "#!/bin/sh\nexec echo OK\n") fi, err = os.Stat(fnm) c.Check(err, check.IsNil) if err == nil { c.Check(fi.Mode(), check.Equals, os.FileMode(0755)) } // Ensure there's no extra stuff like a ".git" dir s.checkTmpdirContents(c, []string{"dir1"}) // Ensure tmpdir is world-readable and world-executable so the // UID inside the container can use it. fi, err = os.Stat(s.tmpdir) c.Check(err, check.IsNil) c.Check(fi.Mode()&os.ModePerm, check.Equals, os.FileMode(0755)) } // Commit 5ebfab0 is not the tip of any branch or tag, but is // reachable in branch "crunch-run-non-tip-test". func (s *GitMountSuite) TestExtractNonTipCommit(c *check.C) { gm := gitMount{ UUID: arvadostest.Repository2UUID, Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e", } err := gm.extractTree(&ArvTestClient{}, s.tmpdir, arvadostest.ActiveToken) c.Check(err, check.IsNil) fnm := filepath.Join(s.tmpdir, "file only on testbranch") data, err := ioutil.ReadFile(fnm) c.Check(err, check.IsNil) c.Check(string(data), check.DeepEquals, "testfile\n") } func (s *GitMountSuite) TestNonexistentRepository(c *check.C) { gm := gitMount{ Path: "/", UUID: "zzzzz-s0uqq-nonexistentrepo", Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e", } err := gm.extractTree(&ArvTestClient{}, s.tmpdir, arvadostest.ActiveToken) c.Check(err, check.NotNil) c.Check(err, check.ErrorMatches, ".*repository not found.*") s.checkTmpdirContents(c, []string{}) } func (s *GitMountSuite) TestNonexistentCommit(c *check.C) { gm := gitMount{ Path: "/", UUID: arvadostest.Repository2UUID, Commit: "bb66b6bb6b6bbb6b6b6b66b6b6b6b6b6b6b6b66b", } err := gm.extractTree(&ArvTestClient{}, s.tmpdir, arvadostest.ActiveToken) c.Check(err, check.NotNil) c.Check(err, check.ErrorMatches, ".*object not found.*") s.checkTmpdirContents(c, []string{}) } func (s *GitMountSuite) TestGitUrlDiscoveryFails(c *check.C) { delete(discoveryMap, "gitUrl") gm := gitMount{ Path: "/", UUID: arvadostest.Repository2UUID, Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e", } err := gm.extractTree(&ArvTestClient{}, s.tmpdir, arvadostest.ActiveToken) c.Check(err, check.ErrorMatches, ".*gitUrl.*") } func (s *GitMountSuite) TestInvalid(c *check.C) { for _, trial := range []struct { gm gitMount matcher string }{ { gm: gitMount{ Path: "/", UUID: arvadostest.Repository2UUID, Commit: "abc123", }, matcher: ".*SHA1.*", }, { gm: gitMount{ Path: "/", UUID: arvadostest.Repository2UUID, RepositoryName: arvadostest.Repository2Name, Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e", }, matcher: ".*repository_name.*", }, { gm: gitMount{ Path: "/", GitURL: "https://localhost:0/" + arvadostest.Repository2Name + ".git", Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e", }, matcher: ".*git_url.*", }, { gm: gitMount{ Path: "/dir1/", UUID: arvadostest.Repository2UUID, Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e", }, matcher: ".*path.*", }, { gm: gitMount{ Path: "/", Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e", }, matcher: ".*UUID.*", }, { gm: gitMount{ Path: "/", UUID: arvadostest.Repository2UUID, Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e", Writable: true, }, matcher: ".*writable.*", }, } { err := trial.gm.extractTree(&ArvTestClient{}, s.tmpdir, arvadostest.ActiveToken) c.Check(err, check.NotNil) s.checkTmpdirContents(c, []string{}) err = trial.gm.validate() c.Check(err, check.ErrorMatches, trial.matcher) } } func (s *GitMountSuite) checkTmpdirContents(c *check.C, expect []string) { f, err := os.Open(s.tmpdir) c.Check(err, check.IsNil) names, err := f.Readdirnames(-1) c.Check(err, check.IsNil) c.Check(names, check.DeepEquals, expect) } func (*GitMountSuite) useTestGitServer(c *check.C) { git_client.InstallProtocol("https", git_http.NewClient(arvados.InsecureHTTPClient)) loader := config.NewLoader(nil, ctxlog.TestLogger(c)) cfg, err := loader.Load() c.Assert(err, check.IsNil) cluster, err := cfg.GetCluster("") c.Assert(err, check.IsNil) discoveryMap["gitUrl"] = (*url.URL)(&cluster.Services.GitHTTP.ExternalURL).String() }