[ARVADOS] updated: 658183e2bca17f5aa281ab95068906c7150b2b73
Git user
git at public.curoverse.com
Thu Feb 2 11:38:10 EST 2017
Summary of changes:
services/boot/arvados_go.go | 45 +++++++++----
services/boot/arvados_packages.go | 33 ++++++++++
services/boot/booter.go | 9 ++-
services/boot/command.go | 13 ++++
services/boot/config.go | 35 +++++++++-
services/boot/consul.go | 63 ++++++++++++++++--
services/boot/controller.go | 7 +-
services/boot/main.go | 7 +-
services/boot/os_package.go | 5 +-
services/boot/package.json | 2 +-
services/boot/supervisor.go | 11 +++-
services/boot/systemd.go | 9 +--
services/boot/vault.go | 132 ++++++++++++++++++++++++++++++++++++++
services/boot/write_file.go | 46 +++++++++++++
14 files changed, 376 insertions(+), 41 deletions(-)
create mode 100644 services/boot/arvados_packages.go
create mode 100644 services/boot/command.go
create mode 100644 services/boot/vault.go
create mode 100644 services/boot/write_file.go
via 658183e2bca17f5aa281ab95068906c7150b2b73 (commit)
via 315fb56f14fbef24204cc424f95ff49a9ee6149b (commit)
via 55ce7e1b9befcde1a7a5be556bed7f6db8a1c098 (commit)
via eb459d42be239bd579634884292d3606896792fd (commit)
from a31038ebef04b7c8473222d90586ff8ae0a4a904 (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 658183e2bca17f5aa281ab95068906c7150b2b73
Author: Tom Clegg <tom at curoverse.com>
Date: Mon Jan 30 10:24:24 2017 -0500
enable consul webgui on :18500
diff --git a/services/boot/arvados_go.go b/services/boot/arvados_go.go
index e23a1d1..3d60dde 100644
--- a/services/boot/arvados_go.go
+++ b/services/boot/arvados_go.go
@@ -28,10 +28,6 @@ type arvadosGoBooter struct {
tmpl string
}
-func availablePort() int {
- return rand.Intn(10000) + 20000
-}
-
func (agb *arvadosGoBooter) Boot(ctx context.Context) error {
cfg := cfg(ctx)
@@ -58,7 +54,9 @@ func (agb *arvadosGoBooter) Boot(ctx context.Context) error {
if err := os.MkdirAll(path.Dir(cfgPath), 0755); err != nil {
return err
}
- if err := atomicWriteFile(cfgPath+".ctmpl", []byte("{}"), 0644); err != nil {
+ // ctmpl := []byte(fmt.Sprintf(`{{tree %q | explode | toJSONPretty}}`, agb.name))
+ ctmpl := []byte(`{}`)
+ if err := atomicWriteFile(cfgPath+".ctmpl", ctmpl, 0644); err != nil {
return err
}
return Series{
diff --git a/services/boot/consul.go b/services/boot/consul.go
index d5e6301..f51d694 100644
--- a/services/boot/consul.go
+++ b/services/boot/consul.go
@@ -61,10 +61,12 @@ func (cb *consulBooter) Boot(ctx context.Context) error {
{
cf := path.Join(cfg.DataDir, "consul-ports.json")
err = atomicWriteJSON(cf, map[string]interface{}{
+ "client_addr": "0.0.0.0",
"bootstrap_expect": len(cfg.ControlHosts),
"data_dir": dataDir,
"datacenter": cfg.SiteID,
"server": true,
+ "ui": true,
"ports": map[string]int{
"dns": cfg.Ports.ConsulDNS,
"http": cfg.Ports.ConsulHTTP,
diff --git a/services/boot/package.json b/services/boot/package.json
index 6e2be8a..7c30502 100644
--- a/services/boot/package.json
+++ b/services/boot/package.json
@@ -14,7 +14,7 @@
"scripts": {
"dev": "WEBPACK_FLAGS=-d go generate && go get ./... && $GOPATH/bin/boot",
"dev-as-root": "WEBPACK_FLAGS=-d go generate && go get ./... && sudo $GOPATH/bin/boot",
- "dev-docker": "WEBPACK_FLAGS=-d go generate && go get ./... && docker build --tag=arvados-boot-test-runit testimage_runit && docker run -it --cap-add=IPC_LOCK --rm --volume=${GOPATH}/bin/boot:/usr/bin/arvados-boot:ro arvados-boot-test-runit",
+ "dev-docker": "WEBPACK_FLAGS=-d go generate && go get ./... && docker build --tag=arvados-boot-test-runit testimage_runit && docker run --rm -it --publish=18500:18500 --cap-add=IPC_LOCK --volume=${GOPATH}/bin/boot:/usr/bin/arvados-boot:ro arvados-boot-test-runit",
"test": "./node_modules/.bin/tap 'js/**/*_test.js'",
"build": "go generate && go get ./...",
"start": "npm run build && $GOPATH/bin/boot",
diff --git a/services/boot/supervisor.go b/services/boot/supervisor.go
index 9ac2532..a8d8a8c 100644
--- a/services/boot/supervisor.go
+++ b/services/boot/supervisor.go
@@ -28,9 +28,10 @@ func newSupervisor(ctx context.Context, name, cmd string, args ...string) superv
}
}
+// supervised by systemd/runit/etc and registered with consul
type supervisedService struct {
- name string
- cmd string
+ name string // name to register with consul
+ cmd string // program to run (absolute path)
args []string
}
@@ -72,3 +73,7 @@ func (s *supervisedService) Boot(ctx context.Context) error {
Port: availablePort(),
})
}
+
+func availablePort() int {
+ return rand.Intn(10000) + 20000
+}
commit 315fb56f14fbef24204cc424f95ff49a9ee6149b
Author: Tom Clegg <tom at curoverse.com>
Date: Sun Jan 29 14:01:38 2017 -0500
fix templated services
diff --git a/services/boot/arvados_go.go b/services/boot/arvados_go.go
index 8a4a10d..e23a1d1 100644
--- a/services/boot/arvados_go.go
+++ b/services/boot/arvados_go.go
@@ -2,6 +2,7 @@ package main
import (
"context"
+ "fmt"
"log"
"math/rand"
"os"
@@ -12,15 +13,19 @@ import (
var (
dispatchLocal = &arvadosGoBooter{name: "crunch-dispatch-local"}
dispatchSLURM = &arvadosGoBooter{name: "crunch-dispatch-slurm"}
- gitHTTP = &arvadosGoBooter{name: "arvados-git-httpd"}
- keepbalance = &arvadosGoBooter{name: "keep-balance"}
+ gitHTTP = &arvadosGoBooter{name: "arvados-git-httpd", conf: "git-httpd"}
+ keepbalance = &arvadosGoBooter{name: "keep-balance", tmpl: keepbalanceTmpl}
keepproxy = &arvadosGoBooter{name: "keepproxy"}
keepstore = &arvadosGoBooter{name: "keepstore"}
- websocket = &arvadosGoBooter{name: "arvados-ws"}
+ websocket = &arvadosGoBooter{name: "arvados-ws", conf: "ws"}
+
+ keepbalanceTmpl = `{"RunPeriod":"1m"}`
)
type arvadosGoBooter struct {
name string
+ conf string
+ tmpl string
}
func availablePort() int {
@@ -29,6 +34,14 @@ func availablePort() int {
func (agb *arvadosGoBooter) Boot(ctx context.Context) error {
cfg := cfg(ctx)
+
+ if agb.conf == "" {
+ agb.conf = agb.name
+ }
+ if agb.tmpl == "" {
+ agb.tmpl = "{}"
+ }
+
cmd := path.Join(cfg.UsrDir, "bin", agb.name)
if _, err := os.Stat(cmd); err != nil {
if found, err := filepath.Glob(path.Join(cfg.UsrDir, "pkg", agb.name+"_*.deb")); err == nil && len(found) > 0 {
@@ -41,8 +54,13 @@ func (agb *arvadosGoBooter) Boot(ctx context.Context) error {
}
}
}
- cfgPath := path.Join("/etc/arvados", agb.name, agb.name+".yml")
- atomicWriteFile(cfgPath+".ctmpl", []byte("{}"), 0644)
+ cfgPath := path.Join("/etc/arvados", agb.conf, agb.conf+".yml")
+ if err := os.MkdirAll(path.Dir(cfgPath), 0755); err != nil {
+ return err
+ }
+ if err := atomicWriteFile(cfgPath+".ctmpl", []byte("{}"), 0644); err != nil {
+ return err
+ }
return Series{
&osPackage{
Debian: agb.name,
@@ -51,8 +69,8 @@ func (agb *arvadosGoBooter) Boot(ctx context.Context) error {
name: agb.name,
cmd: path.Join(cfg.UsrDir, "bin", "consul-template"),
args: []string{
- "-consul-addr=127.0.0.1:8500",
- "-template="+cfgPath+".ctmpl:"+cfgPath,
+ "-consul-addr=" + fmt.Sprintf("0.0.0.0:%d", cfg.Ports.ConsulHTTP),
+ "-template=" + cfgPath + ".ctmpl:" + cfgPath,
"-exec",
agb.name,
},
diff --git a/services/boot/booter.go b/services/boot/booter.go
index 3ca800d..ee37fd0 100644
--- a/services/boot/booter.go
+++ b/services/boot/booter.go
@@ -45,7 +45,14 @@ func (cb Concurrent) Boot(ctx context.Context) error {
i, b := i, b
go func() {
defer wg.Done()
- errs[i] = b.Boot(ctx)
+ err := b.Boot(ctx)
+ switch err.(type) {
+ case nil:
+ case *MultipleError:
+ default:
+ err = fmt.Errorf("%T: %s", b, err)
+ }
+ errs[i] = err
}()
}
wg.Wait()
diff --git a/services/boot/consul.go b/services/boot/consul.go
index 6ad5e6e..d5e6301 100644
--- a/services/boot/consul.go
+++ b/services/boot/consul.go
@@ -80,7 +80,7 @@ func (cb *consulBooter) Boot(ctx context.Context) error {
}
args = append(args, "-config-file="+cf)
}
- supervisor := newSupervisor(ctx, "consul", bin, args...)
+ supervisor := newSupervisor(ctx, "arvados-consul", bin, args...)
running, err := supervisor.Running(ctx)
if err != nil {
return err
diff --git a/services/boot/supervisor.go b/services/boot/supervisor.go
index 2fcb336..9ac2532 100644
--- a/services/boot/supervisor.go
+++ b/services/boot/supervisor.go
@@ -42,7 +42,7 @@ func (s *supervisedService) Boot(ctx context.Context) error {
if _, err := os.Stat(bin); err != nil {
return err
}
- sup := newSupervisor(ctx, s.name, bin)
+ sup := newSupervisor(ctx, s.name, bin, s.args...)
if ok, err := sup.Running(ctx); err != nil {
return err
} else if !ok {
diff --git a/services/boot/vault.go b/services/boot/vault.go
index 85b062a..de9cfb3 100644
--- a/services/boot/vault.go
+++ b/services/boot/vault.go
@@ -53,7 +53,7 @@ func (vb *vaultBooter) Boot(ctx context.Context) error {
}
args := []string{"server", "-config=" + cfgPath}
- supervisor := newSupervisor(ctx, "vault", bin, args...)
+ supervisor := newSupervisor(ctx, "arvados-vault", bin, args...)
running, err := supervisor.Running(ctx)
if err != nil {
return err
commit 55ce7e1b9befcde1a7a5be556bed7f6db8a1c098
Author: Tom Clegg <tom at curoverse.com>
Date: Sun Jan 29 05:54:30 2017 -0500
unseal vault
diff --git a/services/boot/consul.go b/services/boot/consul.go
index e1015ae..6ad5e6e 100644
--- a/services/boot/consul.go
+++ b/services/boot/consul.go
@@ -5,6 +5,8 @@ import (
"fmt"
"os"
"os/exec"
+ "path"
+ "strings"
"sync"
"github.com/hashicorp/consul/api"
@@ -38,16 +40,46 @@ func (cb *consulBooter) Boot(ctx context.Context) error {
if err := os.MkdirAll(dataDir, 0700); err != nil {
return err
}
- args := []string{
- "agent",
- "-server",
- "-datacenter=" + cfg.SiteID,
- "-dns-port=" + fmt.Sprintf("%d", cfg.Ports.ConsulDNS),
- "-http-port=" + fmt.Sprintf("%d", cfg.Ports.ConsulHTTP),
- "-serf-lan-bind=0.0.0.0:" + fmt.Sprintf("%d", cfg.Ports.ConsulSerfLAN),
- "-serf-wan-bind=0.0.0.0:" + fmt.Sprintf("%d", cfg.Ports.ConsulSerfWAN),
- "-data-dir", dataDir,
- "-bootstrap-expect", fmt.Sprintf("%d", len(cfg.ControlHosts))}
+ args := []string{"agent"}
+ {
+ cf := path.Join(cfg.DataDir, "consul-encrypt.json")
+ _, err := os.Stat(cf)
+ if os.IsNotExist(err) {
+ key, err := exec.Command(bin, "keygen").CombinedOutput()
+ if err != nil {
+ return err
+ }
+ err = atomicWriteJSON(cf, map[string]interface{}{
+ "encrypt": strings.TrimSpace(string(key)),
+ }, 0400)
+ }
+ if err != nil {
+ return err
+ }
+ args = append(args, "-config-file="+cf)
+ }
+ {
+ cf := path.Join(cfg.DataDir, "consul-ports.json")
+ err = atomicWriteJSON(cf, map[string]interface{}{
+ "bootstrap_expect": len(cfg.ControlHosts),
+ "data_dir": dataDir,
+ "datacenter": cfg.SiteID,
+ "server": true,
+ "ports": map[string]int{
+ "dns": cfg.Ports.ConsulDNS,
+ "http": cfg.Ports.ConsulHTTP,
+ "https": cfg.Ports.ConsulHTTPS,
+ "rpc": cfg.Ports.ConsulRPC,
+ "serf_lan": cfg.Ports.ConsulSerfLAN,
+ "serf_wan": cfg.Ports.ConsulSerfWAN,
+ "server": cfg.Ports.ConsulServer,
+ },
+ }, 0644)
+ if err != nil {
+ return err
+ }
+ args = append(args, "-config-file="+cf)
+ }
supervisor := newSupervisor(ctx, "consul", bin, args...)
running, err := supervisor.Running(ctx)
if err != nil {
@@ -88,3 +120,13 @@ func (cb *consulBooter) check(ctx context.Context) error {
}
return nil
}
+
+// OnlyNode returns true if this is the only consul node.
+func (cb *consulBooter) OnlyNode() (bool, error) {
+ c, err := api.NewClient(consulCfg)
+ if err != nil {
+ return false, err
+ }
+ nodes, _, err := c.Catalog().Nodes(nil)
+ return len(nodes) == 1, err
+}
diff --git a/services/boot/controller.go b/services/boot/controller.go
index 06de1d3..953507f 100644
--- a/services/boot/controller.go
+++ b/services/boot/controller.go
@@ -10,22 +10,22 @@ type controller struct{}
func (c *controller) Boot(ctx context.Context) error {
cfg := cfg(ctx)
return Series{
+ cfg,
Concurrent{
- cfg,
installCerts,
arvadosRepo,
},
Concurrent{
- consul,
&download{
URL: "https://releases.hashicorp.com/consul-template/0.18.0/consul-template_0.18.0_linux_amd64.zip",
Dest: path.Join(cfg.UsrDir, "bin", "consul-template"),
Size: 6912352,
Mode: 0755,
},
+ consul,
},
+ vault,
Concurrent{
- vault,
dispatchLocal,
dispatchSLURM,
gitHTTP,
diff --git a/services/boot/vault.go b/services/boot/vault.go
index 1b0d38a..85b062a 100644
--- a/services/boot/vault.go
+++ b/services/boot/vault.go
@@ -3,6 +3,7 @@ package main
import (
"context"
"fmt"
+ "io/ioutil"
"log"
"path"
"sync"
@@ -10,7 +11,10 @@ import (
"github.com/hashicorp/vault/api"
)
-var vault = &vaultBooter{}
+var (
+ vault = &vaultBooter{}
+ vaultCfg = api.DefaultConfig()
+)
type vaultBooter struct {
sync.Mutex
@@ -34,6 +38,7 @@ func (vb *vaultBooter) Boot(ctx context.Context) error {
if err != nil {
return err
}
+
cfgPath := path.Join(cfg.DataDir, "vault.hcl")
err = atomicWriteFile(cfgPath, []byte(fmt.Sprintf(`backend "consul" {
address = "127.0.0.1:%d"
@@ -60,22 +65,68 @@ func (vb *vaultBooter) Boot(ctx context.Context) error {
return fmt.Errorf("starting vault: %s", err)
}
}
+
+ vb.tryInit(ctx)
return vb.check(ctx)
}
-var vaultCfg = api.DefaultConfig()
+func (vb *vaultBooter) tryInit(ctx context.Context) {
+ cfg := cfg(ctx)
+ vault, err := vb.client(ctx)
+ if err != nil {
+ return
+ }
+ if init, err := vault.Sys().InitStatus(); err != nil {
+ log.Printf("error: vault InitStatus: %s", err)
+ return
+ } else if init {
+ return
+ }
+ resp, err := vault.Sys().Init(&api.InitRequest{
+ SecretShares: 5,
+ SecretThreshold: 3,
+ })
+ if err != nil {
+ log.Printf("vault-init: %s", err)
+ return
+ }
+ atomicWriteJSON(path.Join(cfg.DataDir, "vault-keys.json"), resp, 0400)
+ atomicWriteFile(path.Join(cfg.DataDir, "vault-root-token.txt"), []byte(resp.RootToken), 0400)
-func (vb *vaultBooter) check(ctx context.Context) error {
+ for _, key := range resp.Keys {
+ resp, err := vault.Sys().Unseal(key)
+ if err != nil {
+ log.Printf("error: unseal: %s", err)
+ continue
+ }
+ if !resp.Sealed {
+ log.Printf("unseal successful")
+ break
+ }
+ }
+}
+
+func (vb *vaultBooter) client(ctx context.Context) (*api.Client, error) {
cfg := cfg(ctx)
vaultCfg.Address = fmt.Sprintf("http://0.0.0.0:%d", cfg.Ports.VaultServer)
- vault, err := api.NewClient(vaultCfg)
+ return api.NewClient(vaultCfg)
+}
+
+func (vb *vaultBooter) check(ctx context.Context) error {
+ cfg := cfg(ctx)
+ vault, err := vb.client(ctx)
if err != nil {
return err
}
- help, err := vault.Help("help")
+ token, err := ioutil.ReadFile(path.Join(cfg.DataDir, "vault-root-token.txt"))
if err != nil {
return err
}
- log.Printf("%#v", help)
+ vault.SetToken(string(token))
+ if init, err := vault.Sys().InitStatus(); err != nil {
+ return err
+ } else if !init {
+ return fmt.Errorf("vault is not initialized")
+ }
return nil
}
diff --git a/services/boot/write_file.go b/services/boot/write_file.go
index 24374dd..d482f16 100644
--- a/services/boot/write_file.go
+++ b/services/boot/write_file.go
@@ -1,6 +1,7 @@
package main
import (
+ "encoding/json"
"io/ioutil"
"os"
"path"
@@ -35,3 +36,11 @@ func atomicWriteFile(name string, data []byte, mode os.FileMode) error {
tmp = nil
return nil
}
+
+func atomicWriteJSON(name string, data interface{}, mode os.FileMode) error {
+ j, err := json.MarshalIndent(data, "", " ")
+ if err != nil {
+ return err
+ }
+ return atomicWriteFile(name, j, mode)
+}
commit eb459d42be239bd579634884292d3606896792fd
Author: Tom Clegg <tom at curoverse.com>
Date: Sun Jan 29 02:15:12 2017 -0500
add vault, consul-template, arvados pkgs
diff --git a/services/boot/arvados_go.go b/services/boot/arvados_go.go
index b95f7c0..8a4a10d 100644
--- a/services/boot/arvados_go.go
+++ b/services/boot/arvados_go.go
@@ -5,7 +5,6 @@ import (
"log"
"math/rand"
"os"
- "os/exec"
"path"
"path/filepath"
)
@@ -33,9 +32,7 @@ func (agb *arvadosGoBooter) Boot(ctx context.Context) error {
cmd := path.Join(cfg.UsrDir, "bin", agb.name)
if _, err := os.Stat(cmd); err != nil {
if found, err := filepath.Glob(path.Join(cfg.UsrDir, "pkg", agb.name+"_*.deb")); err == nil && len(found) > 0 {
- cmd := exec.Command("dpkg", "-i", found[0])
- cmd.Stdout = os.Stderr
- cmd.Stderr = os.Stderr
+ cmd := command("dpkg", "-i", found[0])
osPackageMutex.Lock()
err = cmd.Run()
osPackageMutex.Unlock()
@@ -44,13 +41,21 @@ func (agb *arvadosGoBooter) Boot(ctx context.Context) error {
}
}
}
+ cfgPath := path.Join("/etc/arvados", agb.name, agb.name+".yml")
+ atomicWriteFile(cfgPath+".ctmpl", []byte("{}"), 0644)
return Series{
&osPackage{
Debian: agb.name,
},
&supervisedService{
+ name: agb.name,
cmd: path.Join(cfg.UsrDir, "bin", "consul-template"),
- args: []string{"blah"},
+ args: []string{
+ "-consul-addr=127.0.0.1:8500",
+ "-template="+cfgPath+".ctmpl:"+cfgPath,
+ "-exec",
+ agb.name,
+ },
},
}.Boot(ctx)
}
diff --git a/services/boot/arvados_packages.go b/services/boot/arvados_packages.go
new file mode 100644
index 0000000..5115b46
--- /dev/null
+++ b/services/boot/arvados_packages.go
@@ -0,0 +1,33 @@
+package main
+
+import (
+ "context"
+ "io/ioutil"
+ "os"
+ "sync"
+)
+
+var arvadosRepo = &arvadosRepoBooter{}
+
+type arvadosRepoBooter struct {
+ sync.Mutex
+}
+
+func (*arvadosRepoBooter) Boot(ctx context.Context) error {
+ cfg := cfg(ctx)
+ repo := cfg.ArvadosAptRepo
+ if !repo.Enabled {
+ return nil
+ }
+ srcPath := "/etc/apt/sources.list.d/arvados.list"
+ if _, err := os.Stat(srcPath); err == nil {
+ return nil
+ }
+ if err := command("apt-key", "adv", "--keyserver", "pool.sks-keyservers.net", "--recv", "1078ECD7").Run(); err != nil {
+ return err
+ }
+ if err := ioutil.WriteFile(srcPath, []byte("deb "+repo.URL+" "+repo.Release+" main\n"), 0644); err != nil {
+ return err
+ }
+ return command("apt-get", "update").Run()
+}
diff --git a/services/boot/command.go b/services/boot/command.go
new file mode 100644
index 0000000..c080918
--- /dev/null
+++ b/services/boot/command.go
@@ -0,0 +1,13 @@
+package main
+
+import (
+ "os"
+ "os/exec"
+)
+
+func command(prog string, args ...string) *exec.Cmd {
+ cmd := exec.Command(prog, args...)
+ cmd.Stderr = os.Stderr
+ cmd.Stdout = os.Stderr
+ return cmd
+}
diff --git a/services/boot/config.go b/services/boot/config.go
index 2eeac01..3ee981d 100644
--- a/services/boot/config.go
+++ b/services/boot/config.go
@@ -3,7 +3,9 @@ package main
import (
"context"
"fmt"
+ "io/ioutil"
"os"
+ "strings"
)
type Config struct {
@@ -20,6 +22,8 @@ type Config struct {
DataDir string
UsrDir string
RunitSvDir string
+
+ ArvadosAptRepo aptRepoConfig
}
type portsConfig struct {
@@ -27,9 +31,10 @@ type portsConfig struct {
ConsulHTTP int
ConsulHTTPS int
ConsulRPC int
- ConsulSerfLAN int `json:"Serf_LAN"`
- ConsulSerfWAN int `json:"Serf_WAN"`
+ ConsulSerfLAN int
+ ConsulSerfWAN int
ConsulServer int
+ VaultServer int
}
type webguiConfig struct {
@@ -38,6 +43,12 @@ type webguiConfig struct {
Listen string
}
+type aptRepoConfig struct {
+ Enabled bool
+ URL string
+ Release string
+}
+
func (c *Config) Boot(ctx context.Context) error {
for _, path := range []string{c.DataDir, c.UsrDir, c.UsrDir + "/bin"} {
if fi, err := os.Stat(path); err != nil {
@@ -53,8 +64,25 @@ func (c *Config) Boot(ctx context.Context) error {
}
func DefaultConfig() *Config {
+ var repoConf aptRepoConfig
+ if rel, err := ioutil.ReadFile("/etc/os-release"); err == nil {
+ rel := string(rel)
+ for _, try := range []string{"jessie", "precise", "xenial"} {
+ if !strings.Contains(rel, try) {
+ continue
+ }
+ repoConf = aptRepoConfig{
+ Enabled: true,
+ URL: "http://apt.arvados.org/",
+ Release: try,
+ }
+ break
+ }
+ }
return &Config{
- ControlHosts: []string{"127.0.0.1"},
+ SiteID: "zzzzz",
+ ArvadosAptRepo: repoConf,
+ ControlHosts: []string{"127.0.0.1"},
Ports: portsConfig{
ConsulDNS: 18600,
ConsulHTTP: 18500,
@@ -63,6 +91,7 @@ func DefaultConfig() *Config {
ConsulSerfLAN: 18301,
ConsulSerfWAN: 18302,
ConsulServer: 18300,
+ VaultServer: 18200,
},
DataDir: "/var/lib/arvados",
UsrDir: "/usr/local/arvados",
diff --git a/services/boot/consul.go b/services/boot/consul.go
index a536d1a..e1015ae 100644
--- a/services/boot/consul.go
+++ b/services/boot/consul.go
@@ -41,7 +41,11 @@ func (cb *consulBooter) Boot(ctx context.Context) error {
args := []string{
"agent",
"-server",
- "-advertise=127.0.0.1",
+ "-datacenter=" + cfg.SiteID,
+ "-dns-port=" + fmt.Sprintf("%d", cfg.Ports.ConsulDNS),
+ "-http-port=" + fmt.Sprintf("%d", cfg.Ports.ConsulHTTP),
+ "-serf-lan-bind=0.0.0.0:" + fmt.Sprintf("%d", cfg.Ports.ConsulSerfLAN),
+ "-serf-wan-bind=0.0.0.0:" + fmt.Sprintf("%d", cfg.Ports.ConsulSerfWAN),
"-data-dir", dataDir,
"-bootstrap-expect", fmt.Sprintf("%d", len(cfg.ControlHosts))}
supervisor := newSupervisor(ctx, "consul", bin, args...)
@@ -72,6 +76,7 @@ var consulCfg = api.DefaultConfig()
func (cb *consulBooter) check(ctx context.Context) error {
cfg := cfg(ctx)
+ consulCfg.Address = fmt.Sprintf("127.0.0.1:%d", cfg.Ports.ConsulHTTP)
consulCfg.Datacenter = cfg.SiteID
consul, err := api.NewClient(consulCfg)
if err != nil {
diff --git a/services/boot/controller.go b/services/boot/controller.go
index cc996bf..06de1d3 100644
--- a/services/boot/controller.go
+++ b/services/boot/controller.go
@@ -13,16 +13,19 @@ func (c *controller) Boot(ctx context.Context) error {
Concurrent{
cfg,
installCerts,
+ arvadosRepo,
},
Concurrent{
consul,
&download{
URL: "https://releases.hashicorp.com/consul-template/0.18.0/consul-template_0.18.0_linux_amd64.zip",
Dest: path.Join(cfg.UsrDir, "bin", "consul-template"),
+ Size: 6912352,
Mode: 0755,
},
},
Concurrent{
+ vault,
dispatchLocal,
dispatchSLURM,
gitHTTP,
diff --git a/services/boot/main.go b/services/boot/main.go
index 86846b3..ebab009 100644
--- a/services/boot/main.go
+++ b/services/boot/main.go
@@ -2,6 +2,7 @@ package main
import (
"context"
+ "encoding/json"
"flag"
"log"
"os"
@@ -22,6 +23,11 @@ func main() {
} else if err != nil {
log.Fatal(err)
}
+
+ enc := json.NewEncoder(os.Stderr)
+ enc.SetIndent("", " ")
+ enc.Encode(cfg)
+
go runWebGUI(cfg)
go func() {
var ctl Booter = &controller{}
@@ -38,4 +44,3 @@ func main() {
}()
<-(chan struct{})(nil)
}
-
diff --git a/services/boot/os_package.go b/services/boot/os_package.go
index db953a1..dc5cd18 100644
--- a/services/boot/os_package.go
+++ b/services/boot/os_package.go
@@ -4,7 +4,6 @@ import (
"context"
"fmt"
"os"
- "os/exec"
"strings"
"sync"
)
@@ -56,9 +55,7 @@ func (pkg *osPackage) Boot(ctx context.Context) error {
}
func (*osPackage) aptGet(args ...string) error {
- cmd := exec.Command("apt-get", args...)
- cmd.Stdout = os.Stderr
- cmd.Stderr = os.Stderr
+ cmd := command("apt-get", args...)
for _, kv := range os.Environ() {
if !strings.HasPrefix(kv, "DEBIAN_FRONTEND=") {
cmd.Env = append(cmd.Env, kv)
diff --git a/services/boot/package.json b/services/boot/package.json
index 340c69f..6e2be8a 100644
--- a/services/boot/package.json
+++ b/services/boot/package.json
@@ -14,7 +14,7 @@
"scripts": {
"dev": "WEBPACK_FLAGS=-d go generate && go get ./... && $GOPATH/bin/boot",
"dev-as-root": "WEBPACK_FLAGS=-d go generate && go get ./... && sudo $GOPATH/bin/boot",
- "dev-docker": "WEBPACK_FLAGS=-d go generate && go get ./... && docker build --tag=arvados-boot-test-runit testimage_runit && docker run -it --rm --volume=${GOPATH}/bin/boot:/usr/bin/arvados-boot:ro arvados-boot-test-runit",
+ "dev-docker": "WEBPACK_FLAGS=-d go generate && go get ./... && docker build --tag=arvados-boot-test-runit testimage_runit && docker run -it --cap-add=IPC_LOCK --rm --volume=${GOPATH}/bin/boot:/usr/bin/arvados-boot:ro arvados-boot-test-runit",
"test": "./node_modules/.bin/tap 'js/**/*_test.js'",
"build": "go generate && go get ./...",
"start": "npm run build && $GOPATH/bin/boot",
diff --git a/services/boot/systemd.go b/services/boot/systemd.go
index 4cde7a9..18d123e 100644
--- a/services/boot/systemd.go
+++ b/services/boot/systemd.go
@@ -3,7 +3,6 @@ package main
import (
"context"
"fmt"
- "os"
"os/exec"
)
@@ -14,9 +13,7 @@ type systemdUnit struct {
}
func (u *systemdUnit) Start(ctx context.Context) error {
- cmd := exec.Command("systemd-run", append([]string{"--unit=arvados-" + u.name, u.cmd}, u.args...)...)
- cmd.Stdout = os.Stderr
- cmd.Stderr = os.Stderr
+ cmd := command("systemd-run", append([]string{"--unit=arvados-" + u.name, u.cmd}, u.args...)...)
err := cmd.Run()
if err != nil {
err = fmt.Errorf("systemd-run: %s", err)
@@ -29,9 +26,7 @@ func (u *systemdUnit) Running(ctx context.Context) (bool, error) {
}
func runStatusCmd(prog string, args ...string) (bool, error) {
- cmd := exec.Command(prog, args...)
- cmd.Stdout = os.Stderr
- cmd.Stderr = os.Stderr
+ cmd := command(prog, args...)
err := cmd.Run()
switch err.(type) {
case *exec.ExitError:
diff --git a/services/boot/vault.go b/services/boot/vault.go
new file mode 100644
index 0000000..1b0d38a
--- /dev/null
+++ b/services/boot/vault.go
@@ -0,0 +1,81 @@
+package main
+
+import (
+ "context"
+ "fmt"
+ "log"
+ "path"
+ "sync"
+
+ "github.com/hashicorp/vault/api"
+)
+
+var vault = &vaultBooter{}
+
+type vaultBooter struct {
+ sync.Mutex
+}
+
+func (vb *vaultBooter) Boot(ctx context.Context) error {
+ vb.Lock()
+ defer vb.Unlock()
+
+ if vb.check(ctx) == nil {
+ return nil
+ }
+ cfg := cfg(ctx)
+ bin := cfg.UsrDir + "/bin/vault"
+ err := (&download{
+ URL: "https://releases.hashicorp.com/vault/0.6.4/vault_0.6.4_linux_amd64.zip",
+ Dest: bin,
+ Size: 52518022,
+ Mode: 0755,
+ }).Boot(ctx)
+ if err != nil {
+ return err
+ }
+ cfgPath := path.Join(cfg.DataDir, "vault.hcl")
+ err = atomicWriteFile(cfgPath, []byte(fmt.Sprintf(`backend "consul" {
+ address = "127.0.0.1:%d"
+ path = "vault"
+ }
+ listener "tcp" {
+ address = "127.0.0.1:%d"
+ tls_disable = 1
+ }`, cfg.Ports.ConsulHTTP, cfg.Ports.VaultServer)), 0644)
+ if err != nil {
+ return err
+ }
+
+ args := []string{"server", "-config=" + cfgPath}
+ supervisor := newSupervisor(ctx, "vault", bin, args...)
+ running, err := supervisor.Running(ctx)
+ if err != nil {
+ return err
+ }
+ if !running {
+ defer feedbackf(ctx, "starting vault service")()
+ err = supervisor.Start(ctx)
+ if err != nil {
+ return fmt.Errorf("starting vault: %s", err)
+ }
+ }
+ return vb.check(ctx)
+}
+
+var vaultCfg = api.DefaultConfig()
+
+func (vb *vaultBooter) check(ctx context.Context) error {
+ cfg := cfg(ctx)
+ vaultCfg.Address = fmt.Sprintf("http://0.0.0.0:%d", cfg.Ports.VaultServer)
+ vault, err := api.NewClient(vaultCfg)
+ if err != nil {
+ return err
+ }
+ help, err := vault.Help("help")
+ if err != nil {
+ return err
+ }
+ log.Printf("%#v", help)
+ return nil
+}
diff --git a/services/boot/write_file.go b/services/boot/write_file.go
new file mode 100644
index 0000000..24374dd
--- /dev/null
+++ b/services/boot/write_file.go
@@ -0,0 +1,37 @@
+package main
+
+import (
+ "io/ioutil"
+ "os"
+ "path"
+)
+
+func atomicWriteFile(name string, data []byte, mode os.FileMode) error {
+ tmp, err := ioutil.TempFile(path.Dir(name), path.Base(name)+"~")
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if tmp != nil {
+ os.Remove(tmp.Name())
+ }
+ }()
+ _, err = tmp.Write(data)
+ if err != nil {
+ return err
+ }
+ err = tmp.Close()
+ if err != nil {
+ return err
+ }
+ err = os.Chmod(tmp.Name(), mode)
+ if err != nil {
+ return err
+ }
+ err = os.Rename(tmp.Name(), name)
+ if err != nil {
+ return err
+ }
+ tmp = nil
+ return nil
+}
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list