From: Tom Clegg Date: Tue, 12 Apr 2022 15:54:26 +0000 (-0400) Subject: 18700: Merge branch 'main' X-Git-Tag: 2.5.0~214^2~1 X-Git-Url: https://git.arvados.org/arvados.git/commitdiff_plain/b53513423ab948804425424278ac554870864997?hp=-c 18700: Merge branch 'main' Arvados-DCO-1.1-Signed-off-by: Tom Clegg --- b53513423ab948804425424278ac554870864997 diff --combined cmd/arvados-server/cmd.go index c5465ee561,13b06d6795..26c3f485ea --- a/cmd/arvados-server/cmd.go +++ b/cmd/arvados-server/cmd.go @@@ -5,10 -5,6 +5,10 @@@ package main import ( + "encoding/json" + "fmt" + "io" + "net/http" "os" "git.arvados.org/arvados.git/lib/boot" @@@ -21,6 -17,7 +21,7 @@@ "git.arvados.org/arvados.git/lib/install" "git.arvados.org/arvados.git/lib/lsf" "git.arvados.org/arvados.git/lib/recovercollection" + "git.arvados.org/arvados.git/services/keepproxy" "git.arvados.org/arvados.git/services/keepstore" "git.arvados.org/arvados.git/services/ws" ) @@@ -42,9 -39,9 +43,10 @@@ var "dispatch-lsf": lsf.DispatchCommand, "install": install.Command, "init": install.InitCommand, + "keepproxy": keepproxy.Command, "keepstore": keepstore.Command, "recover-collection": recovercollection.Command, + "workbench2": wb2command{}, "ws": ws.Command, }) ) @@@ -52,31 -49,3 +54,31 @@@ func main() { os.Exit(handler.RunCommand(os.Args[0], os.Args[1:], os.Stdin, os.Stdout, os.Stderr)) } + +type wb2command struct{} + +func (wb2command) RunCommand(prog string, args []string, stdin io.Reader, stdout, stderr io.Writer) int { + if len(args) != 3 { + fmt.Fprintf(stderr, "usage: %s api-host listen-addr app-dir\n", prog) + return 1 + } + configJSON, err := json.Marshal(map[string]string{"API_HOST": args[0]}) + if err != nil { + fmt.Fprintf(stderr, "json.Marshal: %s\n", err) + return 1 + } + mux := http.NewServeMux() + mux.Handle("/", http.FileServer(http.Dir(args[2]))) + mux.HandleFunc("/config.json", func(w http.ResponseWriter, _ *http.Request) { + w.Write(configJSON) + }) + mux.HandleFunc("/_health/ping", func(w http.ResponseWriter, _ *http.Request) { + io.WriteString(w, `{"health":"OK"}`) + }) + err = http.ListenAndServe(args[1], mux) + if err != nil { + fmt.Fprintln(stderr, err.Error()) + return 1 + } + return 0 +} diff --combined lib/boot/supervisor.go index 323f672348,526411c41f..7daceccb93 --- a/lib/boot/supervisor.go +++ b/lib/boot/supervisor.go @@@ -42,9 -42,7 +42,9 @@@ type Supervisor struct ClusterType string // e.g., production ListenHost string // e.g., localhost ControllerAddr string // e.g., 127.0.0.1:8000 + Workbench2Source string // e.g., /home/username/src/arvados-workbench2 NoWorkbench1 bool + NoWorkbench2 bool OwnTemporaryDatabase bool Stderr io.Writer @@@ -60,8 -58,8 +60,8 @@@ waitShutdown sync.WaitGroup bindir string - tempdir string - wwwtempdir string + tempdir string // in production mode, this is accessible only to root + wwwtempdir string // in production mode, this is accessible only to www-data configfile string environ []string // for child processes } @@@ -246,7 -244,7 +246,7 @@@ func (super *Supervisor) run(cfg *arvad runServiceCommand{name: "controller", svc: super.cluster.Services.Controller, depends: []supervisedTask{seedDatabase{}}}, runGoProgram{src: "services/arv-git-httpd", svc: super.cluster.Services.GitHTTP}, runGoProgram{src: "services/health", svc: super.cluster.Services.Health}, - runGoProgram{src: "services/keepproxy", svc: super.cluster.Services.Keepproxy, depends: []supervisedTask{runPassenger{src: "services/api"}}}, + runServiceCommand{name: "keepproxy", svc: super.cluster.Services.Keepproxy, depends: []supervisedTask{runPassenger{src: "services/api"}}}, runServiceCommand{name: "keepstore", svc: super.cluster.Services.Keepstore}, runGoProgram{src: "services/keep-web", svc: super.cluster.Services.WebDAV}, runServiceCommand{name: "ws", svc: super.cluster.Services.Websocket, depends: []supervisedTask{seedDatabase{}}}, @@@ -260,11 -258,6 +260,11 @@@ runPassenger{src: "apps/workbench", varlibdir: "workbench1", svc: super.cluster.Services.Workbench1, depends: []supervisedTask{installPassenger{src: "apps/workbench"}}}, ) } + if !super.NoWorkbench2 { + tasks = append(tasks, + runWorkbench2{svc: super.cluster.Services.Workbench2}, + ) + } if super.ClusterType != "test" { tasks = append(tasks, runServiceCommand{name: "dispatch-cloud", svc: super.cluster.Services.DispatchCloud}, @@@ -489,7 -482,6 +489,7 @@@ type runOptions struct output io.Writer // attach stdout env []string // add/replace environment variables user string // run as specified user + stdin io.Reader } // RunProgram runs prog with args, using dir as working directory. If ctx is @@@ -533,7 -525,6 +533,7 @@@ func (super *Supervisor) RunProgram(ct } cmd := exec.Command(super.lookPath(prog), args...) + cmd.Stdin = opts.stdin stdout, err := cmd.StdoutPipe() if err != nil { return err @@@ -637,40 -628,32 +637,40 @@@ func (super *Supervisor) autofillConfig return err } usedPort := map[string]bool{} - nextPort := func(host string) string { + nextPort := func(host string) (string, error) { for { port, err := availablePort(host) if err != nil { - panic(err) + port, err = availablePort(super.ListenHost) + } + if err != nil { + return "", err } if usedPort[port] { continue } usedPort[port] = true - return port + return port, nil } } if cluster.Services.Controller.ExternalURL.Host == "" { h, p, err := net.SplitHostPort(super.ControllerAddr) if err != nil { - return err + return fmt.Errorf("SplitHostPort(ControllerAddr): %w", err) } if h == "" { h = super.ListenHost } if p == "0" { - p = nextPort(h) + p, err = nextPort(h) + if err != nil { + return err + } } cluster.Services.Controller.ExternalURL = arvados.URL{Scheme: "https", Host: net.JoinHostPort(h, p), Path: "/"} } + u := url.URL(cluster.Services.Controller.ExternalURL) + defaultExtHost := u.Hostname() for _, svc := range []*arvados.Service{ &cluster.Services.Controller, &cluster.Services.DispatchCloud, @@@ -683,32 -666,24 +683,32 @@@ &cluster.Services.WebDAVDownload, &cluster.Services.Websocket, &cluster.Services.Workbench1, + &cluster.Services.Workbench2, } { if svc == &cluster.Services.DispatchCloud && super.ClusterType == "test" { continue } if svc.ExternalURL.Host == "" { + port, err := nextPort(defaultExtHost) + if err != nil { + return err + } + host := net.JoinHostPort(defaultExtHost, port) if svc == &cluster.Services.Controller || svc == &cluster.Services.GitHTTP || svc == &cluster.Services.Health || svc == &cluster.Services.Keepproxy || svc == &cluster.Services.WebDAV || svc == &cluster.Services.WebDAVDownload || - svc == &cluster.Services.Workbench1 { - svc.ExternalURL = arvados.URL{Scheme: "https", Host: fmt.Sprintf("%s:%s", super.ListenHost, nextPort(super.ListenHost)), Path: "/"} + svc == &cluster.Services.Workbench1 || + svc == &cluster.Services.Workbench2 { + svc.ExternalURL = arvados.URL{Scheme: "https", Host: host, Path: "/"} } else if svc == &cluster.Services.Websocket { - svc.ExternalURL = arvados.URL{Scheme: "wss", Host: fmt.Sprintf("%s:%s", super.ListenHost, nextPort(super.ListenHost)), Path: "/websocket"} + svc.ExternalURL = arvados.URL{Scheme: "wss", Host: host, Path: "/websocket"} } } - if super.NoWorkbench1 && svc == &cluster.Services.Workbench1 { + if super.NoWorkbench1 && svc == &cluster.Services.Workbench1 || + super.NoWorkbench2 && svc == &cluster.Services.Workbench2 { // When workbench1 is disabled, it gets an // ExternalURL (so we have a valid listening // port to write in our Nginx config) but no @@@ -717,13 -692,8 +717,13 @@@ continue } if len(svc.InternalURLs) == 0 { + port, err := nextPort(super.ListenHost) + if err != nil { + return err + } + host := net.JoinHostPort(super.ListenHost, port) svc.InternalURLs = map[arvados.URL]arvados.ServiceInstance{ - {Scheme: "http", Host: fmt.Sprintf("%s:%s", super.ListenHost, nextPort(super.ListenHost)), Path: "/"}: {}, + {Scheme: "http", Host: host, Path: "/"}: {}, } } } @@@ -751,12 -721,7 +751,12 @@@ } if super.ClusterType == "test" { // Add a second keepstore process. - cluster.Services.Keepstore.InternalURLs[arvados.URL{Scheme: "http", Host: fmt.Sprintf("%s:%s", super.ListenHost, nextPort(super.ListenHost)), Path: "/"}] = arvados.ServiceInstance{} + port, err := nextPort(super.ListenHost) + if err != nil { + return err + } + host := net.JoinHostPort(super.ListenHost, port) + cluster.Services.Keepstore.InternalURLs[arvados.URL{Scheme: "http", Host: host, Path: "/"}] = arvados.ServiceInstance{} // Create a directory-backed volume for each keepstore // process. @@@ -790,14 -755,10 +790,14 @@@ } } if super.OwnTemporaryDatabase { + port, err := nextPort("localhost") + if err != nil { + return err + } cluster.PostgreSQL.Connection = arvados.PostgreSQLConnection{ "client_encoding": "utf8", - "host": super.ListenHost, - "port": nextPort(super.ListenHost), + "host": "localhost", + "port": port, "dbname": "arvados_test", "user": "arvados", "password": "insecure_arvados_test", diff --combined lib/config/export.go index a20c5b2c32,dae749c874..8e23f07328 --- a/lib/config/export.go +++ b/lib/config/export.go @@@ -133,6 -133,7 +133,7 @@@ var whitelist = map[string]bool "Containers.MaxDispatchAttempts": false, "Containers.MaxRetryAttempts": true, "Containers.MinRetryPeriod": true, + "Containers.PreemptiblePriceFactor": false, "Containers.ReserveExtraRAM": true, "Containers.RuntimeEngine": true, "Containers.ShellAccess": true, @@@ -219,9 -220,6 +220,9 @@@ "SystemLogs": false, "SystemRootToken": false, "TLS": false, + "TLS.Certificate": false, + "TLS.Insecure": true, + "TLS.Key": false, "Users": true, "Users.ActivatedUsersAreVisibleToOthers": false, "Users.AdminNotifierEmailFrom": false, diff --combined lib/controller/integration_test.go index 6ffbbd2720,b71c4afb55..50cf89c0d4 --- a/lib/controller/integration_test.go +++ b/lib/controller/integration_test.go @@@ -135,7 -135,6 +135,7 @@@ func (s *IntegrationSuite) SetUpSuite( filepath.Join(cwd, "..", ".."), id, cfg, "127.0.0."+id[3:], c.Log) tc.Super.NoWorkbench1 = true + tc.Super.NoWorkbench2 = true tc.Start() s.testClusters[id] = tc } @@@ -380,6 -379,56 +380,56 @@@ func (s *IntegrationSuite) TestGetColle c.Check(coll.PortableDataHash, check.Equals, pdh) } + // z3333 should forward the locally-issued anonymous user token to its login + // cluster z1111. That is no problem because the login cluster controller will + // map any anonymous user token to its local anonymous user. + // + // This needs to work because wb1 has a tendency to slap the local anonymous + // user token on every request as a reader_token, which gets folded into the + // request token list controller. + // + // Use a z1111 user token and the anonymous token from z3333 passed in as a + // reader_token to do a request on z3333, asking for the z1111 anonymous user + // object. The request will be forwarded to the z1111 cluster. The presence of + // the z3333 anonymous user token should not prohibit the request from being + // forwarded. + func (s *IntegrationSuite) TestForwardAnonymousTokenToLoginCluster(c *check.C) { + conn1 := s.testClusters["z1111"].Conn() + s.testClusters["z3333"].Conn() + + rootctx1, _, _ := s.testClusters["z1111"].RootClients() + _, anonac3, _ := s.testClusters["z3333"].AnonymousClients() + + // Make a user connection to z3333 (using a z1111 user, because that's the login cluster) + _, userac1, _, _ := s.testClusters["z3333"].UserClients(rootctx1, c, conn1, "user@example.com", true) + + // Get the anonymous user token for z3333 + var anon3Auth arvados.APIClientAuthorization + err := anonac3.RequestAndDecode(&anon3Auth, "GET", "/arvados/v1/api_client_authorizations/current", nil, nil) + c.Check(err, check.IsNil) + + var userList arvados.UserList + where := make(map[string]string) + where["uuid"] = "z1111-tpzed-anonymouspublic" + err = userac1.RequestAndDecode(&userList, "GET", "/arvados/v1/users", nil, + map[string]interface{}{ + "reader_tokens": []string{anon3Auth.TokenV2()}, + "where": where, + }, + ) + // The local z3333 anonymous token must be allowed to be forwarded to the login cluster + c.Check(err, check.IsNil) + + userac1.AuthToken = "v2/z1111-gj3su-asdfasdfasdfasd/this-token-does-not-validate-so-anonymous-token-will-be-used-instead" + err = userac1.RequestAndDecode(&userList, "GET", "/arvados/v1/users", nil, + map[string]interface{}{ + "reader_tokens": []string{anon3Auth.TokenV2()}, + "where": where, + }, + ) + c.Check(err, check.IsNil) + } + // Get a token from the login cluster (z1111), use it to submit a // container request on z2222. func (s *IntegrationSuite) TestCreateContainerRequestWithFedToken(c *check.C) {