[ARVADOS] updated: cea3337f1d104150d3314e43bc1c07eef0851bc5
Git user
git at public.curoverse.com
Sat Feb 25 19:33:37 EST 2017
Summary of changes:
.../app/controllers/collections_controller.rb | 8 +-
apps/workbench/app/controllers/jobs_controller.rb | 1 +
.../controllers/pipeline_instances_controller.rb | 10 +
.../app/controllers/projects_controller.rb | 7 +-
apps/workbench/app/models/job.rb | 2 +-
apps/workbench/app/models/job_work_unit.rb | 4 +
apps/workbench/app/models/pipeline_instance.rb | 4 +
apps/workbench/app/models/work_unit.rb | 4 +
.../workbench/app/views/jobs/_show_status.html.erb | 32 +-
.../pipeline_instances/_show_tab_buttons.html.erb | 5 +-
.../app/views/work_units/_show_component.html.erb | 7 +-
apps/workbench/config/routes.rb | 1 +
.../test/controllers/jobs_controller_test.rb | 15 +
apps/workbench/test/integration/work_units_test.rb | 32 +-
build/build.list | 34 +-
build/package-build-dockerfiles/Makefile | 8 +-
build/package-build-dockerfiles/centos7/Dockerfile | 8 +-
build/package-build-dockerfiles/debian8/Dockerfile | 8 +-
.../ubuntu1204/Dockerfile | 8 +-
.../ubuntu1404/Dockerfile | 8 +-
.../{ubuntu1204 => ubuntu1604}/Dockerfile | 17 +-
.../{ubuntu1204 => ubuntu1604}/Dockerfile | 11 +-
.../ubuntu1604/etc-apt-preferences.d-arvados | 3 +
build/package-testing/deb-common-test-packages.sh | 2 +-
...ages-debian7.sh => test-packages-ubuntu1604.sh} | 0
build/run-build-packages-one-target.sh | 5 +-
build/run-build-packages.sh | 3 +
build/run-tests.sh | 5 +
cmd/arvados-admin/.gitignore | 1 +
cmd/arvados-admin/main.go | 26 ++
cmd/arvados-admin/setup_debian8_test.go | 42 +++
cmd/arvados-admin/setup_docker_compose_test.go | 23 ++
cmd/arvados-admin/test-debian8/Dockerfile | 14 +
cmd/arvados-admin/test-docker-compose/agent.yml | 4 +
.../test-docker-compose/docker-compose.yml | 35 ++
.../test-docker-compose/encrypt-key.txt | 1 +
.../test-docker-compose/master-token.txt | 1 +
cmd/dispatch.go | 59 ++++
doc/_includes/_install_ruby_and_bundler.liquid | 8 +-
doc/_includes/_mount_types.liquid | 55 ++++
doc/_includes/_navbar_top.liquid | 2 +-
doc/api/methods.html.textile.liquid | 2 +
.../methods/container_requests.html.textile.liquid | 2 +-
.../install-dispatch.html.textile.liquid | 12 +
doc/sdk/cli/reference.html.textile.liquid | 13 +-
doc/user/index.html.textile.liquid | 2 +-
services/boot/config.go => lib/agent/agent.go | 84 ++---
lib/setup/check.go | 12 +
lib/setup/command.go | 26 ++
lib/setup/consul.go | 153 +++++++++
lib/setup/daemon.go | 75 +++++
{services/boot => lib/setup}/download.go | 62 ++--
{services/boot => lib/setup}/os_package.go | 17 +-
lib/setup/runit.go | 41 +++
lib/setup/setup.go | 65 ++++
lib/setup/systemd.go | 20 ++
{services/boot => lib/setup}/write_file.go | 5 +-
sdk/cli/arvados-cli.gemspec | 4 +-
sdk/cli/bin/crunch-job | 9 +
sdk/cwl/arvados_cwl/__init__.py | 94 ++++--
sdk/cwl/arvados_cwl/arvcontainer.py | 101 ++++--
sdk/cwl/arvados_cwl/arvdocker.py | 2 +
sdk/cwl/arvados_cwl/arvjob.py | 46 ++-
sdk/cwl/arvados_cwl/arvworkflow.py | 57 ++--
sdk/cwl/arvados_cwl/done.py | 35 +-
sdk/cwl/arvados_cwl/fsaccess.py | 40 ++-
sdk/cwl/arvados_cwl/pathmapper.py | 12 +-
sdk/cwl/arvados_cwl/runner.py | 180 ++++++++---
sdk/cwl/setup.py | 4 +-
sdk/cwl/test_with_arvbox.sh | 2 +
sdk/cwl/tests/test_container.py | 125 +++++++-
sdk/cwl/tests/test_job.py | 17 +-
sdk/cwl/tests/test_submit.py | 248 ++++++++------
sdk/cwl/tests/wf/expect_arvworkflow.cwl | 22 +-
sdk/cwl/tests/wf/expect_packed.cwl | 4 +-
sdk/cwl/tests/wf/scatter2_subwf.cwl | 116 ++++---
.../wf/{expect_packed.cwl => submit_wf_packed.cwl} | 8 +-
sdk/go/arvados/collection.go | 5 +-
sdk/go/arvados/container.go | 15 +-
sdk/go/arvados/resource_list.go | 2 +
sdk/go/config/dump.go | 27 ++
sdk/go/dispatch/dispatch.go | 356 ++++++++++-----------
sdk/go/dispatch/throttle.go | 58 ++++
sdk/go/dispatch/throttle_test.go | 38 +++
sdk/go/keepclient/block_cache.go | 104 ++++++
sdk/go/keepclient/collectionreader.go | 321 +++++++------------
sdk/go/keepclient/collectionreader_test.go | 108 +++++--
sdk/go/keepclient/keepclient.go | 9 +
sdk/go/manifest/manifest.go | 341 +++++++++++++++++---
sdk/go/manifest/manifest_test.go | 126 +++++++-
sdk/go/manifest/testdata/long_manifest | 8 +-
sdk/go/manifest/testdata/short_manifest | 7 +-
sdk/python/arvados/arvfile.py | 7 +-
sdk/python/arvados/collection.py | 12 +-
sdk/python/arvados/commands/keepdocker.py | 103 ++++++
sdk/python/arvados/commands/put.py | 60 ++--
sdk/python/bin/arv-migrate-docker19 | 4 +
sdk/python/setup.py | 1 +
sdk/python/tests/test_arv_keepdocker.py | 97 ++++++
sdk/python/tests/test_arvfile.py | 24 +-
sdk/ruby/arvados.gemspec | 4 +-
.../api/app/controllers/application_controller.rb | 15 +-
.../app/controllers/arvados/v1/jobs_controller.rb | 2 +-
.../arvados/v1/pipeline_instances_controller.rb | 6 +
.../controllers/arvados/v1/schema_controller.rb | 11 +-
services/api/app/models/collection.rb | 18 ++
services/api/app/models/container_request.rb | 2 +-
services/api/app/models/job.rb | 51 ++-
services/api/app/models/node.rb | 28 +-
services/api/app/models/pipeline_instance.rb | 27 ++
services/api/config/application.default.yml | 11 +
.../api/config/initializers/noop_deep_munge.rb | 9 +
services/api/config/routes.rb | 4 +-
services/api/test/fixtures/collections.yml | 2 +-
services/api/test/fixtures/jobs.yml | 175 ++++++++++
services/api/test/fixtures/links.yml | 56 ++++
services/api/test/fixtures/pipeline_instances.yml | 39 +++
.../v1/pipeline_instances_controller_test.rb | 20 ++
.../api/test/functional/arvados/v1/query_test.rb | 29 ++
.../api/test/helpers/docker_migration_helper.rb | 13 +
services/api/test/integration/noop_deep_munge.rb | 35 ++
services/api/test/unit/container_request_test.rb | 19 ++
services/api/test/unit/job_test.rb | 103 ++++++
services/api/test/unit/node_test.rb | 27 ++
services/arv-git-httpd/main.go | 5 +
services/boot/.gitignore | 1 +
services/boot/arvados_go.go | 1 -
services/boot/arvados_packages.go | 8 +-
services/boot/check.go | 16 +
services/boot/config.go | 11 +
services/boot/consul.go | 81 +++--
services/boot/controller.go | 22 +-
services/boot/debian8_test.go | 35 ++
services/boot/download.go | 2 +-
services/boot/gateway.go | 166 ++++++++++
services/boot/main.go | 21 +-
services/boot/nomad.go | 107 +++++++
services/boot/package.json | 2 +-
services/boot/postgresql.go | 30 ++
services/boot/runit.go | 31 +-
services/boot/supervisor.go | 10 +-
services/boot/testimage_runit/Dockerfile | 14 +-
services/boot/vault.go | 100 +++++-
services/boot/webpack.config.js | 2 +-
services/boot/write_file.go | 3 +
.../crunch-dispatch-local/crunch-dispatch-local.go | 34 +-
.../crunch-dispatch-local_test.go | 56 ++--
.../crunch-dispatch-slurm/crunch-dispatch-slurm.go | 285 +++++++----------
.../crunch-dispatch-slurm_test.go | 93 +++---
services/crunch-dispatch-slurm/squeue.go | 164 ++++------
services/crunch-run/crunchrun.go | 118 ++++++-
services/crunch-run/crunchrun_test.go | 283 ++++++++++++++--
services/keep-balance/balance_run_test.go | 4 +-
services/keep-balance/collection.go | 75 +++--
services/keep-balance/collection_test.go | 57 ++++
services/keep-balance/main.go | 19 +-
services/keep-web/handler.go | 52 +--
services/keep-web/handler_test.go | 43 ---
services/keep-web/main.go | 6 +
services/keep-web/ranges_test.go | 90 ++++++
services/keepproxy/keepproxy.go | 11 +-
services/keepstore/keepstore.go | 8 +-
.../arvnodeman/computenode/dispatch/__init__.py | 40 +--
.../arvnodeman/computenode/dispatch/slurm.py | 8 +-
services/nodemanager/arvnodeman/daemon.py | 46 +--
.../nodemanager/tests/test_computenode_dispatch.py | 29 +-
.../tests/test_computenode_dispatch_slurm.py | 10 +
.../tests/test_computenode_driver_azure.py | 4 +-
services/nodemanager/tests/test_daemon.py | 57 ++--
services/nodemanager/tests/test_failure.py | 4 +-
services/nodemanager/tests/testutil.py | 4 +-
services/ws/event_source.go | 94 ++++--
services/ws/main.go | 8 +-
tools/arvbox/lib/arvbox/docker/Dockerfile.base | 23 +-
tools/arvbox/lib/arvbox/docker/api-setup.sh | 4 +-
tools/arvbox/lib/arvbox/docker/createusers.sh | 15 +-
176 files changed, 5398 insertions(+), 1793 deletions(-)
copy build/package-build-dockerfiles/{ubuntu1204 => ubuntu1604}/Dockerfile (54%)
copy build/package-test-dockerfiles/{ubuntu1204 => ubuntu1604}/Dockerfile (55%)
create mode 100644 build/package-test-dockerfiles/ubuntu1604/etc-apt-preferences.d-arvados
rename build/package-testing/{test-packages-debian7.sh => test-packages-ubuntu1604.sh} (100%)
create mode 100644 cmd/arvados-admin/.gitignore
create mode 100644 cmd/arvados-admin/main.go
create mode 100644 cmd/arvados-admin/setup_debian8_test.go
create mode 100644 cmd/arvados-admin/setup_docker_compose_test.go
create mode 100644 cmd/arvados-admin/test-debian8/Dockerfile
create mode 100644 cmd/arvados-admin/test-docker-compose/agent.yml
create mode 100644 cmd/arvados-admin/test-docker-compose/docker-compose.yml
create mode 100644 cmd/arvados-admin/test-docker-compose/encrypt-key.txt
create mode 100644 cmd/arvados-admin/test-docker-compose/master-token.txt
create mode 100644 cmd/dispatch.go
copy services/boot/config.go => lib/agent/agent.go (55%)
create mode 100644 lib/setup/check.go
create mode 100644 lib/setup/command.go
create mode 100644 lib/setup/consul.go
create mode 100644 lib/setup/daemon.go
copy {services/boot => lib/setup}/download.go (67%)
copy {services/boot => lib/setup}/os_package.go (80%)
create mode 100644 lib/setup/runit.go
create mode 100644 lib/setup/setup.go
create mode 100644 lib/setup/systemd.go
copy {services/boot => lib/setup}/write_file.go (89%)
copy sdk/cwl/tests/wf/{expect_packed.cwl => submit_wf_packed.cwl} (53%)
create mode 100644 sdk/go/config/dump.go
create mode 100644 sdk/go/dispatch/throttle.go
create mode 100644 sdk/go/dispatch/throttle_test.go
create mode 100644 sdk/go/keepclient/block_cache.go
create mode 100755 sdk/python/bin/arv-migrate-docker19
create mode 100644 services/api/config/initializers/noop_deep_munge.rb
create mode 100644 services/api/test/helpers/docker_migration_helper.rb
create mode 100644 services/api/test/integration/noop_deep_munge.rb
create mode 100644 services/boot/check.go
create mode 100644 services/boot/debian8_test.go
create mode 100644 services/boot/gateway.go
create mode 100644 services/boot/nomad.go
create mode 100644 services/boot/postgresql.go
create mode 100644 services/keep-balance/collection_test.go
create mode 100644 services/keep-web/ranges_test.go
via cea3337f1d104150d3314e43bc1c07eef0851bc5 (commit)
via 379726401a04d87bdb9ef795af321ec0791a41ec (commit)
via fc33deaecf2f7e4c9b3cd8d2e1f5b56901794042 (commit)
via 016a995d5a65f9de66c505fe80ab49eebc1a11c4 (commit)
via aaa536943dde5b3f1ec59c1bd18929b53dfea308 (commit)
via 5624fec61db977d386ce03ca333241c74ca251b5 (commit)
via 4edf67aee4e8d4b351ee08bcb19c051a9bddeacd (commit)
via 31d76600cdb691251d0823cc6be601d958b4e1a4 (commit)
via 03306e210c6835c6de1c908d5afe02ba964e7dbc (commit)
via 6873eca0bf64a2a94ea7536bbc9a5a3788695136 (commit)
via 6b775ec45db0143c0d476cf2f0fcfb8bdd39a845 (commit)
via e86743ca1a4e1431d6d8417083ef1a56461b45e9 (commit)
via bee301067b50d0cc00bbc1dc0a0b5c036d747a74 (commit)
via f782a2505422ad9c853c4c416640c41f3b1e7e79 (commit)
via 3f30342290d901408a3b9a640a21e41f011041cd (commit)
via c90f6525e949c2314ccc9c2cb980bccbc23e2434 (commit)
via 6e8c06b81867a3d54e89694f1301ab037d3f5d22 (commit)
via 72b6a2992c69f557f3b6b850914c5ee914cf862b (commit)
via 38bf86b7d9e256aaae50870174ae2cf6a84e8656 (commit)
via c86cbaa6f286e50900dae3203a42044449e042f7 (commit)
via 0030aceea911108449d67a785d802e894943b340 (commit)
via 70f47bfdccdbdcc773225a94015bba2d2975d7f7 (commit)
via 7c667d8963c7a3cf9acd04c1d938b5273b761228 (commit)
via 5763c67176e8e34656cd96881074777b14b2dc4a (commit)
via 53b24cf4fafa5c8ce76eb4abf5e61de944bb4a6a (commit)
via 232a69cedf3024380546b9e67ad10d6beb357649 (commit)
via 10b3fe2ae3a37ee473684177aa6e4e9f090a230e (commit)
via 90982bd47200f6a555074842c817ac2893c2e391 (commit)
via 01779cbbd49870dbe12478713bf6cd3332d08144 (commit)
via 2a469c4874895b05ee137e2382fd882680b3feb2 (commit)
via 091c92aef16f9657cf7b9eb8f8778aafa33f12c1 (commit)
via 15907692a7a9213ef99a74e5ef1c48a487a8ed8b (commit)
via 5eace5e8b255fdc7f65081429d0b42e551479e95 (commit)
via 07f620f078c6f75cf52e9ae65040857ea1980fdc (commit)
via dde508ae4d3f9542a16c5ebbe90de534cbdaaabb (commit)
via 816f3bfd2b6a562fc712b7c2b3eb30157a95cb7e (commit)
via e2f3f8e7347a8ded697d3c0127f82325d672e7ab (commit)
via 08c06bc813d96634b362e8c5736341fb2d874f59 (commit)
via d6aab18f9688d46bc1f86f021d68e02e5601cfe7 (commit)
via 5dfc48c1a1697d9c29eac0061a491e96c9b72441 (commit)
via dc82c1c16a9b18e094e60af2c3973e034d5e2068 (commit)
via d3719c6ba29daec66eb1dd4003f2580f97da8e41 (commit)
via 35ae0e8d87dde84dd3a0ab41cef9567ab93b042a (commit)
via 2e9cb970e94c1ba259c6365ea4b456ca87e85cee (commit)
via fbc6c71ef67461cde5ba914e61f3f3b8740a4045 (commit)
via 397a747639fe360c18f3aa79846fef530b263184 (commit)
via a2fe6f9367de3ee93064fbee3f2df78ce84aa318 (commit)
via 9333c9f65503d86c12776e0bc8bfcb6fc07dc79c (commit)
via cff6cd57cbbaa032602ca2fb930c78812c5824dc (commit)
via 6eded76b722df150ce59a1bddd2fb7e5175a596d (commit)
via d6cc6f748c79e9bbd0ba18dd8d32ae210a7b897b (commit)
via ef9bbef07f63dd2207e1336e85884aa90434ad29 (commit)
via ad464d416de6996a41d0c752124e0d201de0d3fc (commit)
via 80689aac71f6e3e9b103f0f6b668bd173a76554f (commit)
via 4ee34d218487d8b330147b185a2c9bcea8d68b09 (commit)
via 6b1bf77727379c7ffaf1620399c37ea0106a0909 (commit)
via ddee3839f8a82b889f84171e2354108cb20f93e0 (commit)
via 78b94fd03e3c0a2d225d0ab8882ee62dee9f8a11 (commit)
via d95e6df5184ab2ec137c8098b47caf9ebcf4e7d9 (commit)
via 7b4c1b70b7d1ef4c977c57c89c4dc0f479e7e5ae (commit)
via 4fa9baf6590e63975b6053a049543590db0e2527 (commit)
via 4c081dd00f65f1e5a8e0cea34276d60ecbb49f40 (commit)
via 2b297df85b61ac7f2ded512eca7c307d75b1cd8e (commit)
via a0195a506af77771434302b96a5e05ecfd3814d8 (commit)
via 85c684122fd678dc24035d58236dd5734aed50e5 (commit)
via 1c434a9f9ec70d8f23583bc737a516c3ef0eb91d (commit)
via 310f7b0266f012355e38f3296bc6defe14a3d25f (commit)
via 15b49783aa0ac76508986e772b98ffa9d187c57f (commit)
via 5bf9312a5174f97f00db383836eb7666dc500293 (commit)
via 2b7834020290b28d797333f90fcb87e5da67d616 (commit)
via 4fd89ed7b10f0860a6030c25e44d4df45a087b2e (commit)
via 8ee2c7c4f231a55601fdc90b087e42985b52fb20 (commit)
via d5effac093938be2b57d579cc1fecfa90310af02 (commit)
via 0fc6eaead0bf7691e99d19e74ec33636909001a7 (commit)
via 8e7c3b36efef6ef6590f4359eb48bf98826d71d4 (commit)
via 4c1ca6b3e4cadc74df738882d44019c623869329 (commit)
via 210af1cc7ede88914026fde078e45ef84c187a0c (commit)
via bf0945d1136d2578e40909d54e8614085d6f9c34 (commit)
via ca56623679bcf5733a3266711f513f8c23f8b0df (commit)
via 4dbaf8c355f3743bd42ff5b917eda57d3e90abf8 (commit)
via 108467e2b85c9f3c44b483bc79f68acf6ae3b963 (commit)
via ab6a70e86dd041f3b4da167c59e3e91309f14365 (commit)
via 3f8336875d5938afb6b00289e9d6c9941456b57f (commit)
via 61476528523e4ee2ebe199807b8aeba1e17074d4 (commit)
via 668b2ae22b910765d4e7982a9d9b8a82307e4360 (commit)
via ef934e66fee76dcf760dd5fc835f27127e4cc791 (commit)
via 61f0eb808bba87639e5e4b068f444b7de0526bb2 (commit)
via 126f499d2f084963a5ef5df7cf567a1ed4cb96ed (commit)
via 674236324476c58ccf20d554acd4427dfb6b9873 (commit)
via 87107582273d254e98a66a3036bc0fc487edfa68 (commit)
via 8734a7391a5672eebcdf572d93bae1b3ed1179c9 (commit)
via 8ee173e80b4954159490c8f9327dab07a4bffcf3 (commit)
via 837c509a55f56fa653454e7b99e293f8f87ebef2 (commit)
via 8adad21150d3678aad0f88e5fb30a088145478ee (commit)
via aaa45b09de0e9437743fce53d7c0bf8165074b5e (commit)
via efee0049baf53efa3be10804abc9bc292f2a60ed (commit)
via 925a1526383299a1ade38a18e616564ab8c38da4 (commit)
via 785c967e74a7dab0b29b276162d1d7513ce1cf6b (commit)
via ef328d9143c65c72c37194272f90fabc3ec45e0a (commit)
via 74a9decf66adc216d3d8bbb7ee8f6e3704d9590d (commit)
via 51f5a4ede44615be700eec7fcbfe3c1e60c842ac (commit)
via 211884f495248bbaf2ab74ff8d5ae2ed54b97bf2 (commit)
via a8b210d2bb5b10e6583abf295b99788b3dff7479 (commit)
via e41dc06c9115d0ce30207560b83d6c8dec6fd18a (commit)
via 8a882eff8b8359d58b56f1bc7cd2da95775d97eb (commit)
via 471270bc6ec9453fdd4c1faf97b65a8291543c6f (commit)
via 6a7d7a2fa8e217e1ff9440769f39a2095d5bb837 (commit)
via d02bf4d817e50c3c0ee9f5e2dd901c512ea30943 (commit)
via 9c9b52038aa8b9c15f02567d186539fd8794d0f2 (commit)
via 519ab4c83aeb44ce91da941ecc191d00b6c6c72b (commit)
via 1bba7f8fb361186ad040b521d168a73abd8fdd65 (commit)
via 04a8e2c7d8a8dd3afd891292415cdfaea25fd481 (commit)
via e6986ed88126f61ecad0f557c78981961f901044 (commit)
via f927cd24852edcd7a8389533e96a16cf6877e58f (commit)
via 7d29578411f1940ef5cc5ce985766dd81d133aaa (commit)
via c3d4f8a585202ec58df5506934b698039c200b68 (commit)
via 36360d1f2987cea89ce217a2519c01da7456d533 (commit)
via 3860042ac5783cddd368d8997991b0d1f8e9a111 (commit)
via 7a53cfc92d4bca452a687db0a6f338e6deb1564a (commit)
via 5caa73a3bf5a17241bf908c75aa2c3aa427289d1 (commit)
via a19ffad966b25b3869e666f749f7c6da187bef68 (commit)
via 1bc602ad5480b9b1ed78b318e9d3d9749d2b83ab (commit)
via e502060ffe4f68d33e2cca8f8d7544ce40d53eb7 (commit)
via dcf5452fb14c7025feff04b3003ff68c9f4ec630 (commit)
via 4f485c1318130c61d81f6553460d5eb063f100cb (commit)
via da42861619eb478cd1f01d58a1ebe59f1a25002e (commit)
via dc7d01f4d4031962ffd5734ca0c64146a7217e4a (commit)
via a5e7c0c8bf829a41c4d02b48d5a9a40d6d225c8a (commit)
via ecd8381224f7883db0504eb338d7f1c55fc4349f (commit)
via edd5811cd9627cd1c734d9c5b1e863b3d94f746a (commit)
via 280621308e41e9cc8b8557d27738f186e795780b (commit)
via 804d23f38fb98ec648349703f74a229f225ee22a (commit)
via 49aa7305a80547bc7fb8c32f1073d7add2506ece (commit)
via 65123c5a66fe155d6dad2cee3a1e0b90f7b7f3f2 (commit)
via aa05b5d5ee2e42f2e456cca0c2f3cd835ab7cef4 (commit)
via fdecbc701188e64dc9e539da2dddbbeded709b42 (commit)
via 28aea3c6b1888c00a041992282c95fe595f85005 (commit)
via 436f5c768dbc97135490b6477efd1ff0482a9dda (commit)
via 71229e23918b698caa7c6c8b62b368d4aef2ab85 (commit)
via d6579d95bacbba5682d0c085f139681c93cb005a (commit)
via 827879be023e90d58eb681b3c930154739a0b27f (commit)
via 24b137a5b3313778e2db7f5d1e0c82daf0634a9c (commit)
via b001425779a0189b357c4e3a47734eda6b77ce2d (commit)
via 2b37f7a8e843638431dc9e8031c1c2c2a81c1e7e (commit)
via 1b8106da867aafbe6e4653485d5e644faee4c35d (commit)
via dcb7f718a7bf31c6e1227d28cdaac64fa769015b (commit)
via 95d8984418a5198639000f0a622da74af259b6c5 (commit)
via 8675eec8206c0e39753741864636c8a05ce02408 (commit)
via 799b5333c66ccd18fe1b0ee97c2a28be6e07b731 (commit)
via 9dd66f4d896785e0c6dce839ed1b411dd3c77bf0 (commit)
via e34a5060cfc1cc4821b431e8aa6778a31898e0eb (commit)
via ae5eb12d3d9ab298a4c36412b4a4d83272574d25 (commit)
via 7dd717ca530fccae814c8c59a8c242d376fa0cef (commit)
via 683f5374b0fc516579c1d6dc3379fc900d642322 (commit)
via 318dd887d108e0664ef22a8d38a34fa18e1b2657 (commit)
via a7222f4df954c9ac973d58bb2f27a8f049dbbbc2 (commit)
via a3ca6693f522b59ea50d76cadde69b91c0a62cad (commit)
via 13c27ef91fc2516bdcdee94ba1ff2f08361dc51d (commit)
via e356309e05714cd65d88456c563cea606f820394 (commit)
via 5ba9471d651c9f6235988d3ec680461ba4785453 (commit)
via 0d7ceb1e3498210d20859516de4ffdd59530b6d7 (commit)
via da0aee751d8cb039c9b6b85a03e7d62cb973e3b3 (commit)
via a20c77028c182b684a3acb791c7de4183319737e (commit)
via 1edd524ecd7b6776dd9b20ab81030e7c69c392b4 (commit)
via b172bbd9e4c780d9af79774aee81a1ac48b3a857 (commit)
via 8e569c16ba035b131c148441ca5a590fb49811ac (commit)
via 38ac8f3e065e74f6af172cee90144701d2f73b58 (commit)
via 1e7d93d8dcc2d896a71c38910f4fb6ef35408c0d (commit)
via 7fd60cc870863647127a438a085685d415c37a46 (commit)
via aea835bc965d42e225c2641b0210c4b521f6dc4e (commit)
via 16fe80b0e93ed8c8416b2dcbc0e2ad49bc850738 (commit)
via b8de9b3e62e82b806576b237be5f317bf378169f (commit)
via 39189b90bd2f73d4f4938049ffa4441a967ca24c (commit)
via dc5a33cbfc156c839515acb4fa6ea2f9162a0972 (commit)
via cd383b7168d9412f4f097438d590e919ff7a97d6 (commit)
via ddcaafee5dc10ee0104c108c9648f4d5024a83d9 (commit)
via 685af7fb2ae3a8ea162edd89eec61fdd4ca376f0 (commit)
via ae9f71231ed50eb35097c10c84b0070bcdcd22cf (commit)
via 01007e0a2c7cf5461ced83339f6abcfb6f9fac72 (commit)
via 6143bba5421756c78b282ee6c4da793d45a4523e (commit)
via 036c59ea6b19372e74f7ccacb5dcb2f522f99629 (commit)
via 7fa95f2db716ebfdb6312fa67b9b07bebb815b39 (commit)
via f40364c4d42e111b9da3873afcfaed2b49e7f182 (commit)
via 2f953026bc4baeccb78ca82acc4d07cad37625b8 (commit)
via 60d986b8908487c086eb4e402ac69669cb26108b (commit)
via c40389e0f064d4ea379d5f5471116936239a467a (commit)
via b6e15a581be2e5b2387fe18ecb01714fbc21d3aa (commit)
via 80f042bec0b25966498324cb6aafb7fc24a36e12 (commit)
via 8e9a3e39375b4dd689cd85a92e77a5eee03b4908 (commit)
via 6b91e8201f24d2b4126532d809abba42a5ab959c (commit)
via fbacdaec3dbba425155ab6348c7e6b80ff4e710b (commit)
via edd77406c5a428af8780ed4dffd512adcc70bc0f (commit)
via 1cdb5cbf83d34cb1a19c78478a7d5a28738e7bbf (commit)
via e8521124b0b8e647c58e99905100171ea5e30abd (commit)
via b07d8a573c74e7be56a2fd8c5064032c37d90c67 (commit)
via de4ecbc700759ff22e76948a58f7d70e5d3c1464 (commit)
via e1fd558686c78d6edfd460b7531ec9b559299889 (commit)
via 4696633ae5e955c267d50a14e790c93d833f41b0 (commit)
via a9ae80084e5b8897408a47fe081481cb913fd260 (commit)
via 609646134bcd8fc3a7fd500848220741ecc4a9d2 (commit)
via 49d7a1fbd42359aa0948efd0968349eaf854d6cb (commit)
via 9cc8eb72a4d8dddd2ffe2014d085517ecd0f6a67 (commit)
via 89ce36332958f698bc571eca770fb94e579957cd (commit)
via d2942208ef4bc31bc965d5f72f254b8d39a1bc9b (commit)
via 4032e4dc4284391f21f21630bdb7ca88f8329d8e (commit)
via 0d0092442c009b8b3e387da18f828f3f0518b709 (commit)
via a4edc2a4a740d3908b907682a85e227eee80683b (commit)
via f65530a60d7b74da723d16eccd84576c53575401 (commit)
via be141b88fe871c7e72b19a5cf1e0aa56bf28283a (commit)
via 43dcf83e8b5332004bddd01be22476e68b1cef0f (commit)
via bb037e3872214d2b709964405775f476c6b3b550 (commit)
from 658183e2bca17f5aa281ab95068906c7150b2b73 (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 cea3337f1d104150d3314e43bc1c07eef0851bc5
Author: Tom Clegg <tom at curoverse.com>
Date: Sat Feb 25 19:32:45 2017 -0500
multiple servers, add docker-compose test
diff --git a/build/run-tests.sh b/build/run-tests.sh
index aafbead..3cbc6b3 100755
--- a/build/run-tests.sh
+++ b/build/run-tests.sh
@@ -196,6 +196,9 @@ sanity_checks() {
echo -n 'gitolite: '
which gitolite \
|| fatal "No gitolite. Try: apt-get install gitolite3"
+ echo -n 'docker-compose: '
+ which docker-compose \
+ || fatal "No docker-compose. Try: sudo curl -L https://github.com/docker/compose/releases/download/1.11.2/docker-compose-`uname -s`-`uname -m` --output /usr/local/bin/docker-compose && sudo chmod +x /usr/local/bin/docker-compose"
}
rotate_logfile() {
diff --git a/cmd/arvados-admin/setup_docker_compose_test.go b/cmd/arvados-admin/setup_docker_compose_test.go
new file mode 100644
index 0000000..d949604
--- /dev/null
+++ b/cmd/arvados-admin/setup_docker_compose_test.go
@@ -0,0 +1,23 @@
+package main
+
+import (
+ "os"
+ "os/exec"
+ "testing"
+)
+
+func TestSetupDockerCompose(t *testing.T) {
+ for _, cmdline := range [][]string{
+ {"go", "build"},
+ {"docker-compose", "--file", "test-docker-compose/docker-compose.yml", "down"},
+ {"docker-compose", "--file", "test-docker-compose/docker-compose.yml", "up"},
+ } {
+ cmd := exec.Command(cmdline[0], cmdline[1:]...)
+ cmd.Stdout = os.Stderr
+ cmd.Stderr = os.Stderr
+ err := cmd.Run()
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+}
diff --git a/cmd/arvados-admin/test-docker-compose/agent.yml b/cmd/arvados-admin/test-docker-compose/agent.yml
new file mode 100644
index 0000000..46f4de7
--- /dev/null
+++ b/cmd/arvados-admin/test-docker-compose/agent.yml
@@ -0,0 +1,4 @@
+ControlHosts:
+ - sys0
+ - sys1
+ - sys2
diff --git a/cmd/arvados-admin/test-docker-compose/docker-compose.yml b/cmd/arvados-admin/test-docker-compose/docker-compose.yml
new file mode 100644
index 0000000..66378e5
--- /dev/null
+++ b/cmd/arvados-admin/test-docker-compose/docker-compose.yml
@@ -0,0 +1,35 @@
+version: '2'
+services:
+ sys0:
+ build: ../test-debian8
+ cap_add:
+ - IPC_LOCK
+ - SYS_ADMIN
+ volumes:
+ - ../arvados-admin:/usr/bin/arvados-admin:ro
+ - ./agent.yml:/etc/arvados/agent/agent.yml:ro
+ - ./encrypt-key.txt:/var/lib/arvados/encrypt-key.txt:ro
+ - ./master-token.txt:/var/lib/arvados/master-token.txt:ro
+ command: ["bash", "-c", "runsvdir /etc/sv & arvados-admin setup -unseal=true && wait"]
+ sys1:
+ build: ../test-debian8
+ cap_add:
+ - IPC_LOCK
+ - SYS_ADMIN
+ volumes:
+ - ../arvados-admin:/usr/bin/arvados-admin:ro
+ - ./agent.yml:/etc/arvados/agent/agent.yml:ro
+ - ./encrypt-key.txt:/var/lib/arvados/encrypt-key.txt:ro
+ - ./master-token.txt:/var/lib/arvados/master-token.txt:ro
+ command: ["bash", "-c", "runsvdir /etc/sv & arvados-admin setup && wait"]
+ sys2:
+ build: ../test-debian8
+ cap_add:
+ - IPC_LOCK
+ - SYS_ADMIN
+ volumes:
+ - ../arvados-admin:/usr/bin/arvados-admin:ro
+ - ./agent.yml:/etc/arvados/agent/agent.yml:ro
+ - ./encrypt-key.txt:/var/lib/arvados/encrypt-key.txt:ro
+ - ./master-token.txt:/var/lib/arvados/master-token.txt:ro
+ command: ["bash", "-c", "runsvdir /etc/sv & arvados-admin setup && wait"]
diff --git a/cmd/arvados-admin/test-docker-compose/encrypt-key.txt b/cmd/arvados-admin/test-docker-compose/encrypt-key.txt
new file mode 100644
index 0000000..507ff36
--- /dev/null
+++ b/cmd/arvados-admin/test-docker-compose/encrypt-key.txt
@@ -0,0 +1 @@
+qigR/fVUccR07/J56MsloA==
diff --git a/cmd/arvados-admin/test-docker-compose/master-token.txt b/cmd/arvados-admin/test-docker-compose/master-token.txt
new file mode 100644
index 0000000..f12bf2c
--- /dev/null
+++ b/cmd/arvados-admin/test-docker-compose/master-token.txt
@@ -0,0 +1 @@
+2f79a06949ba76666308f5c821f234c9c038664df2b8662b587b9500ef4853a1
\ No newline at end of file
diff --git a/lib/setup/consul.go b/lib/setup/consul.go
index 0ebff83..b1682b2 100644
--- a/lib/setup/consul.go
+++ b/lib/setup/consul.go
@@ -16,9 +16,9 @@ import (
func (s *Setup) installConsul() error {
prog := s.UsrDir + "/bin/consul"
err := (&download{
- URL: "https://releases.hashicorp.com/consul/0.7.4/consul_0.7.4_linux_amd64.zip",
+ URL: "https://releases.hashicorp.com/consul/0.7.5/consul_0.7.5_linux_amd64.zip",
Dest: prog,
- Size: 36003597,
+ Size: 36003713,
Mode: 0755,
PreloadDir: s.PreloadDir,
}).install()
@@ -29,43 +29,45 @@ func (s *Setup) installConsul() error {
if err := os.MkdirAll(dataDir, 0700); err != nil {
return err
}
- args := []string{"agent"}
- {
- cf := path.Join(s.DataDir, "consul-encrypt.json")
- if _, err := os.Stat(cf); err != nil && !os.IsNotExist(err) {
+
+ keyPath := path.Join(s.DataDir, "encrypt-key.txt")
+ key, err := ioutil.ReadFile(keyPath)
+ if os.IsNotExist(err) {
+ key, err = exec.Command(prog, "keygen").CombinedOutput()
+ if err != nil {
return err
- } else if err != nil {
- key, err := exec.Command(prog, "keygen").CombinedOutput()
- if err != nil {
- return err
- }
- if err = atomicWriteJSON(cf, map[string]interface{}{
- "encrypt": strings.TrimSpace(string(key)),
- }, 0400); err != nil {
- return err
- }
}
- args = append(args, "-config-file="+cf)
+ err = atomicWriteFile(keyPath, key, 0400)
}
- {
+ if err != nil {
+ return err
+ }
+ encryptKey := strings.TrimSpace(string(key))
+
+ tokPath := path.Join(s.DataDir, "master-token.txt")
+ if tok, err := ioutil.ReadFile(tokPath); err != nil {
s.masterToken = generateToken()
- // os.Setenv("CONSUL_TOKEN", s.masterToken)
- err = atomicWriteFile(path.Join(s.DataDir, "master-token.txt"), []byte(s.masterToken), 0600)
+ err = atomicWriteFile(tokPath, []byte(s.masterToken), 0600)
if err != nil {
return err
}
- cf := path.Join(s.DataDir, "consul-config.json")
- err = atomicWriteJSON(cf, map[string]interface{}{
- "acl_datacenter": s.ClusterID,
- "acl_default_policy": "deny",
- "acl_enforce_version_8": true,
- "acl_master_token": s.masterToken,
- "client_addr": "0.0.0.0",
- "bootstrap_expect": len(s.ControlHosts),
- "data_dir": dataDir,
- "datacenter": s.ClusterID,
- "server": true,
- "ui": true,
+ } else {
+ s.masterToken = string(tok)
+ }
+
+ cf := path.Join(s.DataDir, "consul-config.json")
+ {
+ c := map[string]interface{}{
+ "acl_datacenter": s.ClusterID,
+ "acl_default_policy": "deny",
+ "acl_master_token": s.masterToken,
+ "bootstrap_expect": len(s.ControlHosts),
+ "client_addr": "0.0.0.0",
+ "data_dir": dataDir,
+ "datacenter": s.ClusterID,
+ "encrypt": encryptKey,
+ "server": true,
+ "ui": true,
"ports": map[string]int{
"dns": s.Ports.ConsulDNS,
"http": s.Ports.ConsulHTTP,
@@ -75,23 +77,30 @@ func (s *Setup) installConsul() error {
"serf_wan": s.Ports.ConsulSerfWAN,
"server": s.Ports.ConsulServer,
},
- }, 0644)
+ }
+ err = atomicWriteJSON(cf, c, 0600)
if err != nil {
return err
}
- args = append(args, "-config-file="+cf)
}
+
err = s.installService(daemon{
name: "arvados-consul",
prog: prog,
- args: args,
+ args: []string{"agent", "-config-file=" + cf},
noRegister: true,
})
if err != nil {
return err
}
+ if err = waitCheck(20*time.Second, s.consulCheck); err != nil {
+ return err
+ }
if len(s.ControlHosts) > 1 {
- cmd := exec.Command(prog, append([]string{"join"}, s.ControlHosts...)...)
+ args := []string{"join"}
+ args = append(args, fmt.Sprintf("-rpc-addr=127.0.0.1:%d", s.Ports.ConsulRPC))
+ args = append(args, s.ControlHosts...)
+ cmd := exec.Command(prog, args...)
cmd.Stdout = os.Stderr
cmd.Stderr = os.Stderr
err := cmd.Run()
@@ -99,7 +108,7 @@ func (s *Setup) installConsul() error {
return fmt.Errorf("consul join: %s", err)
}
}
- return waitCheck(20*time.Second, s.consulCheck)
+ return nil
}
var consulCfg = api.DefaultConfig()
commit 379726401a04d87bdb9ef795af321ec0791a41ec
Author: Tom Clegg <tom at curoverse.com>
Date: Sat Feb 25 17:48:06 2017 -0500
gitignore
diff --git a/cmd/arvados-admin/.gitignore b/cmd/arvados-admin/.gitignore
new file mode 100644
index 0000000..87fbbf4
--- /dev/null
+++ b/cmd/arvados-admin/.gitignore
@@ -0,0 +1 @@
+arvados-admin
commit fc33deaecf2f7e4c9b3cd8d2e1f5b56901794042
Author: Tom Clegg <tom at curoverse.com>
Date: Mon Feb 20 04:28:07 2017 -0500
cmd, lib
diff --git a/cmd/arvados-admin/main.go b/cmd/arvados-admin/main.go
new file mode 100644
index 0000000..de532cb
--- /dev/null
+++ b/cmd/arvados-admin/main.go
@@ -0,0 +1,26 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "os"
+
+ "git.curoverse.com/arvados.git/cmd"
+ "git.curoverse.com/arvados.git/lib/agent"
+ "git.curoverse.com/arvados.git/lib/setup"
+)
+
+var cmds = map[string]cmd.Command{
+ "agent": agent.Command(),
+ "setup": setup.Command(),
+}
+
+func main() {
+ err := cmd.Dispatch(cmds, os.Args[0], os.Args[1:])
+ if err != nil {
+ if err != flag.ErrHelp {
+ fmt.Fprintf(os.Stderr, "%s\n", err)
+ }
+ os.Exit(1)
+ }
+}
diff --git a/cmd/arvados-admin/setup_debian8_test.go b/cmd/arvados-admin/setup_debian8_test.go
new file mode 100644
index 0000000..671f8c7
--- /dev/null
+++ b/cmd/arvados-admin/setup_debian8_test.go
@@ -0,0 +1,42 @@
+package main
+
+import (
+ "log"
+ "net"
+ "os"
+ "os/exec"
+ "testing"
+)
+
+func TestSetupDebian8(t *testing.T) {
+ cwd, err := os.Getwd()
+ if err != nil {
+ t.Fatal(err)
+ }
+ ln, err := net.Listen("tcp", ":")
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, port, err := net.SplitHostPort(ln.Addr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = ln.Close()
+ if err != nil {
+ t.Fatal(err)
+ }
+ log.Printf("Publishing consul webgui at %v", ln.Addr())
+ for _, cmdline := range [][]string{
+ {"go", "build"},
+ {"docker", "build", "--tag=arvados-admin-debian8-test", "test-debian8"},
+ {"docker", "run", "--rm", "--publish=" + port + ":18500", "--cap-add=IPC_LOCK", "--cap-add=SYS_ADMIN", "--volume=/sys/fs/cgroup", "--volume=" + cwd + "/arvados-admin:/usr/bin/arvados-admin:ro", "--volume=/var/cache/arvados:/var/cache/arvados:ro", "arvados-admin-debian8-test"},
+ } {
+ cmd := exec.Command(cmdline[0], cmdline[1:]...)
+ cmd.Stdout = os.Stderr
+ cmd.Stderr = os.Stderr
+ err = cmd.Run()
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+}
diff --git a/services/boot/testimage_runit/Dockerfile b/cmd/arvados-admin/test-debian8/Dockerfile
similarity index 88%
copy from services/boot/testimage_runit/Dockerfile
copy to cmd/arvados-admin/test-debian8/Dockerfile
index aaf5b88..645aec2 100644
--- a/services/boot/testimage_runit/Dockerfile
+++ b/cmd/arvados-admin/test-debian8/Dockerfile
@@ -11,4 +11,4 @@ RUN ["bash", "-c", "echo en_US.utf8 UTF-8 | tee -a /etc/locale.gen && locale-gen
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends ca-certificates locales nginx postgresql runit
-CMD ["bash", "-c", "runsvdir /etc/sv & exec arvados-boot"]
+CMD ["bash", "-c", "runsvdir /etc/sv & arvados-admin setup && arvados-admin setup"]
diff --git a/cmd/dispatch.go b/cmd/dispatch.go
new file mode 100644
index 0000000..2fc2a70
--- /dev/null
+++ b/cmd/dispatch.go
@@ -0,0 +1,59 @@
+package cmd
+
+import (
+ "flag"
+ "fmt"
+ "os"
+ "sort"
+
+ "git.curoverse.com/arvados.git/sdk/go/config"
+)
+
+// A Command is a subcommand that can be invoked by Dispatch.
+type Command interface {
+ DefaultConfigFile() string
+ ParseFlags([]string) error
+ Run() error
+}
+
+// Dispatch parses flags from args, chooses an entry in cmds using the
+// next argument after the parsed flags, loads the command's
+// configuration file if it exists, passes any additional flags to the
+// command's ParseFlags method, and -- if all of those steps complete
+// without errors -- runs the command.
+func Dispatch(cmds map[string]Command, prog string, args []string) error {
+ fs := flag.NewFlagSet(prog, flag.ContinueOnError)
+ err := fs.Parse(args)
+ if err != nil {
+ return err
+ }
+
+ subcmd := fs.Arg(0)
+ cmd, ok := cmds[subcmd]
+ if !ok {
+ if subcmd != "" && subcmd != "help" {
+ return fmt.Errorf("unrecognized subcommand %q", subcmd)
+ }
+ var subcmds []string
+ for s := range cmds {
+ subcmds = append(subcmds, s)
+ }
+ sort.Sort(sort.StringSlice(subcmds))
+ return fmt.Errorf("available subcommands: %q", subcmds)
+ }
+
+ err = config.LoadFile(cmd, cmd.DefaultConfigFile())
+ if err != nil && !os.IsNotExist(err) {
+ return err
+ }
+ if fs.NArg() > 1 {
+ args = fs.Args()[1:]
+ } else {
+ args = nil
+ }
+ err = cmd.ParseFlags(args)
+ if err != nil {
+ return err
+ }
+ return cmd.Run()
+}
diff --git a/lib/agent/agent.go b/lib/agent/agent.go
new file mode 100644
index 0000000..52a3d83
--- /dev/null
+++ b/lib/agent/agent.go
@@ -0,0 +1,107 @@
+package agent
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "strings"
+)
+
+type Agent struct {
+ // 5 alphanumeric chars. Must be either xx*, yy*, zz*, or
+ // globally unique.
+ ClusterID string
+
+ // "runit" or "systemd"
+ DaemonSupervisor string
+
+ // Hostnames or IP addresses of control hosts. Use at least 3
+ // in production. System functions only when a majority are
+ // alive.
+ ControlHosts []string
+ Ports PortsConfig
+ DataDir string
+ UsrDir string
+ RunitSvDir string
+
+ ArvadosAptRepo RepoConfig
+
+ // Unseal the vault automatically at startup
+ Unseal bool
+}
+
+type PortsConfig struct {
+ ConsulDNS int
+ ConsulHTTP int
+ ConsulHTTPS int
+ ConsulRPC int
+ ConsulSerfLAN int
+ ConsulSerfWAN int
+ ConsulServer int
+ NomadHTTP int
+ NomadRPC int
+ NomadSerf int
+ VaultServer int
+}
+
+type RepoConfig struct {
+ Enabled bool
+ URL string
+ Release string
+}
+
+func Command() *Agent {
+ var repoConf RepoConfig
+ 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 = RepoConfig{
+ Enabled: true,
+ URL: "http://apt.arvados.org/",
+ Release: try,
+ }
+ break
+ }
+ }
+ ds := "runit"
+ if _, err := os.Stat("/run/systemd/system"); err == nil {
+ ds = "systemd"
+ }
+ return &Agent{
+ ClusterID: "zzzzz",
+ DaemonSupervisor: ds,
+ ArvadosAptRepo: repoConf,
+ ControlHosts: []string{"127.0.0.1"},
+ Ports: PortsConfig{
+ ConsulDNS: 18600,
+ ConsulHTTP: 18500,
+ ConsulHTTPS: -1,
+ ConsulRPC: 18400,
+ ConsulSerfLAN: 18301,
+ ConsulSerfWAN: 18302,
+ ConsulServer: 18300,
+ NomadHTTP: 14646,
+ NomadRPC: 14647,
+ NomadSerf: 14648,
+ VaultServer: 18200,
+ },
+ DataDir: "/var/lib/arvados",
+ UsrDir: "/usr/local/arvados",
+ RunitSvDir: "/etc/sv",
+ }
+}
+
+func (*Agent) ParseFlags(args []string) error {
+ return nil
+}
+
+func (a *Agent) Run() error {
+ return fmt.Errorf("not implemented: %T.Run()", a)
+}
+
+func (*Agent) DefaultConfigFile() string {
+ return "/etc/arvados/agent/agent.yml"
+}
diff --git a/lib/setup/check.go b/lib/setup/check.go
new file mode 100644
index 0000000..2b12c1f
--- /dev/null
+++ b/lib/setup/check.go
@@ -0,0 +1,12 @@
+package setup
+
+import "time"
+
+func waitCheck(timeout time.Duration, check func() error) error {
+ deadline := time.Now().Add(timeout)
+ var err error
+ for err = check(); err != nil && !time.Now().After(deadline); err = check() {
+ time.Sleep(time.Second)
+ }
+ return err
+}
diff --git a/lib/setup/command.go b/lib/setup/command.go
new file mode 100644
index 0000000..79c28b7
--- /dev/null
+++ b/lib/setup/command.go
@@ -0,0 +1,26 @@
+package setup
+
+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
+}
+
+func runStatusCmd(prog string, args ...string) (bool, error) {
+ cmd := command(prog, args...)
+ err := cmd.Run()
+ switch err.(type) {
+ case *exec.ExitError:
+ return false, nil
+ case nil:
+ return true, nil
+ default:
+ return false, err
+ }
+}
diff --git a/lib/setup/consul.go b/lib/setup/consul.go
new file mode 100644
index 0000000..0ebff83
--- /dev/null
+++ b/lib/setup/consul.go
@@ -0,0 +1,144 @@
+package setup
+
+import (
+ "crypto/rand"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path"
+ "strings"
+ "time"
+
+ "github.com/hashicorp/consul/api"
+)
+
+func (s *Setup) installConsul() error {
+ prog := s.UsrDir + "/bin/consul"
+ err := (&download{
+ URL: "https://releases.hashicorp.com/consul/0.7.4/consul_0.7.4_linux_amd64.zip",
+ Dest: prog,
+ Size: 36003597,
+ Mode: 0755,
+ PreloadDir: s.PreloadDir,
+ }).install()
+ if err != nil {
+ return err
+ }
+ dataDir := path.Join(s.DataDir, "consul")
+ if err := os.MkdirAll(dataDir, 0700); err != nil {
+ return err
+ }
+ args := []string{"agent"}
+ {
+ cf := path.Join(s.DataDir, "consul-encrypt.json")
+ if _, err := os.Stat(cf); err != nil && !os.IsNotExist(err) {
+ return err
+ } else if err != nil {
+ key, err := exec.Command(prog, "keygen").CombinedOutput()
+ if err != nil {
+ return err
+ }
+ if err = atomicWriteJSON(cf, map[string]interface{}{
+ "encrypt": strings.TrimSpace(string(key)),
+ }, 0400); err != nil {
+ return err
+ }
+ }
+ args = append(args, "-config-file="+cf)
+ }
+ {
+ s.masterToken = generateToken()
+ // os.Setenv("CONSUL_TOKEN", s.masterToken)
+ err = atomicWriteFile(path.Join(s.DataDir, "master-token.txt"), []byte(s.masterToken), 0600)
+ if err != nil {
+ return err
+ }
+ cf := path.Join(s.DataDir, "consul-config.json")
+ err = atomicWriteJSON(cf, map[string]interface{}{
+ "acl_datacenter": s.ClusterID,
+ "acl_default_policy": "deny",
+ "acl_enforce_version_8": true,
+ "acl_master_token": s.masterToken,
+ "client_addr": "0.0.0.0",
+ "bootstrap_expect": len(s.ControlHosts),
+ "data_dir": dataDir,
+ "datacenter": s.ClusterID,
+ "server": true,
+ "ui": true,
+ "ports": map[string]int{
+ "dns": s.Ports.ConsulDNS,
+ "http": s.Ports.ConsulHTTP,
+ "https": s.Ports.ConsulHTTPS,
+ "rpc": s.Ports.ConsulRPC,
+ "serf_lan": s.Ports.ConsulSerfLAN,
+ "serf_wan": s.Ports.ConsulSerfWAN,
+ "server": s.Ports.ConsulServer,
+ },
+ }, 0644)
+ if err != nil {
+ return err
+ }
+ args = append(args, "-config-file="+cf)
+ }
+ err = s.installService(daemon{
+ name: "arvados-consul",
+ prog: prog,
+ args: args,
+ noRegister: true,
+ })
+ if err != nil {
+ return err
+ }
+ if len(s.ControlHosts) > 1 {
+ cmd := exec.Command(prog, append([]string{"join"}, s.ControlHosts...)...)
+ cmd.Stdout = os.Stderr
+ cmd.Stderr = os.Stderr
+ err := cmd.Run()
+ if err != nil {
+ return fmt.Errorf("consul join: %s", err)
+ }
+ }
+ return waitCheck(20*time.Second, s.consulCheck)
+}
+
+var consulCfg = api.DefaultConfig()
+
+func (s *Setup) consulMaster() (*api.Client, error) {
+ masterToken, err := ioutil.ReadFile(path.Join(s.DataDir, "master-token.txt"))
+ if err != nil {
+ return nil, err
+ }
+ ccfg := api.DefaultConfig()
+ ccfg.Address = fmt.Sprintf("127.0.0.1:%d", s.Ports.ConsulHTTP)
+ ccfg.Datacenter = s.ClusterID
+ ccfg.Token = string(masterToken)
+ return api.NewClient(ccfg)
+}
+
+func (s *Setup) consulCheck() error {
+ consul, err := s.consulMaster()
+ if err != nil {
+ return err
+ }
+ _, err = consul.Catalog().Datacenters()
+ return err
+}
+
+// OnlyNode returns true if this is the only consul node.
+func (s *Setup) OnlyNode() (bool, error) {
+ c, err := s.consulMaster()
+ if err != nil {
+ return false, err
+ }
+ nodes, _, err := c.Catalog().Nodes(nil)
+ return len(nodes) == 1, err
+}
+
+func generateToken() string {
+ var r [16]byte
+ if _, err := rand.Read(r[:]); err != nil {
+ panic(err)
+ }
+ return fmt.Sprintf("%x", r)
+}
diff --git a/lib/setup/daemon.go b/lib/setup/daemon.go
new file mode 100644
index 0000000..3985259
--- /dev/null
+++ b/lib/setup/daemon.go
@@ -0,0 +1,75 @@
+package setup
+
+import (
+ "log"
+ "math/rand"
+ "os"
+
+ "github.com/hashicorp/consul/api"
+)
+
+type daemon struct {
+ name string
+ prog string // program to run (absolute path) -- if blank, use name
+ args []string
+ noRegister bool
+}
+
+func (s *Setup) installService(d daemon) error {
+ if d.prog == "" {
+ d.prog = d.name
+ }
+ if _, err := os.Stat(d.prog); err != nil {
+ return err
+ }
+ sup := s.superviseDaemon(d)
+ if ok, err := sup.Running(); err != nil {
+ return err
+ } else if !ok {
+ if err := sup.Start(); err != nil {
+ return err
+ }
+ }
+ if d.noRegister {
+ return nil
+ }
+ consul, err := s.consulMaster()
+ if err != nil {
+ return err
+ }
+ agent := consul.Agent()
+ svcs, err := agent.Services()
+ if err != nil {
+ return err
+ }
+ if svc, ok := svcs[d.name]; ok {
+ log.Printf("%q is registered: %#v", d.name, svc)
+ return nil
+ }
+ return agent.ServiceRegister(&api.AgentServiceRegistration{
+ ID: d.name,
+ Name: d.name,
+ Port: availablePort(),
+ })
+}
+
+type supervisor interface {
+ Running() (bool, error)
+ Start() error
+}
+
+func (s *Setup) superviseDaemon(d daemon) supervisor {
+ switch s.DaemonSupervisor {
+ case "runit":
+ return &runitService{daemon: d, etcsv: s.RunitSvDir}
+ case "systemd":
+ return &systemdSupervisor{daemon: d}
+ default:
+ log.Fatalf("unknown DaemonSupervisor %q", s.DaemonSupervisor)
+ return nil
+ }
+}
+
+func availablePort() int {
+ return rand.Intn(10000) + 20000
+}
diff --git a/lib/setup/download.go b/lib/setup/download.go
new file mode 100644
index 0000000..550f6cb
--- /dev/null
+++ b/lib/setup/download.go
@@ -0,0 +1,130 @@
+package setup
+
+import (
+ "archive/zip"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "os"
+ "path"
+ "strings"
+)
+
+type download struct {
+ URL string
+ Dest string
+ Size int64
+ Mode os.FileMode
+ Hash string
+ PreloadDir string
+}
+
+func (d *download) install() error {
+ fi, err := os.Stat(d.Dest)
+ if os.IsNotExist(err) {
+ // fall through to fix
+ } else if err != nil {
+ return err
+ } else if d.Size > 0 && fi.Size() != d.Size {
+ err = fmt.Errorf("Size mismatch: %q is %d bytes, expected %d", d.Dest, fi.Size(), d.Size)
+ } else if d.Mode > 0 && fi.Mode() != d.Mode {
+ err = fmt.Errorf("Mode mismatch: %q is %s, expected %s", d.Dest, fi.Mode(), d.Mode)
+ } else {
+ return nil
+ }
+
+ out, err := ioutil.TempFile(path.Dir(d.Dest), path.Base(d.Dest))
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if out != nil {
+ os.Remove(out.Name())
+ out.Close()
+ }
+ }()
+
+ var size int64
+ {
+ got := false
+ if d.PreloadDir != "" {
+ fn := path.Join(d.PreloadDir, path.Base(d.URL))
+ f, err := os.Open(fn)
+ defer f.Close()
+ if err == nil {
+ size, err = io.Copy(out, f)
+ if err != nil {
+ return err
+ }
+ got = true
+ }
+ }
+ if !got {
+ resp, err := http.Get(d.URL)
+ if err != nil {
+ return err
+ }
+ size, err = io.Copy(out, resp.Body)
+ resp.Body.Close()
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ if strings.HasSuffix(d.URL, ".zip") && !strings.HasSuffix(d.Dest, ".zip") {
+ r, err := zip.NewReader(out, size)
+ if err != nil {
+ return err
+ }
+ defer os.Remove(out.Name())
+ out = nil
+
+ found := false
+ for _, f := range r.File {
+ if !strings.HasSuffix(d.Dest, "/"+f.Name) {
+ continue
+ }
+ rc, err := f.Open()
+ if err != nil {
+ return err
+ }
+ defer rc.Close()
+
+ out, err = ioutil.TempFile(path.Dir(d.Dest), path.Base(d.Dest))
+ if err != nil {
+ return err
+ }
+
+ size, err = io.Copy(out, rc)
+ if err != nil {
+ return err
+ }
+ found = true
+ break
+ }
+ if !found {
+ return fmt.Errorf("File not found in archive")
+ }
+ }
+
+ if d.Size > 0 && d.Size != size {
+ return fmt.Errorf("Size mismatch: got %d bytes, expected %d", size, d.Size)
+ } else if d.Size == 0 {
+ log.Printf("%v: size was %d", d, size)
+ }
+ if err = out.Close(); err != nil {
+ return err
+ }
+ if err = os.Chmod(out.Name(), d.Mode); err != nil {
+ return err
+ }
+ err = os.Rename(out.Name(), d.Dest)
+ if err == nil {
+ // skip deferred os.Remove(out.Name())
+ out = nil
+ }
+ return err
+}
diff --git a/lib/setup/os_package.go b/lib/setup/os_package.go
new file mode 100644
index 0000000..106945b
--- /dev/null
+++ b/lib/setup/os_package.go
@@ -0,0 +1,57 @@
+package setup
+
+import (
+ "fmt"
+ "os"
+ "strings"
+ "sync"
+)
+
+type osPackage struct {
+ Debian string
+ RedHat string
+}
+
+var (
+ osPackageMutex sync.Mutex
+ osPackageDidUpdate bool
+)
+
+func (pkg *osPackage) install() error {
+ osPackageMutex.Lock()
+ defer osPackageMutex.Unlock()
+
+ if _, err := os.Stat("/var/lib/dpkg/info/" + pkg.Debian + ".list"); err == nil {
+ return nil
+ }
+ if !osPackageDidUpdate {
+ d, err := os.Open("/var/lib/apt/lists")
+ if err != nil {
+ return err
+ }
+ defer d.Close()
+ if files, err := d.Readdir(4); len(files) < 4 || err != nil {
+ err = pkg.aptGet("update")
+ if err != nil {
+ return err
+ }
+ osPackageDidUpdate = true
+ }
+ }
+ return pkg.aptGet("install", "-y", "--no-install-recommends", pkg.Debian)
+}
+
+func (*osPackage) aptGet(args ...string) error {
+ cmd := command("apt-get", args...)
+ for _, kv := range os.Environ() {
+ if !strings.HasPrefix(kv, "DEBIAN_FRONTEND=") {
+ cmd.Env = append(cmd.Env, kv)
+ }
+ }
+ cmd.Env = append(cmd.Env, "DEBIAN_FRONTEND=noninteractive")
+ err := cmd.Run()
+ if err != nil {
+ return fmt.Errorf("%s: %s", cmd.Args, err)
+ }
+ return nil
+}
diff --git a/lib/setup/runit.go b/lib/setup/runit.go
new file mode 100644
index 0000000..3e9f347
--- /dev/null
+++ b/lib/setup/runit.go
@@ -0,0 +1,41 @@
+package setup
+
+import (
+ "bytes"
+ "fmt"
+ "os"
+ "path"
+)
+
+func (s *Setup) installRunit() error {
+ if s.DaemonSupervisor != "runit" {
+ return nil
+ }
+ return (&osPackage{Debian: "runit"}).install()
+}
+
+type runitService struct {
+ daemon
+ etcsv string
+}
+
+func (r *runitService) Start() error {
+ script := &bytes.Buffer{}
+ fmt.Fprintf(script, "#!/bin/sh\n\nexec %q", r.prog)
+ for _, arg := range r.args {
+ fmt.Fprintf(script, " %q", arg)
+ }
+ fmt.Fprintf(script, " 2>&1\n")
+ return atomicWriteFile(path.Join(r.svdir(), "run"), script.Bytes(), 0755)
+}
+
+func (r *runitService) Running() (bool, error) {
+ if _, err := os.Stat(r.svdir()); err != nil && os.IsNotExist(err) {
+ return false, nil
+ }
+ return runStatusCmd("sv", "stat", r.svdir())
+}
+
+func (r *runitService) svdir() string {
+ return path.Join(r.etcsv, r.name)
+}
diff --git a/lib/setup/setup.go b/lib/setup/setup.go
new file mode 100644
index 0000000..935db1a
--- /dev/null
+++ b/lib/setup/setup.go
@@ -0,0 +1,65 @@
+package setup
+
+import (
+ "flag"
+ "fmt"
+ "os"
+
+ "git.curoverse.com/arvados.git/lib/agent"
+ "git.curoverse.com/arvados.git/sdk/go/config"
+)
+
+func Command() *Setup {
+ return &Setup{
+ Agent: agent.Command(),
+ PreloadDir: "/var/cache/arvados",
+ }
+}
+
+type Setup struct {
+ *agent.Agent
+ PreloadDir string
+
+ masterToken string
+}
+
+func (s *Setup) ParseFlags(args []string) error {
+ fs := flag.NewFlagSet("setup", flag.ContinueOnError)
+ fs.StringVar(&s.ClusterID, "cluster-id", s.ClusterID, "five-character cluster ID")
+ fs.BoolVar(&s.Unseal, "unseal", s.Unseal, "unseal the vault automatically")
+ return fs.Parse(args)
+}
+
+func (s *Setup) Run() error {
+ err := config.LoadFile(s, s.DefaultConfigFile())
+ if err != nil && !os.IsNotExist(err) {
+ return err
+ }
+ for _, f := range []func() error{
+ s.makeDirs,
+ (&osPackage{Debian: "ca-certificates"}).install,
+ (&osPackage{Debian: "nginx"}).install,
+ s.installRunit,
+ s.installConsul,
+ } {
+ err := f()
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (s *Setup) makeDirs() error {
+ for _, path := range []string{s.DataDir, s.UsrDir, s.UsrDir + "/bin"} {
+ if fi, err := os.Stat(path); err != nil {
+ err = os.MkdirAll(path, 0755)
+ if err != nil {
+ return err
+ }
+ } else if !fi.IsDir() {
+ return fmt.Errorf("%s: is not a directory", path)
+ }
+ }
+ return nil
+}
diff --git a/lib/setup/systemd.go b/lib/setup/systemd.go
new file mode 100644
index 0000000..bc3502f
--- /dev/null
+++ b/lib/setup/systemd.go
@@ -0,0 +1,20 @@
+package setup
+
+import "fmt"
+
+type systemdSupervisor struct {
+ daemon
+}
+
+func (ss *systemdSupervisor) Start() error {
+ cmd := command("systemd-run", append([]string{"--unit=arvados-" + ss.name, ss.prog}, ss.args...)...)
+ err := cmd.Run()
+ if err != nil {
+ err = fmt.Errorf("systemd-run: %s", err)
+ }
+ return err
+}
+
+func (ss *systemdSupervisor) Running() (bool, error) {
+ return runStatusCmd("systemctl", "status", "arvados-"+ss.name)
+}
diff --git a/lib/setup/write_file.go b/lib/setup/write_file.go
new file mode 100644
index 0000000..b50079c
--- /dev/null
+++ b/lib/setup/write_file.go
@@ -0,0 +1,49 @@
+package setup
+
+import (
+ "encoding/json"
+ "io/ioutil"
+ "os"
+ "path"
+)
+
+func atomicWriteFile(name string, data []byte, mode os.FileMode) error {
+ if err := os.MkdirAll(path.Dir(name), 0755); err != nil {
+ return err
+ }
+ 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
+}
+
+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)
+}
diff --git a/services/boot/testimage_runit/Dockerfile b/services/boot/testimage_runit/Dockerfile
index aaf5b88..e606868 100644
--- a/services/boot/testimage_runit/Dockerfile
+++ b/services/boot/testimage_runit/Dockerfile
@@ -11,4 +11,4 @@ RUN ["bash", "-c", "echo en_US.utf8 UTF-8 | tee -a /etc/locale.gen && locale-gen
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends ca-certificates locales nginx postgresql runit
-CMD ["bash", "-c", "runsvdir /etc/sv & exec arvados-boot"]
+CMD ["bash", "-c", "runsvdir /etc/sv & arvados-boot && arvados-boot"]
commit 016a995d5a65f9de66c505fe80ab49eebc1a11c4
Author: Tom Clegg <tom at curoverse.com>
Date: Fri Feb 17 03:09:34 2017 -0500
more vault
diff --git a/services/boot/controller.go b/services/boot/controller.go
index 4b3e249..abd0725 100644
--- a/services/boot/controller.go
+++ b/services/boot/controller.go
@@ -17,20 +17,16 @@ func (c *controller) Boot(ctx context.Context) error {
},
Concurrent{
postgresql,
- Concurrent{
- &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,
- },
- Concurrent{
- vault,
- nomad,
+ &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,
+ nomad,
// Concurrent{
// dispatchLocal,
// dispatchSLURM,
diff --git a/services/boot/nomad.go b/services/boot/nomad.go
index 632f993..0dfdd11 100644
--- a/services/boot/nomad.go
+++ b/services/boot/nomad.go
@@ -3,6 +3,7 @@ package main
import (
"context"
"fmt"
+ "io/ioutil"
"os"
"path"
"sync"
@@ -36,6 +37,11 @@ func (nb *nomadBooter) Boot(ctx context.Context) error {
return err
}
+ masterToken, err := ioutil.ReadFile(cfg.masterTokenFile())
+ if err != nil {
+ return err
+ }
+
dataDir := path.Join(cfg.DataDir, "nomad")
if err := os.MkdirAll(dataDir, 0700); err != nil {
return err
@@ -51,6 +57,7 @@ func (nb *nomadBooter) Boot(ctx context.Context) error {
},
"consul": map[string]interface{}{
"address": fmt.Sprintf("127.0.0.1:%d", cfg.Ports.ConsulHTTP),
+ "token": string(masterToken),
},
"data_dir": dataDir,
"datacenter": cfg.SiteID,
diff --git a/services/boot/vault.go b/services/boot/vault.go
index f01dbb6..4d063e7 100644
--- a/services/boot/vault.go
+++ b/services/boot/vault.go
@@ -128,31 +128,54 @@ func (vb *vaultBooter) tryInit(ctx context.Context) error {
return fmt.Errorf("vault unseal failed!")
}
+ // Use master token to create a management token
master, err := consul.master(ctx)
if err != nil {
return err
}
- token, _, err := master.ACL().Create(&consulAPI.ACLEntry{Name: "vault", Type: "management"}, nil)
+ mgmtToken, _, err := master.ACL().Create(&consulAPI.ACLEntry{Name: "vault", Type: "management"}, nil)
if err != nil {
return err
}
- err = waitCheck(ctx, 30*time.Second, func(context.Context) error {
+ if err = atomicWriteFile(path.Join(cfg.DataDir, "vault-mgmt-token.txt"), []byte(mgmtToken), 0400); err != nil {
+ return err
+ }
+
+ // Mount+configure consul backend
+ if err = waitCheck(ctx, 30*time.Second, func(context.Context) error {
+ // Typically this first fails "500 node not active but
+ // active node not found" but then succeeds.
return vault.Sys().Mount("consul", &api.MountInput{Type: "consul"})
- })
- if err != nil {
+ }); err != nil {
return err
}
_, err = vault.Logical().Write("consul/config/access", map[string]interface{}{
"address": fmt.Sprintf("127.0.0.1:%d", cfg.Ports.ConsulHTTP),
- "token": string(token),
+ "token": string(mgmtToken),
})
if err != nil {
return err
}
+
+ // Create a role
_, err = vault.Logical().Write("consul/roles/write-all", map[string]interface{}{
"policy": base64.StdEncoding.EncodeToString([]byte(`key "" { policy = "write" }`)),
})
- return err
+ if err != nil {
+ return err
+ }
+
+ // Generate a new token with the write-all role
+ secret, err := vault.Logical().Read("consul/creds/write-all")
+ if err != nil {
+ return err
+ }
+ token, ok := secret.Data["token"].(string)
+ if !ok {
+ return fmt.Errorf("secret token broken?? %+v", secret)
+ }
+ log.Printf("Vault supplied token with lease duration %s (renewable=%v): %q", time.Duration(secret.LeaseDuration)*time.Second, secret.Renewable, token)
+ return nil
}
func (vb *vaultBooter) client(ctx context.Context) (*api.Client, error) {
commit aaa536943dde5b3f1ec59c1bd18929b53dfea308
Merge: bee3010 5624fec
Author: Tom Clegg <tom at curoverse.com>
Date: Thu Feb 16 12:01:17 2017 -0500
Merge branch 'master' into deploy-agent
Conflicts:
build/package-build-dockerfiles/centos7/Dockerfile
build/package-build-dockerfiles/debian8/Dockerfile
build/package-build-dockerfiles/ubuntu1204/Dockerfile
build/package-build-dockerfiles/ubuntu1404/Dockerfile
diff --cc build/package-build-dockerfiles/centos7/Dockerfile
index 8035ef4,08bd473..189a841
--- a/build/package-build-dockerfiles/centos7/Dockerfile
+++ b/build/package-build-dockerfiles/centos7/Dockerfile
@@@ -4,12 -4,9 +4,12 @@@ MAINTAINER Brett Smith <brett at curoverse
# Install build dependencies provided in base distribution
RUN yum -q -y install make automake gcc gcc-c++ libyaml-devel patch readline-devel zlib-devel libffi-devel openssl-devel bzip2 libtool bison sqlite-devel rpm-build git perl-ExtUtils-MakeMaker libattr-devel nss-devel libcurl-devel which tar unzip scl-utils centos-release-scl postgresql-devel python-devel python-setuptools fuse-devel xz-libs git
+# Node.js
+RUN curl --silent --location https://rpm.nodesource.com/setup_6.x | bash - && yum install -y nodejs
+
# Install golang binary
- ADD generated/go1.7.1.linux-amd64.tar.gz /usr/local/
- RUN ln -s /usr/local/go/bin/go* /usr/local/bin/
+ ADD generated/go1.7.5.linux-amd64.tar.gz /usr/local/
+ RUN ln -s /usr/local/go/bin/go /usr/local/bin/
# Install RVM
RUN gpg --keyserver pool.sks-keyservers.net --recv-keys D39DC0E3 && \
commit bee301067b50d0cc00bbc1dc0a0b5c036d747a74
Author: Tom Clegg <tom at curoverse.com>
Date: Wed Feb 15 01:19:15 2017 -0500
consul acl
diff --git a/services/boot/config.go b/services/boot/config.go
index 50e2850..f301132 100644
--- a/services/boot/config.go
+++ b/services/boot/config.go
@@ -5,6 +5,7 @@ import (
"fmt"
"io/ioutil"
"os"
+ "path"
"strings"
)
@@ -107,3 +108,7 @@ func DefaultConfig() *Config {
},
}
}
+
+func (cfg *Config) masterTokenFile() string {
+ return path.Join(cfg.DataDir, "consul-master-token.txt")
+}
diff --git a/services/boot/consul.go b/services/boot/consul.go
index 3c57386..ebf8661 100644
--- a/services/boot/consul.go
+++ b/services/boot/consul.go
@@ -2,7 +2,10 @@ package main
import (
"context"
+ "crypto/rand"
+ "encoding/json"
"fmt"
+ "io/ioutil"
"os"
"os/exec"
"path"
@@ -60,14 +63,23 @@ func (cb *consulBooter) Boot(ctx context.Context) error {
args = append(args, "-config-file="+cf)
}
{
+ masterToken := generateUUID()
+ os.Setenv("CONSUL_TOKEN", masterToken)
+ err = atomicWriteFile(cfg.masterTokenFile(), []byte(masterToken), 0600)
+ if err != nil {
+ return err
+ }
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,
+ "acl_datacenter": cfg.SiteID,
+ "acl_default_policy": "deny",
+ "acl_master_token": masterToken,
+ "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,
@@ -109,11 +121,21 @@ func (cb *consulBooter) Boot(ctx context.Context) error {
var consulCfg = api.DefaultConfig()
-func (cb *consulBooter) check(ctx context.Context) error {
+func (cb *consulBooter) master(ctx context.Context) (*api.Client, 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)
+ masterToken, err := ioutil.ReadFile(cfg.masterTokenFile())
+ if err != nil {
+ return nil, err
+ }
+ ccfg := api.DefaultConfig()
+ ccfg.Address = fmt.Sprintf("127.0.0.1:%d", cfg.Ports.ConsulHTTP)
+ ccfg.Datacenter = cfg.SiteID
+ ccfg.Token = string(masterToken)
+ return api.NewClient(ccfg)
+}
+
+func (cb *consulBooter) check(ctx context.Context) error {
+ consul, err := cb.master(ctx)
if err != nil {
return err
}
@@ -121,6 +143,14 @@ func (cb *consulBooter) check(ctx context.Context) error {
if err != nil {
return err
}
+ acls, qmeta, err := consul.ACL().List(nil)
+ if err != nil {
+ return err
+ }
+ e := json.NewEncoder(os.Stderr)
+ e.SetIndent("", " ")
+ e.Encode(acls)
+ e.Encode(qmeta)
return nil
}
@@ -133,3 +163,11 @@ func (cb *consulBooter) OnlyNode() (bool, error) {
nodes, _, err := c.Catalog().Nodes(nil)
return len(nodes) == 1, err
}
+
+func generateUUID() string {
+ var r [16]byte
+ if _, err := rand.Read(r[:]); err != nil {
+ panic(err)
+ }
+ return fmt.Sprintf("%x", r)
+}
diff --git a/services/boot/supervisor.go b/services/boot/supervisor.go
index 8a46eb5..87a96c1 100644
--- a/services/boot/supervisor.go
+++ b/services/boot/supervisor.go
@@ -52,10 +52,7 @@ func (s *supervisedService) Boot(ctx context.Context) error {
return err
}
}
- if err := consul.Boot(ctx); err != nil {
- return err
- }
- consul, err := api.NewClient(consulCfg)
+ consul, err := consul.master(ctx)
if err != nil {
return err
}
diff --git a/services/boot/testimage_runit/Dockerfile b/services/boot/testimage_runit/Dockerfile
index 0541e4d..aaf5b88 100644
--- a/services/boot/testimage_runit/Dockerfile
+++ b/services/boot/testimage_runit/Dockerfile
@@ -11,4 +11,4 @@ RUN ["bash", "-c", "echo en_US.utf8 UTF-8 | tee -a /etc/locale.gen && locale-gen
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends ca-certificates locales nginx postgresql runit
-CMD ["bash", "-c", "coproc runsvdir /etc/sv; arvados-boot"]
+CMD ["bash", "-c", "runsvdir /etc/sv & exec arvados-boot"]
diff --git a/services/boot/vault.go b/services/boot/vault.go
index 7d042f8..f01dbb6 100644
--- a/services/boot/vault.go
+++ b/services/boot/vault.go
@@ -2,6 +2,7 @@ package main
import (
"context"
+ "encoding/base64"
"fmt"
"io/ioutil"
"log"
@@ -9,6 +10,7 @@ import (
"sync"
"time"
+ consulAPI "github.com/hashicorp/consul/api"
"github.com/hashicorp/vault/api"
)
@@ -40,15 +42,21 @@ func (vb *vaultBooter) Boot(ctx context.Context) error {
return err
}
+ masterToken, err := ioutil.ReadFile(cfg.masterTokenFile())
+ 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"
+ token = %q
}
listener "tcp" {
address = "127.0.0.1:%d"
tls_disable = 1
- }`, cfg.Ports.ConsulHTTP, cfg.Ports.VaultServer)), 0644)
+ }`, cfg.Ports.ConsulHTTP, masterToken, cfg.Ports.VaultServer)), 0644)
if err != nil {
return err
}
@@ -101,7 +109,9 @@ func (vb *vaultBooter) tryInit(ctx context.Context) error {
}
atomicWriteJSON(path.Join(cfg.DataDir, "vault-keys.json"), resp, 0400)
atomicWriteFile(path.Join(cfg.DataDir, "vault-root-token.txt"), []byte(resp.RootToken), 0400)
+ vault.SetToken(resp.RootToken)
+ ok := false
for _, key := range resp.Keys {
resp, err := vault.Sys().Unseal(key)
if err != nil {
@@ -110,10 +120,39 @@ func (vb *vaultBooter) tryInit(ctx context.Context) error {
}
if !resp.Sealed {
log.Printf("unseal successful")
- return nil
+ ok = true
+ break
}
}
- return fmt.Errorf("vault unseal failed!")
+ if !ok {
+ return fmt.Errorf("vault unseal failed!")
+ }
+
+ master, err := consul.master(ctx)
+ if err != nil {
+ return err
+ }
+ token, _, err := master.ACL().Create(&consulAPI.ACLEntry{Name: "vault", Type: "management"}, nil)
+ if err != nil {
+ return err
+ }
+ err = waitCheck(ctx, 30*time.Second, func(context.Context) error {
+ return vault.Sys().Mount("consul", &api.MountInput{Type: "consul"})
+ })
+ if err != nil {
+ return err
+ }
+ _, err = vault.Logical().Write("consul/config/access", map[string]interface{}{
+ "address": fmt.Sprintf("127.0.0.1:%d", cfg.Ports.ConsulHTTP),
+ "token": string(token),
+ })
+ if err != nil {
+ return err
+ }
+ _, err = vault.Logical().Write("consul/roles/write-all", map[string]interface{}{
+ "policy": base64.StdEncoding.EncodeToString([]byte(`key "" { policy = "write" }`)),
+ })
+ return err
}
func (vb *vaultBooter) client(ctx context.Context) (*api.Client, error) {
commit 15907692a7a9213ef99a74e5ef1c48a487a8ed8b
Author: Tom Clegg <tom at curoverse.com>
Date: Mon Feb 13 01:51:09 2017 -0500
gitignore
diff --git a/services/boot/.gitignore b/services/boot/.gitignore
index 8c8b8e3..72a5a79 100644
--- a/services/boot/.gitignore
+++ b/services/boot/.gitignore
@@ -3,3 +3,4 @@ bindata.tmp
node_modules
bindata_assetfs.go
npm-debug.log
+boot
commit 5eace5e8b255fdc7f65081429d0b42e551479e95
Author: Tom Clegg <tom at curoverse.com>
Date: Mon Feb 13 01:50:06 2017 -0500
consul 0.7.4, go tests
diff --git a/services/boot/consul.go b/services/boot/consul.go
index 9190aac..3c57386 100644
--- a/services/boot/consul.go
+++ b/services/boot/consul.go
@@ -29,9 +29,9 @@ func (cb *consulBooter) Boot(ctx context.Context) error {
cfg := cfg(ctx)
bin := cfg.UsrDir + "/bin/consul"
err := (&download{
- URL: "https://releases.hashicorp.com/consul/0.7.2/consul_0.7.2_linux_amd64.zip",
+ URL: "https://releases.hashicorp.com/consul/0.7.4/consul_0.7.4_linux_amd64.zip",
Dest: bin,
- Size: 29079005,
+ Size: 36003597,
Mode: 0755,
}).Boot(ctx)
if err != nil {
diff --git a/services/boot/debian8_test.go b/services/boot/debian8_test.go
new file mode 100644
index 0000000..8cfafba
--- /dev/null
+++ b/services/boot/debian8_test.go
@@ -0,0 +1,35 @@
+package main
+
+import (
+ "log"
+ "net"
+ "os"
+ "testing"
+)
+
+func TestDebian8Install(t *testing.T) {
+ cwd, err := os.Getwd()
+ if err != nil {
+ t.Fatal(err)
+ }
+ ln, err := net.Listen("tcp", ":")
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, port, err := net.SplitHostPort(ln.Addr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+ ln.Close()
+ log.Printf("Publishing consul webgui at %v", ln.Addr())
+ for _, cmdline := range [][]string{
+ {"go", "build"},
+ {"docker", "build", "--tag=arvados-boot-test-runit", "testimage_runit"},
+ {"docker", "run", "--rm", "--publish=" + port + ":18500", "--cap-add=IPC_LOCK", "--cap-add=SYS_ADMIN", "--volume=/sys/fs/cgroup", "--volume=" + cwd + "/boot:/usr/bin/arvados-boot:ro", "arvados-boot-test-runit"},
+ } {
+ err = command(cmdline[0], cmdline[1:]...).Run()
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+}
diff --git a/services/boot/testimage_runit/Dockerfile b/services/boot/testimage_runit/Dockerfile
index 3a6829d..0541e4d 100644
--- a/services/boot/testimage_runit/Dockerfile
+++ b/services/boot/testimage_runit/Dockerfile
@@ -11,4 +11,4 @@ RUN ["bash", "-c", "echo en_US.utf8 UTF-8 | tee -a /etc/locale.gen && locale-gen
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends ca-certificates locales nginx postgresql runit
-CMD ["bash", "-c", "coproc arvados-boot; runsvdir /etc/sv"]
+CMD ["bash", "-c", "coproc runsvdir /etc/sv; arvados-boot"]
commit 07f620f078c6f75cf52e9ae65040857ea1980fdc
Author: Tom Clegg <tom at curoverse.com>
Date: Sun Feb 12 12:01:52 2017 -0500
gateway conf
diff --git a/services/boot/gateway.go b/services/boot/gateway.go
index 7d0ceb0..aae7ad8 100644
--- a/services/boot/gateway.go
+++ b/services/boot/gateway.go
@@ -5,6 +5,8 @@ package main
import (
"context"
"fmt"
+ "io/ioutil"
+ "os/exec"
"path"
)
@@ -14,73 +16,81 @@ error_log stderr info; # Yes, must be specified here _and_ cmdline
events {
}
http {
- access_log {{keyOrDefault "service/gateway/access_log" "/var/log/arvados/gateway.log" | toJSON}} combined;
- upstream arv-git-http {
- server localhost:{{GITPORT}};
+ access_log {{keyOrDefault "arvados/service/gateway/access_log" "/var/log/arvados/gateway.log" | toJSON}} combined;
+ upstream git-httpd {
+ {{service "arvados-git-http"}}
+ server {{.Address}}:{{.Port}};
+ {{end}}
}
server {
- {{if keyExists"service/gateway/ports/tlsGit"}}
- listen *:{{key "service/gateway/ports/tlsGit"}} ssl default_server;
+ {{if keyExists "arvados/port/tlsGit"}}
+ listen *:{{key "arvados/port/tlsGit"}} ssl default_server;
{{end}}
- listen *:{{keyOrDefault "service/gateway/ports/tlsGateway" 443}} ssl;
- server_name git.{{key "service/gateway/domain"}};
- ssl_certificate {{SSLCERT}};
- ssl_certificate_key {{SSLKEY}};
+ listen *:{{keyOrDefault "arvados/port/tlsGateway" 443}} ssl;
+ server_name git.{{key "arvados/service/gateway/domain"}};
+ ssl_certificate {{key "arvados/service/gateway/pki/certPath"}};
+ ssl_certificate_key {{key "arvados/service/gateway/pki/keyPath"}};
location / {
- proxy_pass http://arv-git-http;
+ proxy_pass http://git-httpd;
}
}
- upstream keepproxy {
- server localhost:{{KEEPPROXYPORT}};
+ upstream keep-proxy {
+ {{service "arvados-keepproxy"}}
+ server {{.Address}}:{{.Port}};
+ {{end}}
}
server {
- listen *:{{KEEPPROXYSSLPORT}} ssl default_server;
- server_name _;
- ssl_certificate {{SSLCERT}};
- ssl_certificate_key {{SSLKEY}};
+ {{if keyExists "arvados/port/tlsKeepProxy"}}
+ listen *:{{key "arvados/port/tlsKeepProxy"}} ssl default_server;
+ {{end}}
+ listen *:{{keyOrDefault "arvados/port/tlsGateway" 443}} ssl;
+ server_name keep.{{key "arvados/service/gateway/domain"}};
+ ssl_certificate {{key "arvados/service/gateway/pki/certPath"}};
+ ssl_certificate_key {{key "arvados/service/gateway/pki/keyPath"}};
location / {
- proxy_pass http://keepproxy;
+ proxy_pass http://keep-proxy;
}
}
upstream keep-web {
- server localhost:{{KEEPWEBPORT}};
- }
- server {
- listen *:{{KEEPWEBSSLPORT}} ssl default_server;
- server_name ~^(?<request_host>.*)$;
- ssl_certificate {{SSLCERT}};
- ssl_certificate_key {{SSLKEY}};
- location / {
- proxy_pass http://keep-web;
- proxy_set_header Host $request_host:{{KEEPWEBPORT}};
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- }
+ {{service "arvados-keep-web"}}
+ server {{.Address}}:{{.Port}};
+ {{end}}
}
server {
- listen *:{{KEEPWEBDLSSLPORT}} ssl default_server;
- server_name ~.*;
- ssl_certificate {{SSLCERT}};
- ssl_certificate_key {{SSLKEY}};
+ {{if keyExists "arvados/port/tlsKeepWeb"}}
+ listen *:{{key "arvados/port/tlsKeepWeb"}} ssl default_server;
+ {{end}}
+ listen *:{{keyOrDefault "arvados/port/tlsGateway" 443}} ssl;
+ server_name download.{{key "arvados/service/gateway/domain"}}
+ collections.{{key "arvados/service/gateway/domain"}}
+ *.collections.{{key "arvados/service/gateway/domain"}}
+ ~.*--collections.{{key "arvados/service/gateway/domain"}};
+ *.collections.{{key "arvados/service/gateway/domain"}};
+ ssl_certificate {{key "arvados/service/gateway/pki/certPath"}};
+ ssl_certificate_key {{key "arvados/service/gateway/pki/keyPath"}};
location / {
proxy_pass http://keep-web;
- proxy_set_header Host download:{{KEEPWEBPORT}};
+ proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_redirect //download:{{KEEPWEBPORT}}/ https://$host:{{KEEPWEBDLSSLPORT}}/;
}
}
upstream ws {
- server localhost:{{WSPORT}};
+ {{service "arvados-ws"}}
+ server {{.Address}}:{{.Port}};
+ {{end}}
}
server {
- listen *:{{WSSPORT}} ssl default_server;
- server_name ~^(?<request_host>.*)$;
- ssl_certificate {{SSLCERT}};
- ssl_certificate_key {{SSLKEY}};
+ {{if keyExists "arvados/port/tlsWS"}}
+ listen *:{{key "arvados/port/tlsWS"}} ssl default_server;
+ {{end}}
+ listen *:{{keyOrDefault "arvados/port/tlsGateway" 443}} ssl;
+ server_name ws.{{key "arvados/service/gateway/domain"}};
+ ssl_certificate {{key "arvados/service/gateway/pki/certPath"}};
+ ssl_certificate_key {{key "arvados/service/gateway/pki/keyPath"}};
location / {
proxy_pass http://ws;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
- proxy_set_header Host $request_host:{{WSPORT}};
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
@@ -106,8 +116,11 @@ func (ngb *nginxGatewayBooter) Boot(ctx context.Context) error {
return err
}
- cfgPath := path.Join(cfg.DataDir, "gateway.consul-template.hcl")
- if err = atomicWriteJSON(cfgPath+".ctmpl", map[string]interface{}{
+ consulCfg := path.Join(cfg.DataDir, "gateway.consul-template.hcl")
+ if err = atomicWriteJSON(consulCfg+".ctmpl", map[string]interface{}{
+ "exec": map[string]interface{}{
+ "reload_signal": "SIGHUP",
+ },
"consul": map[string]interface{}{
"address": fmt.Sprintf("0.0.0.0:%d", cfg.Ports.ConsulHTTP),
},
@@ -118,27 +131,36 @@ func (ngb *nginxGatewayBooter) Boot(ctx context.Context) error {
return err
}
- tmplPath := path.Join(cfg.DataDir, "gateway.nginx.conf")
- if err = atomicWriteFile(tmplPath+".ctmpl", []byte(ngb.tmpl), 0644); err != nil {
+ nginxCfg := path.Join(cfg.DataDir, "gateway.nginx.conf")
+ if err = atomicWriteFile(nginxCfg+".ctmpl", []byte(ngb.tmpl), 0644); err != nil {
+ return err
+ }
+
+ if err := (&osPackage{
+ Debian: "nginx",
+ }).Boot(ctx); err != nil {
+ return err
+ }
+
+ nginxBin, err := exec.LookPath("nginx")
+ if err != nil {
return err
}
- return Series{
- &osPackage{
- Debian: "nginx",
+ return (&supervisedService{
+ name: ngb.name,
+ cmd: path.Join(cfg.UsrDir, "bin", "consul-template"),
+ args: []string{
+ "-config=" + consulCfg,
+ "-template=" + nginxCfg + ".ctmpl:" + nginxCfg,
+ "-exec",
+ "nginx",
+ "-g", "error_log stderr info;",
+ "-g", "pid " + path.Join(cfg.DataDir, "nginx.pid") + ";",
+ "-c", nginxCfg,
},
- &supervisedService{
- name: ngb.name,
- cmd: path.Join(cfg.UsrDir, "bin", "consul-template"),
- args: []string{
- "-config=" + cfgPath,
- "-template=" + tmplPath + ".ctmpl:" + tmplPath,
- "-exec",
- "nginx",
- },
- env: map[string]string{
- "VAULT_TOKEN": rootToken,
- },
+ env: map[string]string{
+ "VAULT_TOKEN": rootToken,
},
- }.Boot(ctx)
+ }).Boot(ctx)
}
commit dde508ae4d3f9542a16c5ebbe90de534cbdaaabb
Author: Tom Clegg <tom at curoverse.com>
Date: Sun Feb 12 12:01:46 2017 -0500
go vet
diff --git a/services/boot/check.go b/services/boot/check.go
index b71db80..7b5c776 100644
--- a/services/boot/check.go
+++ b/services/boot/check.go
@@ -6,7 +6,8 @@ import (
)
func waitCheck(ctx context.Context, timeout time.Duration, check func(ctx context.Context) error) error {
- ctx, _ = context.WithTimeout(ctx, timeout)
+ ctx, cancel := context.WithTimeout(ctx, timeout)
+ defer cancel()
var err error
for err = check(ctx); err != nil && ctx.Err() == nil; err = check(ctx) {
time.Sleep(time.Second)
diff --git a/services/boot/download.go b/services/boot/download.go
index e047aab..83b519a 100644
--- a/services/boot/download.go
+++ b/services/boot/download.go
@@ -97,7 +97,7 @@ func (d *download) Boot(ctx context.Context) error {
if d.Size > 0 && d.Size != n {
return fmt.Errorf("Size mismatch: got %d bytes, expected %d", n, d.Size)
} else if d.Size == 0 {
- log.Printf("%s: size was %d", d, n)
+ log.Printf("%v: size was %d", d, n)
}
if err = out.Close(); err != nil {
return err
commit 816f3bfd2b6a562fc712b7c2b3eb30157a95cb7e
Author: Tom Clegg <tom at curoverse.com>
Date: Sat Feb 11 03:48:35 2017 -0500
dev privileges, db
diff --git a/services/boot/package.json b/services/boot/package.json
index 7c30502..9ef7412 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 --rm -it --publish=18500:18500 --cap-add=IPC_LOCK --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 --cap-add=SYS_ADMIN --volume=/sys/fs/cgroup --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/testimage_runit/Dockerfile b/services/boot/testimage_runit/Dockerfile
index 07e7c3c..3a6829d 100644
--- a/services/boot/testimage_runit/Dockerfile
+++ b/services/boot/testimage_runit/Dockerfile
@@ -9,4 +9,6 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends ru
RUN ["bash", "-c", "echo en_US.utf8 UTF-8 | tee -a /etc/locale.gen && locale-gen -a && \
(echo LANG=en_US.UTF-8; echo LC_ALL=en_US.UTF-8) > /etc/default/locale"]
+RUN DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends ca-certificates locales nginx postgresql runit
+
CMD ["bash", "-c", "coproc arvados-boot; runsvdir /etc/sv"]
commit 61476528523e4ee2ebe199807b8aeba1e17074d4
Author: Tom Clegg <tom at curoverse.com>
Date: Tue Feb 7 01:40:04 2017 -0500
postgresql
diff --git a/services/boot/controller.go b/services/boot/controller.go
index 7ddb65b..4b3e249 100644
--- a/services/boot/controller.go
+++ b/services/boot/controller.go
@@ -31,14 +31,14 @@ func (c *controller) Boot(ctx context.Context) error {
nomad,
},
},
- Concurrent{
- dispatchLocal,
- dispatchSLURM,
- gitHTTP,
- keepbalance,
- keepproxy,
- keepstore,
- websocket,
- },
+ // Concurrent{
+ // dispatchLocal,
+ // dispatchSLURM,
+ // gitHTTP,
+ // keepbalance,
+ // keepproxy,
+ // keepstore,
+ // websocket,
+ // },
}.Boot(ctx)
}
diff --git a/services/boot/postgresql.go b/services/boot/postgresql.go
index 2be582b..e92d365 100644
--- a/services/boot/postgresql.go
+++ b/services/boot/postgresql.go
@@ -2,7 +2,6 @@ package main
import (
"context"
- "os"
"time"
)
@@ -11,20 +10,11 @@ var postgresql = &pgBooter{}
type pgBooter struct {}
func (pb *pgBooter) Boot(ctx context.Context) error {
- os.Setenv("LANG", "en_US.utf8")
// TODO: return nil if this isn't the database host.
if pb.check(ctx) == nil {
return nil
}
if err := (&osPackage{
- Debian: "locales",
- }).Boot(ctx); err != nil {
- return err
- }
- if err := command("bash", "-c", "echo ${LANG} UTF-8 | tee -a /etc/locale.gen && locale-gen -a").Run(); err != nil {
- return err
- }
- if err := (&osPackage{
Debian: "postgresql",
}).Boot(ctx); err != nil {
return err
diff --git a/services/boot/testimage_runit/Dockerfile b/services/boot/testimage_runit/Dockerfile
index d3aac96..07e7c3c 100644
--- a/services/boot/testimage_runit/Dockerfile
+++ b/services/boot/testimage_runit/Dockerfile
@@ -4,6 +4,9 @@ RUN apt-get update
# preload (but don't install) packages arvados-boot might decide to install
RUN DEBIAN_FRONTEND=noninteractive apt-get -dy install --no-install-recommends ca-certificates locales nginx postgresql runit
-RUN DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends runit
+RUN DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends runit locales
+
+RUN ["bash", "-c", "echo en_US.utf8 UTF-8 | tee -a /etc/locale.gen && locale-gen -a && \
+ (echo LANG=en_US.UTF-8; echo LC_ALL=en_US.UTF-8) > /etc/default/locale"]
CMD ["bash", "-c", "coproc arvados-boot; runsvdir /etc/sv"]
commit 668b2ae22b910765d4e7982a9d9b8a82307e4360
Author: Tom Clegg <tom at curoverse.com>
Date: Tue Feb 7 01:19:16 2017 -0500
new webpack
diff --git a/services/boot/webpack.config.js b/services/boot/webpack.config.js
index 836afea..1693554 100644
--- a/services/boot/webpack.config.js
+++ b/services/boot/webpack.config.js
@@ -3,7 +3,7 @@ module.exports = {
js: './js',
},
output: {
- directory: 'bindata.tmp',
+ path: 'bindata.tmp',
filename: 'bindata.tmp/[name].js',
},
};
commit 61f0eb808bba87639e5e4b068f444b7de0526bb2
Author: Tom Clegg <tom at curoverse.com>
Date: Mon Feb 6 09:59:22 2017 -0500
add gateway (part)
diff --git a/services/boot/gateway.go b/services/boot/gateway.go
new file mode 100644
index 0000000..7d0ceb0
--- /dev/null
+++ b/services/boot/gateway.go
@@ -0,0 +1,144 @@
+//+build ignore
+
+package main
+
+import (
+ "context"
+ "fmt"
+ "path"
+)
+
+var gateway = &nginxGatewayBooter{tmpl: `
+daemon off;
+error_log stderr info; # Yes, must be specified here _and_ cmdline
+events {
+}
+http {
+ access_log {{keyOrDefault "service/gateway/access_log" "/var/log/arvados/gateway.log" | toJSON}} combined;
+ upstream arv-git-http {
+ server localhost:{{GITPORT}};
+ }
+ server {
+ {{if keyExists"service/gateway/ports/tlsGit"}}
+ listen *:{{key "service/gateway/ports/tlsGit"}} ssl default_server;
+ {{end}}
+ listen *:{{keyOrDefault "service/gateway/ports/tlsGateway" 443}} ssl;
+ server_name git.{{key "service/gateway/domain"}};
+ ssl_certificate {{SSLCERT}};
+ ssl_certificate_key {{SSLKEY}};
+ location / {
+ proxy_pass http://arv-git-http;
+ }
+ }
+ upstream keepproxy {
+ server localhost:{{KEEPPROXYPORT}};
+ }
+ server {
+ listen *:{{KEEPPROXYSSLPORT}} ssl default_server;
+ server_name _;
+ ssl_certificate {{SSLCERT}};
+ ssl_certificate_key {{SSLKEY}};
+ location / {
+ proxy_pass http://keepproxy;
+ }
+ }
+ upstream keep-web {
+ server localhost:{{KEEPWEBPORT}};
+ }
+ server {
+ listen *:{{KEEPWEBSSLPORT}} ssl default_server;
+ server_name ~^(?<request_host>.*)$;
+ ssl_certificate {{SSLCERT}};
+ ssl_certificate_key {{SSLKEY}};
+ location / {
+ proxy_pass http://keep-web;
+ proxy_set_header Host $request_host:{{KEEPWEBPORT}};
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ }
+ }
+ server {
+ listen *:{{KEEPWEBDLSSLPORT}} ssl default_server;
+ server_name ~.*;
+ ssl_certificate {{SSLCERT}};
+ ssl_certificate_key {{SSLKEY}};
+ location / {
+ proxy_pass http://keep-web;
+ proxy_set_header Host download:{{KEEPWEBPORT}};
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_redirect //download:{{KEEPWEBPORT}}/ https://$host:{{KEEPWEBDLSSLPORT}}/;
+ }
+ }
+ upstream ws {
+ server localhost:{{WSPORT}};
+ }
+ server {
+ listen *:{{WSSPORT}} ssl default_server;
+ server_name ~^(?<request_host>.*)$;
+ ssl_certificate {{SSLCERT}};
+ ssl_certificate_key {{SSLKEY}};
+ location / {
+ proxy_pass http://ws;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "upgrade";
+ proxy_set_header Host $request_host:{{WSPORT}};
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ }
+ }
+}
+`}
+
+type nginxGatewayBooter struct {
+ tmpl string
+}
+
+func (ngb *nginxGatewayBooter) Boot(ctx context.Context) error {
+ cfg := cfg(ctx)
+
+ if ngb.conf == "" {
+ ngb.conf = ngb.name
+ }
+ if ngb.tmpl == "" {
+ ngb.tmpl = "{}"
+ }
+
+ rootToken, err := ioutil.ReadFile(path.Join(cfg.DataDir, "vault-root-token.txt"))
+ if err != nil {
+ return err
+ }
+
+ cfgPath := path.Join(cfg.DataDir, "gateway.consul-template.hcl")
+ if err = atomicWriteJSON(cfgPath+".ctmpl", map[string]interface{}{
+ "consul": map[string]interface{}{
+ "address": fmt.Sprintf("0.0.0.0:%d", cfg.Ports.ConsulHTTP),
+ },
+ "vault": map[string]string{
+ "address": fmt.Sprintf("http://0.0.0.0:%d", cfg.Ports.VaultServer),
+ "token": rootToken,
+ }}, 0600); err != nil {
+ return err
+ }
+
+ tmplPath := path.Join(cfg.DataDir, "gateway.nginx.conf")
+ if err = atomicWriteFile(tmplPath+".ctmpl", []byte(ngb.tmpl), 0644); err != nil {
+ return err
+ }
+
+ return Series{
+ &osPackage{
+ Debian: "nginx",
+ },
+ &supervisedService{
+ name: ngb.name,
+ cmd: path.Join(cfg.UsrDir, "bin", "consul-template"),
+ args: []string{
+ "-config=" + cfgPath,
+ "-template=" + tmplPath + ".ctmpl:" + tmplPath,
+ "-exec",
+ "nginx",
+ },
+ env: map[string]string{
+ "VAULT_TOKEN": rootToken,
+ },
+ },
+ }.Boot(ctx)
+}
commit 126f499d2f084963a5ef5df7cf567a1ed4cb96ed
Author: Tom Clegg <tom at curoverse.com>
Date: Mon Feb 6 05:49:04 2017 -0500
add postgresql
diff --git a/services/boot/arvados_packages.go b/services/boot/arvados_packages.go
index 5115b46..eee5f88 100644
--- a/services/boot/arvados_packages.go
+++ b/services/boot/arvados_packages.go
@@ -4,16 +4,16 @@ import (
"context"
"io/ioutil"
"os"
- "sync"
)
var arvadosRepo = &arvadosRepoBooter{}
-type arvadosRepoBooter struct {
- sync.Mutex
-}
+type arvadosRepoBooter struct {}
func (*arvadosRepoBooter) Boot(ctx context.Context) error {
+ osPackageMutex.Lock()
+ defer osPackageMutex.Unlock()
+
cfg := cfg(ctx)
repo := cfg.ArvadosAptRepo
if !repo.Enabled {
diff --git a/services/boot/check.go b/services/boot/check.go
new file mode 100644
index 0000000..b71db80
--- /dev/null
+++ b/services/boot/check.go
@@ -0,0 +1,15 @@
+package main
+
+import (
+ "context"
+ "time"
+)
+
+func waitCheck(ctx context.Context, timeout time.Duration, check func(ctx context.Context) error) error {
+ ctx, _ = context.WithTimeout(ctx, timeout)
+ var err error
+ for err = check(ctx); err != nil && ctx.Err() == nil; err = check(ctx) {
+ time.Sleep(time.Second)
+ }
+ return err
+}
diff --git a/services/boot/controller.go b/services/boot/controller.go
index 784f09f..7ddb65b 100644
--- a/services/boot/controller.go
+++ b/services/boot/controller.go
@@ -16,17 +16,20 @@ func (c *controller) Boot(ctx context.Context) error {
arvadosRepo,
},
Concurrent{
- &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,
+ postgresql,
+ Concurrent{
+ &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,
+ },
+ Concurrent{
+ vault,
+ nomad,
},
- consul,
- },
- Concurrent{
- vault,
- nomad,
},
Concurrent{
dispatchLocal,
diff --git a/services/boot/postgresql.go b/services/boot/postgresql.go
new file mode 100644
index 0000000..2be582b
--- /dev/null
+++ b/services/boot/postgresql.go
@@ -0,0 +1,40 @@
+package main
+
+import (
+ "context"
+ "os"
+ "time"
+)
+
+var postgresql = &pgBooter{}
+
+type pgBooter struct {}
+
+func (pb *pgBooter) Boot(ctx context.Context) error {
+ os.Setenv("LANG", "en_US.utf8")
+ // TODO: return nil if this isn't the database host.
+ if pb.check(ctx) == nil {
+ return nil
+ }
+ if err := (&osPackage{
+ Debian: "locales",
+ }).Boot(ctx); err != nil {
+ return err
+ }
+ if err := command("bash", "-c", "echo ${LANG} UTF-8 | tee -a /etc/locale.gen && locale-gen -a").Run(); err != nil {
+ return err
+ }
+ if err := (&osPackage{
+ Debian: "postgresql",
+ }).Boot(ctx); err != nil {
+ return err
+ }
+ if err := command("service", "postgresql", "start").Run(); err != nil {
+ return err
+ }
+ return waitCheck(ctx, 30*time.Second, pb.check)
+}
+
+func (pb *pgBooter) check(ctx context.Context) error {
+ return command("pg_isready").Run()
+}
diff --git a/services/boot/testimage_runit/Dockerfile b/services/boot/testimage_runit/Dockerfile
index 1bab296..d3aac96 100644
--- a/services/boot/testimage_runit/Dockerfile
+++ b/services/boot/testimage_runit/Dockerfile
@@ -2,7 +2,7 @@ FROM debian:8
RUN apt-get update
# preload (but don't install) packages arvados-boot might decide to install
-RUN DEBIAN_FRONTEND=noninteractive apt-get -dy install --no-install-recommends ca-certificates nginx runit
+RUN DEBIAN_FRONTEND=noninteractive apt-get -dy install --no-install-recommends ca-certificates locales nginx postgresql runit
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends runit
commit 674236324476c58ccf20d554acd4427dfb6b9873
Author: Tom Clegg <tom at curoverse.com>
Date: Mon Feb 6 05:12:59 2017 -0500
just try init once
diff --git a/services/boot/consul.go b/services/boot/consul.go
index f51d694..9190aac 100644
--- a/services/boot/consul.go
+++ b/services/boot/consul.go
@@ -8,6 +8,7 @@ import (
"path"
"strings"
"sync"
+ "time"
"github.com/hashicorp/consul/api"
)
@@ -36,25 +37,25 @@ func (cb *consulBooter) Boot(ctx context.Context) error {
if err != nil {
return err
}
- dataDir := cfg.DataDir + "/consul"
+ dataDir := path.Join(cfg.DataDir, "consul")
if err := os.MkdirAll(dataDir, 0700); err != nil {
return err
}
args := []string{"agent"}
{
cf := path.Join(cfg.DataDir, "consul-encrypt.json")
- _, err := os.Stat(cf)
- if os.IsNotExist(err) {
+ if _, err := os.Stat(cf); err != nil && !os.IsNotExist(err) {
+ return err
+ } else if err != nil {
key, err := exec.Command(bin, "keygen").CombinedOutput()
if err != nil {
return err
}
- err = atomicWriteJSON(cf, map[string]interface{}{
+ if err = atomicWriteJSON(cf, map[string]interface{}{
"encrypt": strings.TrimSpace(string(key)),
- }, 0400)
- }
- if err != nil {
- return err
+ }, 0400); err != nil {
+ return err
+ }
}
args = append(args, "-config-file="+cf)
}
@@ -103,7 +104,7 @@ func (cb *consulBooter) Boot(ctx context.Context) error {
}
}
}
- return cb.check(ctx)
+ return waitCheck(ctx, 30*time.Second, cb.check)
}
var consulCfg = api.DefaultConfig()
diff --git a/services/boot/main.go b/services/boot/main.go
index ebab009..f145e15 100644
--- a/services/boot/main.go
+++ b/services/boot/main.go
@@ -6,7 +6,6 @@ import (
"flag"
"log"
"os"
- "time"
"git.curoverse.com/arvados.git/sdk/go/config"
)
@@ -28,19 +27,9 @@ func main() {
enc.SetIndent("", " ")
enc.Encode(cfg)
- go runWebGUI(cfg)
- go func() {
- var ctl Booter = &controller{}
- ticker := time.NewTicker(5 * time.Second)
- for {
- err := ctl.Boot(withCfg(context.Background(), cfg))
- if err != nil {
- log.Printf("controller boot failed: %v", err)
- } else {
- log.Printf("controller boot OK")
- }
- <-ticker.C
- }
- }()
- <-(chan struct{})(nil)
+ var ctl Booter = &controller{}
+ err := ctl.Boot(withCfg(context.Background(), cfg))
+ if err != nil {
+ log.Printf("controller boot failed: %v", err)
+ }
}
diff --git a/services/boot/nomad.go b/services/boot/nomad.go
index 07c5de8..632f993 100644
--- a/services/boot/nomad.go
+++ b/services/boot/nomad.go
@@ -6,6 +6,7 @@ import (
"os"
"path"
"sync"
+ "time"
"github.com/hashicorp/nomad/api"
)
@@ -28,7 +29,7 @@ func (nb *nomadBooter) Boot(ctx context.Context) error {
err := (&download{
URL: "https://releases.hashicorp.com/nomad/0.5.4/nomad_0.5.4_linux_amd64.zip",
Dest: bin,
- //Size: 29079005,
+ Size: 34150464,
Mode: 0755,
}).Boot(ctx)
if err != nil {
@@ -79,7 +80,7 @@ func (nb *nomadBooter) Boot(ctx context.Context) error {
return fmt.Errorf("starting nomad: %s", err)
}
}
- return nb.check(ctx)
+ return waitCheck(ctx, 30*time.Second, nb.check)
}
var nomadCfg = api.DefaultConfig()
diff --git a/services/boot/testimage_runit/Dockerfile b/services/boot/testimage_runit/Dockerfile
index b65a158..1bab296 100644
--- a/services/boot/testimage_runit/Dockerfile
+++ b/services/boot/testimage_runit/Dockerfile
@@ -1,10 +1,9 @@
FROM debian:8
RUN apt-get update
-RUN DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends runit
-RUN mkdir /etc/sv/arvados-boot && ln -s /usr/bin/arvados-boot /etc/sv/arvados-boot/run
-
# preload (but don't install) packages arvados-boot might decide to install
-RUN DEBIAN_FRONTEND=noninteractive apt-get -dy install --no-install-recommends ca-certificates nginx
+RUN DEBIAN_FRONTEND=noninteractive apt-get -dy install --no-install-recommends ca-certificates nginx runit
+
+RUN DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends runit
-CMD ["sh", "-c", "runsvdir /etc/sv"]
+CMD ["bash", "-c", "coproc arvados-boot; runsvdir /etc/sv"]
diff --git a/services/boot/vault.go b/services/boot/vault.go
index de9cfb3..7d042f8 100644
--- a/services/boot/vault.go
+++ b/services/boot/vault.go
@@ -7,6 +7,7 @@ import (
"log"
"path"
"sync"
+ "time"
"github.com/hashicorp/vault/api"
)
@@ -66,29 +67,37 @@ func (vb *vaultBooter) Boot(ctx context.Context) error {
}
}
- vb.tryInit(ctx)
- return vb.check(ctx)
+ if err := vb.tryInit(ctx); err != nil {
+ return err
+ }
+ return waitCheck(ctx, 30*time.Second, vb.check)
}
-func (vb *vaultBooter) tryInit(ctx context.Context) {
+func (vb *vaultBooter) tryInit(ctx context.Context) error {
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
+
+ var vault *api.Client
+ var init bool
+ if err := waitCheck(ctx, time.Minute, func(context.Context) error {
+ var err error
+ vault, err = vb.client(ctx)
+ if err != nil {
+ return err
+ }
+ init, err = vault.Sys().InitStatus()
+ return err
+ }); err != nil {
+ return err
} else if init {
- return
+ return nil
}
+
resp, err := vault.Sys().Init(&api.InitRequest{
SecretShares: 5,
SecretThreshold: 3,
})
if err != nil {
- log.Printf("vault-init: %s", err)
- return
+ return fmt.Errorf("vault-init: %s", err)
}
atomicWriteJSON(path.Join(cfg.DataDir, "vault-keys.json"), resp, 0400)
atomicWriteFile(path.Join(cfg.DataDir, "vault-root-token.txt"), []byte(resp.RootToken), 0400)
@@ -101,9 +110,10 @@ func (vb *vaultBooter) tryInit(ctx context.Context) {
}
if !resp.Sealed {
log.Printf("unseal successful")
- break
+ return nil
}
}
+ return fmt.Errorf("vault unseal failed!")
}
func (vb *vaultBooter) client(ctx context.Context) (*api.Client, error) {
commit 87107582273d254e98a66a3036bc0fc487edfa68
Author: Tom Clegg <tom at curoverse.com>
Date: Mon Feb 6 04:27:09 2017 -0500
add nomad
diff --git a/services/boot/config.go b/services/boot/config.go
index 3ee981d..50e2850 100644
--- a/services/boot/config.go
+++ b/services/boot/config.go
@@ -34,6 +34,9 @@ type portsConfig struct {
ConsulSerfLAN int
ConsulSerfWAN int
ConsulServer int
+ NomadHTTP int
+ NomadRPC int
+ NomadSerf int
VaultServer int
}
@@ -91,6 +94,9 @@ func DefaultConfig() *Config {
ConsulSerfLAN: 18301,
ConsulSerfWAN: 18302,
ConsulServer: 18300,
+ NomadHTTP: 14646,
+ NomadRPC: 14647,
+ NomadSerf: 14648,
VaultServer: 18200,
},
DataDir: "/var/lib/arvados",
diff --git a/services/boot/controller.go b/services/boot/controller.go
index 953507f..784f09f 100644
--- a/services/boot/controller.go
+++ b/services/boot/controller.go
@@ -24,7 +24,10 @@ func (c *controller) Boot(ctx context.Context) error {
},
consul,
},
- vault,
+ Concurrent{
+ vault,
+ nomad,
+ },
Concurrent{
dispatchLocal,
dispatchSLURM,
diff --git a/services/boot/nomad.go b/services/boot/nomad.go
new file mode 100644
index 0000000..07c5de8
--- /dev/null
+++ b/services/boot/nomad.go
@@ -0,0 +1,99 @@
+package main
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "path"
+ "sync"
+
+ "github.com/hashicorp/nomad/api"
+)
+
+var nomad = &nomadBooter{}
+
+type nomadBooter struct {
+ sync.Mutex
+}
+
+func (nb *nomadBooter) Boot(ctx context.Context) error {
+ nb.Lock()
+ defer nb.Unlock()
+
+ if nb.check(ctx) == nil {
+ return nil
+ }
+ cfg := cfg(ctx)
+ bin := cfg.UsrDir + "/bin/nomad"
+ err := (&download{
+ URL: "https://releases.hashicorp.com/nomad/0.5.4/nomad_0.5.4_linux_amd64.zip",
+ Dest: bin,
+ //Size: 29079005,
+ Mode: 0755,
+ }).Boot(ctx)
+ if err != nil {
+ return err
+ }
+
+ dataDir := path.Join(cfg.DataDir, "nomad")
+ if err := os.MkdirAll(dataDir, 0700); err != nil {
+ return err
+ }
+
+ cf := path.Join(cfg.DataDir, "nomad.json")
+ err = atomicWriteJSON(cf, map[string]interface{}{
+ "client": map[string]interface{}{
+ "enabled": true,
+ "options": map[string]interface{}{
+ "driver.raw_exec.enable": true,
+ },
+ },
+ "consul": map[string]interface{}{
+ "address": fmt.Sprintf("127.0.0.1:%d", cfg.Ports.ConsulHTTP),
+ },
+ "data_dir": dataDir,
+ "datacenter": cfg.SiteID,
+ "ports": map[string]int{
+ "http": cfg.Ports.NomadHTTP,
+ "rpc": cfg.Ports.NomadRPC,
+ "serf": cfg.Ports.NomadSerf,
+ },
+ "server": map[string]interface{}{
+ "enabled": true,
+ "bootstrap_expect": len(cfg.ControlHosts),
+ },
+ }, 0644)
+ if err != nil {
+ return err
+ }
+
+ supervisor := newSupervisor(ctx, "arvados-nomad", bin, "agent", "-config="+cf)
+ running, err := supervisor.Running(ctx)
+ if err != nil {
+ return err
+ }
+ if !running {
+ defer feedbackf(ctx, "starting nomad service")()
+ err = supervisor.Start(ctx)
+ if err != nil {
+ return fmt.Errorf("starting nomad: %s", err)
+ }
+ }
+ return nb.check(ctx)
+}
+
+var nomadCfg = api.DefaultConfig()
+
+func (nb *nomadBooter) check(ctx context.Context) error {
+ cfg := cfg(ctx)
+ nomadCfg.Address = fmt.Sprintf("http://127.0.0.1:%d", cfg.Ports.NomadHTTP)
+ nomad, err := api.NewClient(nomadCfg)
+ if err != nil {
+ return err
+ }
+ _, err = nomad.Agent().Datacenter()
+ if err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/services/boot/runit.go b/services/boot/runit.go
index ec906ad..a47db32 100644
--- a/services/boot/runit.go
+++ b/services/boot/runit.go
@@ -4,8 +4,6 @@ import (
"bytes"
"context"
"fmt"
- "io/ioutil"
- "os"
"path"
)
@@ -20,7 +18,7 @@ func (r *runitService) Start(ctx context.Context) error {
return err
}
- var script bytes.Buffer
+ script := &bytes.Buffer{}
fmt.Fprintf(script, "#!/bin/sh\n\nexec %q", r.cmd)
for _, arg := range r.args {
fmt.Fprintf(script, " %q", arg)
commit 51f5a4ede44615be700eec7fcbfe3c1e60c842ac
Author: Tom Clegg <tom at curoverse.com>
Date: Fri Feb 3 13:15:02 2017 -0500
tidy runit
diff --git a/services/boot/runit.go b/services/boot/runit.go
index e5bf520..ec906ad 100644
--- a/services/boot/runit.go
+++ b/services/boot/runit.go
@@ -1,6 +1,7 @@
package main
import (
+ "bytes"
"context"
"fmt"
"io/ioutil"
@@ -18,29 +19,15 @@ func (r *runitService) Start(ctx context.Context) error {
if err := installRunit.Boot(ctx); err != nil {
return err
}
- svdir := r.svdir(ctx)
- if err := os.MkdirAll(svdir, 0755); err != nil {
- return err
- }
- tmp, err := ioutil.TempFile(svdir, "run~")
- if err != nil {
- return err
- }
- fmt.Fprintf(tmp, "#!/bin/sh\n\nexec %q", r.cmd)
+
+ var script bytes.Buffer
+ fmt.Fprintf(script, "#!/bin/sh\n\nexec %q", r.cmd)
for _, arg := range r.args {
- fmt.Fprintf(tmp, " %q", arg)
+ fmt.Fprintf(script, " %q", arg)
}
- fmt.Fprintf(tmp, " 2>&1\n")
- tmp.Close()
- if err := os.Chmod(tmp.Name(), 0755); err != nil {
- os.Remove(tmp.Name())
- return err
- }
- if err := os.Rename(tmp.Name(), path.Join(svdir, "run")); err != nil {
- os.Remove(tmp.Name())
- return err
- }
- return nil
+ fmt.Fprintf(script, " 2>&1\n")
+
+ return atomicWriteFile(path.Join(r.svdir(ctx), "run"), script.Bytes(), 0755)
}
func (r *runitService) Running(ctx context.Context) (bool, error) {
diff --git a/services/boot/supervisor.go b/services/boot/supervisor.go
index 43909e8..8a46eb5 100644
--- a/services/boot/supervisor.go
+++ b/services/boot/supervisor.go
@@ -32,7 +32,7 @@ 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 // name to register with consul
- cmd string // program to run (absolute path)
+ cmd string // program to run (absolute path) -- if blank, use name
args []string
}
diff --git a/services/boot/write_file.go b/services/boot/write_file.go
index d482f16..2a5de46 100644
--- a/services/boot/write_file.go
+++ b/services/boot/write_file.go
@@ -8,6 +8,9 @@ import (
)
func atomicWriteFile(name string, data []byte, mode os.FileMode) error {
+ if err := os.MkdirAll(path.Dir(name), 0755); err != nil {
+ return err
+ }
tmp, err := ioutil.TempFile(path.Dir(name), path.Base(name)+"~")
if err != nil {
return err
commit 8a882eff8b8359d58b56f1bc7cd2da95775d97eb
Author: Tom Clegg <tom at curoverse.com>
Date: Thu Feb 2 20:03:09 2017 -0500
move import
diff --git a/services/boot/arvados_go.go b/services/boot/arvados_go.go
index 3d60dde..c4cd499 100644
--- a/services/boot/arvados_go.go
+++ b/services/boot/arvados_go.go
@@ -4,7 +4,6 @@ import (
"context"
"fmt"
"log"
- "math/rand"
"os"
"path"
"path/filepath"
diff --git a/services/boot/supervisor.go b/services/boot/supervisor.go
index a8d8a8c..43909e8 100644
--- a/services/boot/supervisor.go
+++ b/services/boot/supervisor.go
@@ -3,6 +3,7 @@ package main
import (
"context"
"log"
+ "math/rand"
"os"
"github.com/hashicorp/consul/api"
@@ -30,8 +31,8 @@ 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 // name to register with consul
- cmd string // program to run (absolute path)
+ name string // name to register with consul
+ cmd string // program to run (absolute path)
args []string
}
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list