[ARVADOS] updated: b93018f033f37a7a7b719fd7dc6d5b3ad4a0f797
git at public.curoverse.com
git at public.curoverse.com
Mon Mar 16 17:16:05 EDT 2015
Summary of changes:
services/api/app/models/repository.rb | 10 +-
services/api/test/fixtures/repositories.yml | 14 +++
services/api/test/unit/repository_test.rb | 12 ++-
services/arv-git-httpd/auth_handler.go | 4 -
services/arv-git-httpd/doc.go | 22 ++++
services/arv-git-httpd/main.go | 8 ++
services/arv-git-httpd/server.go | 10 +-
services/arv-git-httpd/server_test.go | 152 ++++++++++++++++++++++++++++
8 files changed, 221 insertions(+), 11 deletions(-)
create mode 100644 services/arv-git-httpd/server_test.go
via b93018f033f37a7a7b719fd7dc6d5b3ad4a0f797 (commit)
via c106899198b67d1071ccf164ce743b651981f8cd (commit)
via eb68ddf0ab91faf6ce1dbab4b8db81b56ffeccaf (commit)
from 16421a1aa8d420728b51d7cbb1b006a5613f8697 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
commit b93018f033f37a7a7b719fd7dc6d5b3ad4a0f797
Author: Tom Clegg <tom at curoverse.com>
Date: Mon Mar 16 17:17:07 2015 -0400
5416: Allow users with repo write permission to update modified_at.
diff --git a/services/api/app/models/repository.rb b/services/api/app/models/repository.rb
index f159b48..0189ee7 100644
--- a/services/api/app/models/repository.rb
+++ b/services/api/app/models/repository.rb
@@ -22,7 +22,15 @@ class Repository < ArvadosModel
def permission_to_create
current_user and current_user.is_admin
end
+
def permission_to_update
- current_user and current_user.is_admin
+ return false if not current_user
+ return true if current_user.is_admin
+ # For normal objects, this is a way to check whether you have
+ # write permission. Repositories should be brought closer to the
+ # normal permission model during #4253. Meanwhile, we'll
+ # special-case this so arv-git-httpd can detect write permission:
+ return super if changed_attributes.keys - ['modified_at', 'updated_at'] == []
+ false
end
end
diff --git a/services/api/test/fixtures/repositories.yml b/services/api/test/fixtures/repositories.yml
index a0e3b1f..b80414d 100644
--- a/services/api/test/fixtures/repositories.yml
+++ b/services/api/test/fixtures/repositories.yml
@@ -2,33 +2,47 @@ crunch_dispatch_test:
uuid: zzzzz-s0uqq-382brsig8rp3665
owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz # active user
name: crunch_dispatch_test
+ created_at: 2015-01-01T00:00:00.123456Z
+ modified_at: 2015-01-01T00:00:00.123456Z
arvados:
uuid: zzzzz-s0uqq-arvadosrepo0123
owner_uuid: zzzzz-tpzed-000000000000000 # root
name: arvados
+ created_at: 2015-01-01T00:00:00.123456Z
+ modified_at: 2015-01-01T00:00:00.123456Z
foo:
uuid: zzzzz-s0uqq-382brsig8rp3666
owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz # active user
name: foo
+ created_at: 2015-01-01T00:00:00.123456Z
+ modified_at: 2015-01-01T00:00:00.123456Z
repository2:
uuid: zzzzz-s0uqq-382brsig8rp3667
owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz # active user
name: foo2
+ created_at: 2015-01-01T00:00:00.123456Z
+ modified_at: 2015-01-01T00:00:00.123456Z
repository3:
uuid: zzzzz-s0uqq-38orljkqpyo1j61
owner_uuid: zzzzz-tpzed-d9tiejq69daie8f # admin user
name: foo3
+ created_at: 2015-01-01T00:00:00.123456Z
+ modified_at: 2015-01-01T00:00:00.123456Z
repository4:
uuid: zzzzz-s0uqq-38oru8hnk57ht34
owner_uuid: zzzzz-tpzed-d9tiejq69daie8f # admin user
name: foo4
+ created_at: 2015-01-01T00:00:00.123456Z
+ modified_at: 2015-01-01T00:00:00.123456Z
auto_setup_repository:
uuid: zzzzz-s0uqq-382brabc8rp3667
owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz # active user
name: auto_setup_repo
+ created_at: 2015-01-01T00:00:00.123456Z
+ modified_at: 2015-01-01T00:00:00.123456Z
diff --git a/services/api/test/unit/repository_test.rb b/services/api/test/unit/repository_test.rb
index 327170c..fe99dd4 100644
--- a/services/api/test/unit/repository_test.rb
+++ b/services/api/test/unit/repository_test.rb
@@ -1,7 +1,13 @@
require 'test_helper'
class RepositoryTest < ActiveSupport::TestCase
- # test "the truth" do
- # assert true
- # end
+ test 'write permission allows changing modified_at' do
+ act_as_user users(:active) do
+ r = repositories(:foo)
+ modtime_was = r.modified_at
+ r.modified_at = Time.now
+ assert r.save
+ assert_operator modtime_was, :<, r.modified_at
+ end
+ end
end
commit c106899198b67d1071ccf164ce743b651981f8cd
Author: Tom Clegg <tom at curoverse.com>
Date: Mon Mar 16 16:27:06 2015 -0400
5416: Add integration tests.
diff --git a/services/arv-git-httpd/auth_handler.go b/services/arv-git-httpd/auth_handler.go
index f182bca..3d29993 100644
--- a/services/arv-git-httpd/auth_handler.go
+++ b/services/arv-git-httpd/auth_handler.go
@@ -13,10 +13,6 @@ import (
)
func newArvadosClient() interface{} {
- // MakeArvadosClient returns an error if token is unset (even
- // though we don't need to do anything requiring
- // authentication yet).
- os.Setenv("ARVADOS_API_TOKEN", "xxx")
arv, err := arvadosclient.MakeArvadosClient()
if err != nil {
log.Println("MakeArvadosClient:", err)
diff --git a/services/arv-git-httpd/main.go b/services/arv-git-httpd/main.go
index 47758f6..0e92393 100644
--- a/services/arv-git-httpd/main.go
+++ b/services/arv-git-httpd/main.go
@@ -26,6 +26,14 @@ func init() {
}
flag.StringVar(&theConfig.Root, "repo-root", cwd,
"Path to git repositories.")
+
+ // MakeArvadosClient returns an error if token is unset (even
+ // though we don't need to do anything requiring
+ // authentication yet). We can't do this in newArvadosClient()
+ // just before calling MakeArvadosClient(), though, because
+ // that interferes with the env var needed by "run test
+ // servers".
+ os.Setenv("ARVADOS_API_TOKEN", "xxx")
}
func main() {
diff --git a/services/arv-git-httpd/server.go b/services/arv-git-httpd/server.go
index 393b6c4..716b276 100644
--- a/services/arv-git-httpd/server.go
+++ b/services/arv-git-httpd/server.go
@@ -13,7 +13,7 @@ type server struct {
Addr string // host:port where the server is listening.
err error
cond *sync.Cond
- done bool
+ running bool
listener *net.TCPListener
wantDown bool
}
@@ -54,13 +54,14 @@ func (srv *server) Start() error {
mutex := &sync.RWMutex{}
srv.cond = sync.NewCond(mutex.RLocker())
+ srv.running = true
go func() {
err = srv.Serve(tcpKeepAliveListener{srv.listener})
if !srv.wantDown {
srv.err = err
}
mutex.Lock()
- srv.done = true
+ srv.running = false
srv.cond.Broadcast()
mutex.Unlock()
}()
@@ -69,9 +70,12 @@ func (srv *server) Start() error {
// Wait returns when the server has shut down.
func (srv *server) Wait() error {
+ if srv.cond == nil {
+ return nil
+ }
srv.cond.L.Lock()
defer srv.cond.L.Unlock()
- for !srv.done {
+ for srv.running {
srv.cond.Wait()
}
return srv.err
diff --git a/services/arv-git-httpd/server_test.go b/services/arv-git-httpd/server_test.go
new file mode 100644
index 0000000..c3eed3d
--- /dev/null
+++ b/services/arv-git-httpd/server_test.go
@@ -0,0 +1,152 @@
+package main
+
+import (
+ "errors"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "strings"
+ "testing"
+
+ check "gopkg.in/check.v1"
+ "git.curoverse.com/arvados.git/sdk/go/arvadostest"
+)
+
+var _ = check.Suite(&IntegrationSuite{})
+
+// IntegrationSuite tests need an API server and an arv-git-httpd server
+type IntegrationSuite struct {
+ tmpRepoRoot string
+ tmpWorkdir string
+ testServer *server
+}
+
+func (s *IntegrationSuite) TestReadonly(c *check.C) {
+ // Spectator token
+ os.Setenv("ARVADOS_API_TOKEN", "zw2f4gwx8hw8cjre7yp6v1zylhrhn3m5gvjq73rtpwhmknrybu")
+ err := s.runGit(c, "fetch", "foo.git")
+ c.Assert(err, check.Equals, nil)
+ err = s.runGit(c, "push", "foo.git", "master:newbranchfail")
+ c.Assert(err, check.ErrorMatches, `.*HTTP code = 403.*`)
+ _, err = os.Stat(s.tmpRepoRoot + "/.git/refs/heads/newbranchfail")
+ c.Assert(err, check.FitsTypeOf, &os.PathError{})
+}
+
+func (s *IntegrationSuite) TestReadwrite(c *check.C) {
+ // Active user token
+ os.Setenv("ARVADOS_API_TOKEN", "3kg6k6lzmp9kj5cpkcoxie963cmvjahbt2fod9zru30k1jqdmi")
+ err := s.runGit(c, "fetch", "foo.git")
+ c.Assert(err, check.Equals, nil)
+ err = s.runGit(c, "push", "foo.git", "master:newbranch")
+ c.Assert(err, check.Equals, nil)
+ _, err = os.Stat(s.tmpRepoRoot + "/foo/.git/refs/heads/newbranch")
+ c.Assert(err, check.Equals, nil)
+}
+
+func (s *IntegrationSuite) TestNonexistent(c *check.C) {
+ // Spectator token
+ os.Setenv("ARVADOS_API_TOKEN", "zw2f4gwx8hw8cjre7yp6v1zylhrhn3m5gvjq73rtpwhmknrybu")
+ err := s.runGit(c, "fetch", "thisrepodoesnotexist.git")
+ c.Assert(err, check.ErrorMatches, `.* not found:.*`)
+}
+
+func (s *IntegrationSuite) TestNoPermission(c *check.C) {
+ // Anonymous token
+ os.Setenv("ARVADOS_API_TOKEN", "4kg6k6lzmp9kj4cpkcoxie964cmvjahbt4fod9zru44k4jqdmi")
+ for _, repo := range []string{"foo.git", "foo/.git", "foo/bar.git", "foo/bar/.git"} {
+ err := s.runGit(c, "fetch", repo)
+ c.Assert(err, check.ErrorMatches, `.* not found:.*`)
+ }
+}
+
+func (s *IntegrationSuite) SetUpSuite(c *check.C) {
+ arvadostest.StartAPI()
+}
+
+func (s *IntegrationSuite) SetUpTest(c *check.C) {
+ arvadostest.ResetEnv()
+ s.testServer = &server{}
+ var err error
+ s.tmpRepoRoot, err = ioutil.TempDir("", "arv-git-httpd")
+ c.Assert(err, check.Equals, nil)
+ s.tmpWorkdir, err = ioutil.TempDir("", "arv-git-httpd")
+ c.Assert(err, check.Equals, nil)
+ _, err = exec.Command("git", "init", "--bare", s.tmpRepoRoot + "/arvados.git").Output()
+ c.Assert(err, check.Equals, nil)
+ _, err = exec.Command("git", "--git-dir", s.tmpRepoRoot + "/arvados.git", "fetch", "../../.git", "master:master").Output()
+ c.Assert(err, check.Equals, nil)
+ _, err = exec.Command("git", "init", s.tmpRepoRoot + "/foo").Output()
+ c.Assert(err, check.Equals, nil)
+ _, err = exec.Command("sh", "-c", "cd " + s.tmpRepoRoot + "/foo && echo test >test && git add test && git commit -am 'foo: test'").CombinedOutput()
+ c.Assert(err, check.Equals, nil)
+ _, err = exec.Command("git", "init", s.tmpWorkdir).Output()
+ c.Assert(err, check.Equals, nil)
+ _, err = exec.Command("sh", "-c", "cd " + s.tmpWorkdir + " && echo work >work && git add work && git commit -am 'workdir: test'").CombinedOutput()
+ c.Assert(err, check.Equals, nil)
+
+ theConfig = &config{
+ Addr: ":",
+ GitCommand: "/usr/bin/git",
+ Root: s.tmpRepoRoot,
+ }
+ err = s.testServer.Start()
+ c.Assert(err, check.Equals, nil)
+
+ // Clear ARVADOS_API_TOKEN after starting up the server, to
+ // make sure arv-git-httpd doesn't use it.
+ os.Setenv("ARVADOS_API_TOKEN", "")
+
+ _, err = exec.Command("git", "config",
+ "--file", s.tmpWorkdir + "/.git/config",
+ "credential.http://" + s.testServer.Addr + "/.helper",
+ "!foo(){ echo password=$ARVADOS_API_TOKEN; };foo").Output()
+ c.Assert(err, check.Equals, nil)
+ _, err = exec.Command("git", "config",
+ "--file", s.tmpWorkdir + "/.git/config",
+ "credential.http://" + s.testServer.Addr + "/.username",
+ "none").Output()
+ c.Assert(err, check.Equals, nil)
+}
+
+func (s *IntegrationSuite) TearDownTest(c *check.C) {
+ var err error
+ if s.testServer != nil {
+ err = s.testServer.Close()
+ }
+ c.Check(err, check.Equals, nil)
+ if s.tmpRepoRoot != "" {
+ err = os.RemoveAll(s.tmpRepoRoot)
+ c.Check(err, check.Equals, nil)
+ }
+ if s.tmpWorkdir != "" {
+ err = os.RemoveAll(s.tmpWorkdir)
+ c.Check(err, check.Equals, nil)
+ }
+}
+
+func (s *IntegrationSuite) runGit(c *check.C, gitCmd, repo string, args ...string) error {
+ cwd, err := os.Getwd()
+ c.Assert(err, check.Equals, nil)
+ defer os.Chdir(cwd)
+ os.Chdir(s.tmpWorkdir)
+
+ gitargs := append([]string{
+ gitCmd, "http://" + s.testServer.Addr + "/" + repo,
+ }, args...)
+ cmd := exec.Command("git", gitargs...)
+ w, err := cmd.StdinPipe()
+ c.Assert(err, check.Equals, nil)
+ go w.Close()
+ output, err := cmd.CombinedOutput()
+ c.Log("git ", gitargs, " => ", err)
+ if err != nil {
+ // Easier to match error strings without newlines.
+ err = errors.New(strings.Replace(string(output), "\n", " // ", -1))
+ }
+ return err
+}
+
+// Gocheck boilerplate
+func Test(t *testing.T) {
+ check.TestingT(t)
+}
commit eb68ddf0ab91faf6ce1dbab4b8db81b56ffeccaf
Author: Tom Clegg <tom at curoverse.com>
Date: Mon Mar 16 10:18:08 2015 -0400
5416: Add options to docs.
diff --git a/services/arv-git-httpd/doc.go b/services/arv-git-httpd/doc.go
index 21e8e48..713b018 100644
--- a/services/arv-git-httpd/doc.go
+++ b/services/arv-git-httpd/doc.go
@@ -3,5 +3,27 @@ arv-git-httpd provides authenticated access to Arvados-hosted git repositories.
Example:
arv-git-httpd -address=:8000 -repo-root=/var/lib/arvados/git
+
+Options:
+
+ -address [host]:[port]
+
+ Listen at the given host and port. Each can be a name,
+ a number, or empty.
+
+ -repo-root path
+
+ Directory containing git repositories. When a client
+ requests either "foo/bar.git" or "foo/bar/.git",
+ git-http-backend will be invoked on "path/foo/bar.git"
+ or (if that doesn't exist) "path/foo/bar/.git".
+
+ -git-command path
+
+ Location of the CGI program to execute for each
+ authorized request (normally this is git). It is
+ invoked with a single argument, 'http-backend'.
+ Default is /usr/bin/git.
+
*/
package main
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list