[ARVADOS] updated: 059a62b51d90f82e4286835d26d8bf523a54132b
Git user
git at public.curoverse.com
Fri Apr 28 17:04:35 EDT 2017
Summary of changes:
.../app/assets/javascripts/edit_collection.js | 45 ++
.../app/assets/javascripts/selection.js.erb | 7 +
.../app/assets/stylesheets/collections.css.scss | 6 +
.../app/controllers/actions_controller.rb | 37 +-
.../app/controllers/application_controller.rb | 56 +-
.../app/controllers/collections_controller.rb | 52 ++
.../controllers/container_requests_controller.rb | 27 +-
.../app/controllers/keep_disks_controller.rb | 1 +
.../workbench/app/controllers/search_controller.rb | 3 +
apps/workbench/app/controllers/users_controller.rb | 1 +
apps/workbench/app/helpers/application_helper.rb | 6 +-
apps/workbench/app/helpers/provenance_helper.rb | 48 ++
apps/workbench/app/models/arvados_base.rb | 4 +
apps/workbench/app/models/arvados_resource_list.rb | 8 +
apps/workbench/app/models/collection.rb | 2 +-
apps/workbench/app/models/job.rb | 2 +-
apps/workbench/app/models/pipeline_instance.rb | 7 +-
apps/workbench/app/models/proxy_work_unit.rb | 1 +
apps/workbench/app/models/workflow.rb | 8 +
.../app/views/application/_content.html.erb | 2 +-
.../collections/_extra_tab_line_buttons.html.erb | 3 +
.../app/views/collections/_show_files.html.erb | 36 +-
.../_extra_tab_line_buttons.html.erb | 2 +-
.../_show_provenance.html.erb | 4 +-
.../app/views/projects/_show_dashboard.html.erb | 12 +-
.../app/views/work_units/_show_child.html.erb | 4 +-
.../app/views/workflows/_show_recent.html.erb | 65 ++
apps/workbench/config/routes.rb | 1 +
.../controllers/collections_controller_test.rb | 132 +++-
.../container_requests_controller_test.rb | 21 +
.../test/controllers/disabled_api_test.rb | 11 +
.../test/integration/collection_upload_test.rb | 14 +
.../workbench/test/integration/collections_test.rb | 122 ++++
.../test/integration/container_requests_test.rb | 12 +
apps/workbench/test/integration/work_units_test.rb | 24 +
apps/workbench/test/integration_helper.rb | 15 +
.../test/unit/arvados_resource_list_test.rb | 8 +
apps/workbench/test/unit/link_test.rb | 3 +
apps/workbench/test/unit/pipeline_instance_test.rb | 3 +
apps/workbench/test/unit/work_unit_test.rb | 3 +
build/build.list | 12 +-
.../package-test-dockerfiles/ubuntu1204/Dockerfile | 2 +-
build/rails-package-scripts/postinst.sh | 4 +-
build/run-build-packages-one-target.sh | 2 +-
build/run-build-packages-sso.sh | 3 +
build/run-build-packages.sh | 4 +-
build/run-library.sh | 2 +
build/run-tests.sh | 17 +-
cmd/arvados-admin/.gitignore | 1 -
cmd/arvados-admin/main.go | 26 -
cmd/arvados-admin/setup_docker_compose_test.go | 23 -
doc/_config.yml | 6 +
doc/_includes/_compute_ping_rb.liquid | 285 ++++++++
doc/_includes/_navbar_top.liquid | 2 +-
.../methods/container_requests.html.textile.liquid | 2 +
.../install-compute-node.html.textile.liquid | 6 +
.../install-dispatch.html.textile.liquid | 15 +
.../install-slurm.html.textile.liquid} | 96 +--
doc/install/install-api-server.html.textile.liquid | 86 +--
.../install-compute-ping.html.textile.liquid | 9 +
.../install-keep-balance.html.textile.liquid | 15 +-
doc/install/install-keepstore.html.textile.liquid | 4 +-
.../install-nodemanager.html.textile.liquid | 592 ++++++++++++++++
doc/install/install-ws.html.textile.liquid | 12 +-
doc/install/migrate-docker19.html.textile.liquid | 34 +
doc/user/cwl/cwl-extensions.html.textile.liquid | 17 +
docker/migrate-docker19/Dockerfile | 31 +
docker/migrate-docker19/build.sh | 2 +
.../docker/run => docker/migrate-docker19/dnd.sh | 15 +-
docker/migrate-docker19/migrate.sh | 110 +++
{cmd => lib/cmd}/dispatch.go | 0
lib/configure/configure.go | 32 +
sdk/cli/arvados-cli.gemspec | 4 +-
sdk/cli/bin/crunch-job | 32 +-
sdk/cli/test/binstub_arv-mount/arv-mount | 1 +
.../test/binstub_clean_fail/{mount => arv-mount} | 0
sdk/cli/test/test_arv-collection-create.rb | 1 +
sdk/cli/test/test_arv-keep-get.rb | 4 +-
sdk/cli/test/test_crunch-job.rb | 4 +-
sdk/cwl/arvados_cwl/__init__.py | 70 +-
sdk/cwl/arvados_cwl/arv-cwl-schema.yml | 31 +
sdk/cwl/arvados_cwl/arvcontainer.py | 71 +-
sdk/cwl/arvados_cwl/arvdocker.py | 8 +-
sdk/cwl/arvados_cwl/arvjob.py | 8 +-
sdk/cwl/arvados_cwl/arvworkflow.py | 5 +-
sdk/cwl/arvados_cwl/crunch_script.py | 15 +-
sdk/cwl/arvados_cwl/fsaccess.py | 39 +-
sdk/cwl/arvados_cwl/pathmapper.py | 106 +--
sdk/cwl/arvados_cwl/runner.py | 21 +-
sdk/cwl/setup.py | 7 +-
sdk/cwl/test_with_arvbox.sh | 2 +
sdk/cwl/tests/arvados-tests.sh | 2 +-
sdk/cwl/tests/arvados-tests.yml | 74 ++
sdk/cwl/tests/cat.cwl | 8 +
sdk/cwl/tests/dir-job2.yml | 3 +
...dir-test-input.cwl => keep-dir-test-input2.cwl} | 3 +
...dir-test-input.cwl => keep-dir-test-input3.cwl} | 3 +
sdk/cwl/tests/listing-job.yml | 3 +
sdk/cwl/tests/octo.yml | 3 +
.../cwl/tests/octothorpe/item #1.txt | 0
sdk/cwl/tests/test_container.py | 171 ++++-
sdk/cwl/tests/test_fsaccess.py | 28 +
sdk/cwl/tests/test_job.py | 9 +-
sdk/cwl/tests/test_pathmapper.py | 25 +-
sdk/cwl/tests/test_submit.py | 41 +-
.../cwl/tests/tmp1/tmp2/tmp3}/.gitkeep | 0
sdk/cwl/tests/wf/listing_deep.cwl | 15 +
sdk/cwl/tests/wf/listing_none.cwl | 15 +
sdk/cwl/tests/wf/listing_shallow.cwl | 15 +
sdk/cwl/tests/wf/scatter2.cwl | 1 +
sdk/cwl/tests/wf/scatter2_subwf.cwl | 5 +-
sdk/go/arvados/client.go | 7 +
sdk/go/arvados/collection.go | 4 +-
sdk/go/arvados/log.go | 12 +-
sdk/go/arvados/workflow.go | 22 +
sdk/go/arvadosclient/arvadosclient_test.go | 7 +-
sdk/go/arvadostest/fixtures.go | 26 +-
sdk/go/crunchrunner/crunchrunner.go | 66 +-
sdk/go/crunchrunner/crunchrunner_test.go | 51 +-
sdk/go/dispatch/throttle_test.go | 29 +-
sdk/go/keepclient/discover.go | 15 +-
sdk/go/keepclient/keepclient.go | 22 +-
sdk/go/keepclient/keepclient_test.go | 20 +-
sdk/go/keepclient/support.go | 108 +--
sdk/python/arvados/__init__.py | 1 -
sdk/python/arvados/_ranges.py | 8 +-
sdk/python/arvados/api.py | 15 +-
sdk/python/arvados/arvfile.py | 225 ++++---
sdk/python/arvados/cache.py | 71 ++
sdk/python/arvados/collection.py | 1 +
sdk/python/arvados/commands/get.py | 282 ++++++++
sdk/python/arvados/commands/keepdocker.py | 92 +--
sdk/python/arvados/commands/ls.py | 57 +-
sdk/python/arvados/commands/migrate19.py | 280 ++++++++
sdk/python/arvados/commands/put.py | 29 +-
sdk/python/arvados/commands/run.py | 88 ++-
sdk/python/arvados/keep.py | 19 +-
sdk/python/bin/arv-get | 235 +------
sdk/python/bin/arv-migrate-docker19 | 4 +-
sdk/python/setup.py | 12 +-
sdk/python/tests/run_test_server.py | 24 +-
sdk/python/tests/test_arv_get.py | 137 ++++
sdk/python/tests/test_arv_keepdocker.py | 44 +-
sdk/python/tests/test_arv_ls.py | 11 +-
sdk/python/tests/test_arvfile.py | 134 +++-
sdk/python/tests/test_cache.py | 95 +++
sdk/python/tests/test_collections.py | 60 +-
sdk/python/tests/test_stream.py | 7 +-
sdk/ruby/arvados.gemspec | 2 +-
sdk/ruby/lib/arvados.rb | 23 +-
sdk/ruby/lib/arvados/keep.rb | 6 +-
{lib => server}/agent/agent.go | 14 +
server/arvados-server/.gitignore | 1 +
server/arvados-server/docker_compose_test.go | 43 ++
server/arvados-server/main.go | 29 +
.../arvados-server/setup_test.go | 6 +-
.../arvados-server}/test-docker-compose/agent.yml | 0
.../test-docker-compose/docker-compose.yml | 24 +-
.../test-docker-compose/encrypt-key.txt | 0
.../test-docker-compose/master-token.txt | 0
.../arvados-server/test-setup}/Dockerfile | 2 +-
server/setup/arvados_services.go | 242 +++++++
server/setup/cert.go | 24 +
{lib => server}/setup/check.go | 0
{lib => server}/setup/command.go | 0
server/setup/configure.go | 65 ++
{lib => server}/setup/consul.go | 62 +-
server/setup/curoverse_package.go | 36 +
{lib => server}/setup/daemon.go | 2 +-
{lib => server}/setup/download.go | 0
{lib => server}/setup/os_package.go | 0
{lib => server}/setup/runit.go | 0
{lib => server}/setup/setup.go | 54 +-
{lib => server}/setup/systemd.go | 0
server/setup/tmpl_nginx_api.go | 95 +++
{lib => server}/setup/vault.go | 15 +-
{lib => server}/setup/write_file.go | 0
services/api/.gitignore | 3 +-
services/api/Gemfile | 53 +-
services/api/Gemfile.lock | 279 ++++----
services/api/Rakefile | 16 +-
.../api/app/controllers/application_controller.rb | 66 +-
.../v1/api_client_authorizations_controller.rb | 4 +-
.../controllers/arvados/v1/groups_controller.rb | 16 +
.../arvados/v1/keep_disks_controller.rb | 32 +-
.../app/controllers/arvados/v1/nodes_controller.rb | 16 +-
.../controllers/arvados/v1/schema_controller.rb | 7 +-
.../app/controllers/arvados/v1/users_controller.rb | 2 +-
.../api/app/controllers/database_controller.rb | 4 +-
.../app/controllers/user_sessions_controller.rb | 3 +-
.../api/app/models/api_client_authorization.rb | 8 +-
services/api/app/models/arvados_model.rb | 210 ++++--
services/api/app/models/collection.rb | 145 ++--
services/api/app/models/container.rb | 98 ++-
services/api/app/models/container_request.rb | 234 ++-----
services/api/app/models/job.rb | 13 +-
services/api/app/models/link.rb | 5 -
services/api/app/models/log.rb | 6 +-
services/api/app/models/node.rb | 20 +-
services/api/app/models/user.rb | 8 +-
services/api/app/models/virtual_machine.rb | 6 +-
services/api/config/application.default.yml | 55 +-
services/api/config/application.rb | 29 +-
.../api/config/environments/development.rb.example | 3 -
.../api/config/environments/production.rb.example | 2 +-
services/api/config/environments/test.rb.example | 5 +-
services/api/config/initializers/eventbus.rb | 38 +-
services/api/config/initializers/load_config.rb | 1 +
services/api/config/initializers/lograge.rb | 4 +-
.../api/config/initializers/noop_deep_munge.rb | 1 +
.../config/initializers/permit_all_parameters.rb | 1 +
services/api/config/initializers/time_format.rb | 2 +
services/api/config/routes.rb | 28 +-
.../20170301225558_no_downgrade_after_json.rb | 9 +
...0170319063406_serialized_columns_accept_null.rb | 5 +
..._add_portable_data_hash_index_to_collections.rb | 5 +
...0012505_add_output_ttl_to_container_requests.rb | 5 +
...1_add_created_by_job_task_index_to_job_tasks.rb | 5 +
...0170419173712_add_object_owner_index_to_logs.rb | 5 +
...esting_container_index_to_container_requests.rb | 5 +
services/api/db/structure.sql | 182 +++--
services/api/lib/audit_logs.rb | 65 ++
services/api/lib/can_be_an_owner.rb | 2 +-
services/api/lib/create_superuser_token.rb | 17 +-
services/api/lib/crunch_dispatch.rb | 18 +-
services/api/lib/eventbus.rb | 357 ----------
services/api/lib/has_uuid.rb | 14 +-
services/api/lib/load_param.rb | 10 +-
services/api/lib/safe_json.rb | 8 +
services/api/lib/serializers.rb | 61 ++
.../api/lib/tasks/delete_old_container_logs.rake | 2 +-
services/api/lib/tasks/delete_old_job_logs.rake | 2 +-
services/api/lib/whitelist_update.rb | 15 +-
services/api/test/fixtures/collections.yml | 16 +-
services/api/test/fixtures/logs.yml | 4 +
.../arvados/v1/collections_controller_test.rb | 6 +-
.../api/test/functional/arvados/v1/filters_test.rb | 52 ++
.../functional/arvados/v1/nodes_controller_test.rb | 10 +-
.../functional/arvados/v1/users_controller_test.rb | 25 +-
.../arvados/v1/virtual_machines_controller_test.rb | 4 +-
.../test/functional/database_controller_test.rb | 2 +-
.../api_client_authorizations_scopes_test.rb | 6 +-
.../integration/collections_performance_test.rb | 5 +-
.../api/test/integration/crunch_dispatch_test.rb | 2 +-
.../api/test/integration/database_reset_test.rb | 2 -
services/api/test/integration/errors_test.rb | 2 +-
services/api/test/integration/pipeline_test.rb | 2 +-
.../api/test/integration/reader_tokens_test.rb | 2 +-
services/api/test/integration/websocket_test.rb | 742 ---------------------
services/api/test/test_helper.rb | 26 +-
services/api/test/unit/arvados_model_test.rb | 76 ++-
services/api/test/unit/collection_test.rb | 23 +-
services/api/test/unit/container_request_test.rb | 235 +++++--
services/api/test/unit/container_test.rb | 47 +-
.../api/test/unit/create_superuser_token_test.rb | 1 +
services/api/test/unit/crunch_dispatch_test.rb | 8 +-
services/api/test/unit/fail_jobs_test.rb | 8 +-
services/api/test/unit/job_test.rb | 52 +-
services/api/test/unit/log_test.rb | 78 +++
services/api/test/unit/node_test.rb | 12 +
services/api/test/unit/seralizer_test.rb | 22 +
services/api/test/unit/user_test.rb | 12 +-
services/api/test/unit/workflow_test.rb | 8 +-
services/arv-git-httpd/arvados-git-httpd.service | 5 +
.../crunch-dispatch-slurm.service | 5 +
services/crunch-run/crunchrun.go | 471 ++++++++++---
services/crunch-run/crunchrun_test.go | 406 ++++++++---
services/crunch-run/logging.go | 38 +-
.../dockercleaner/arvados-docker-cleaner.service | 4 +
services/fuse/arvados_fuse/command.py | 46 +-
services/fuse/arvados_fuse/unmount.py | 108 +++
services/fuse/tests/test_crunchstat.py | 13 +
services/fuse/tests/test_mount.py | 17 +-
services/fuse/tests/test_mount_type.py | 23 +
services/fuse/tests/test_tmp_collection.py | 13 +
services/fuse/tests/test_unmount.py | 87 +++
services/keep-balance/keep-balance.service | 4 +
services/keep-web/handler.go | 26 +-
services/keep-web/handler_test.go | 60 ++
services/keep-web/keep-web.service | 5 +
services/keepproxy/keepproxy.go | 118 ++--
services/keepproxy/keepproxy.service | 5 +
services/keepproxy/keepproxy_test.go | 59 +-
services/keepproxy/proxy_client.go | 19 +
services/keepstore/keepstore.service | 5 +
.../arvnodeman/computenode/dispatch/__init__.py | 14 +-
.../arvnodeman/computenode/dispatch/slurm.py | 2 +-
.../arvnodeman/computenode/driver/__init__.py | 17 +
.../arvnodeman/computenode/driver/gce.py | 12 +-
services/nodemanager/arvnodeman/config.py | 5 +-
services/nodemanager/arvnodeman/daemon.py | 67 +-
services/nodemanager/arvnodeman/jobqueue.py | 8 +-
services/nodemanager/arvnodeman/launcher.py | 6 +-
services/nodemanager/arvnodeman/status.py | 65 ++
services/nodemanager/doc/azure.example.cfg | 16 +
services/nodemanager/doc/ec2.example.cfg | 16 +
services/nodemanager/doc/gce.example.cfg | 16 +
services/nodemanager/doc/local.example.cfg | 4 +
services/nodemanager/setup.py | 22 +-
.../tests/test_computenode_driver_gce.py | 13 +-
services/nodemanager/tests/test_config.py | 4 +
services/nodemanager/tests/test_daemon.py | 29 +-
services/nodemanager/tests/test_failure.py | 2 +-
services/nodemanager/tests/test_jobqueue.py | 16 +
services/nodemanager/tests/test_status.py | 55 ++
services/ws/arvados-ws.service | 5 +
services/ws/event_source.go | 38 +-
services/ws/event_source_test.go | 108 +++
services/ws/event_test.go | 21 +
services/{keepstore => ws}/gocheck_test.go | 3 +-
services/ws/main.go | 32 +-
services/ws/permission.go | 28 +-
services/ws/permission_test.go | 71 ++
services/ws/server.go | 71 ++
services/ws/server_test.go | 61 ++
services/ws/session_v0_test.go | 238 +++++++
tools/arvbox/bin/arvbox | 78 ++-
.../arvbox/docker/service/websockets/run-service | 39 +-
tools/keep-exercise/keep-exercise.go | 3 +-
319 files changed, 8910 insertions(+), 3720 deletions(-)
create mode 100644 apps/workbench/app/assets/javascripts/edit_collection.js
create mode 100644 apps/workbench/app/views/collections/_extra_tab_line_buttons.html.erb
copy apps/workbench/app/views/{jobs => container_requests}/_show_provenance.html.erb (52%)
create mode 100644 apps/workbench/app/views/workflows/_show_recent.html.erb
delete mode 100644 cmd/arvados-admin/.gitignore
delete mode 100644 cmd/arvados-admin/main.go
delete mode 100644 cmd/arvados-admin/setup_docker_compose_test.go
create mode 100644 doc/_includes/_compute_ping_rb.liquid
copy doc/install/{install-crunch-dispatch.html.textile.liquid => crunch2-slurm/install-slurm.html.textile.liquid} (53%)
create mode 100644 doc/install/install-compute-ping.html.textile.liquid
create mode 100644 doc/install/install-nodemanager.html.textile.liquid
create mode 100644 doc/install/migrate-docker19.html.textile.liquid
create mode 100644 docker/migrate-docker19/Dockerfile
create mode 100755 docker/migrate-docker19/build.sh
copy tools/arvbox/lib/arvbox/docker/service/docker/run => docker/migrate-docker19/dnd.sh (90%)
create mode 100755 docker/migrate-docker19/migrate.sh
rename {cmd => lib/cmd}/dispatch.go (100%)
create mode 100644 lib/configure/configure.go
create mode 100755 sdk/cli/test/binstub_arv-mount/arv-mount
rename sdk/cli/test/binstub_clean_fail/{mount => arv-mount} (100%)
create mode 100644 sdk/cwl/tests/cat.cwl
create mode 100644 sdk/cwl/tests/dir-job2.yml
copy sdk/cwl/tests/{keep-dir-test-input.cwl => keep-dir-test-input2.cwl} (77%)
copy sdk/cwl/tests/{keep-dir-test-input.cwl => keep-dir-test-input3.cwl} (76%)
create mode 100644 sdk/cwl/tests/listing-job.yml
create mode 100644 sdk/cwl/tests/octo.yml
rename services/api/log/.gitkeep => sdk/cwl/tests/octothorpe/item #1.txt (100%)
create mode 100644 sdk/cwl/tests/test_fsaccess.py
copy {services/api/vendor/plugins => sdk/cwl/tests/tmp1/tmp2/tmp3}/.gitkeep (100%)
create mode 100644 sdk/cwl/tests/wf/listing_deep.cwl
create mode 100644 sdk/cwl/tests/wf/listing_none.cwl
create mode 100644 sdk/cwl/tests/wf/listing_shallow.cwl
create mode 100644 sdk/go/arvados/workflow.go
create mode 100644 sdk/python/arvados/cache.py
create mode 100755 sdk/python/arvados/commands/get.py
create mode 100644 sdk/python/arvados/commands/migrate19.py
create mode 100644 sdk/python/tests/test_arv_get.py
create mode 100644 sdk/python/tests/test_cache.py
rename {lib => server}/agent/agent.go (90%)
create mode 100644 server/arvados-server/.gitignore
create mode 100644 server/arvados-server/docker_compose_test.go
create mode 100644 server/arvados-server/main.go
rename cmd/arvados-admin/setup_debian8_test.go => server/arvados-server/setup_test.go (73%)
rename {cmd/arvados-admin => server/arvados-server}/test-docker-compose/agent.yml (100%)
rename {cmd/arvados-admin => server/arvados-server}/test-docker-compose/docker-compose.yml (60%)
rename {cmd/arvados-admin => server/arvados-server}/test-docker-compose/encrypt-key.txt (100%)
rename {cmd/arvados-admin => server/arvados-server}/test-docker-compose/master-token.txt (100%)
rename {cmd/arvados-admin/test-debian8 => server/arvados-server/test-setup}/Dockerfile (85%)
create mode 100644 server/setup/arvados_services.go
create mode 100644 server/setup/cert.go
rename {lib => server}/setup/check.go (100%)
rename {lib => server}/setup/command.go (100%)
create mode 100644 server/setup/configure.go
rename {lib => server}/setup/consul.go (67%)
create mode 100644 server/setup/curoverse_package.go
rename {lib => server}/setup/daemon.go (97%)
rename {lib => server}/setup/download.go (100%)
rename {lib => server}/setup/os_package.go (100%)
rename {lib => server}/setup/runit.go (100%)
rename {lib => server}/setup/setup.go (68%)
rename {lib => server}/setup/systemd.go (100%)
create mode 100644 server/setup/tmpl_nginx_api.go
rename {lib => server}/setup/vault.go (94%)
rename {lib => server}/setup/write_file.go (100%)
create mode 100644 services/api/config/initializers/permit_all_parameters.rb
create mode 100644 services/api/db/migrate/20170301225558_no_downgrade_after_json.rb
create mode 100644 services/api/db/migrate/20170319063406_serialized_columns_accept_null.rb
create mode 100644 services/api/db/migrate/20170328215436_add_portable_data_hash_index_to_collections.rb
create mode 100644 services/api/db/migrate/20170330012505_add_output_ttl_to_container_requests.rb
create mode 100644 services/api/db/migrate/20170419173031_add_created_by_job_task_index_to_job_tasks.rb
create mode 100644 services/api/db/migrate/20170419173712_add_object_owner_index_to_logs.rb
create mode 100644 services/api/db/migrate/20170419175801_add_requesting_container_index_to_container_requests.rb
create mode 100644 services/api/lib/audit_logs.rb
delete mode 100644 services/api/lib/eventbus.rb
create mode 100644 services/api/lib/safe_json.rb
create mode 100644 services/api/lib/serializers.rb
delete mode 100644 services/api/test/integration/websocket_test.rb
create mode 100644 services/api/test/unit/seralizer_test.rb
create mode 100644 services/fuse/arvados_fuse/unmount.py
create mode 100644 services/fuse/tests/test_crunchstat.py
create mode 100644 services/fuse/tests/test_mount_type.py
create mode 100644 services/fuse/tests/test_unmount.py
create mode 100644 services/keepproxy/proxy_client.go
create mode 100644 services/nodemanager/arvnodeman/status.py
create mode 100644 services/nodemanager/tests/test_status.py
create mode 100644 services/ws/event_source_test.go
create mode 100644 services/ws/event_test.go
copy services/{keepstore => ws}/gocheck_test.go (76%)
create mode 100644 services/ws/permission_test.go
create mode 100644 services/ws/server.go
create mode 100644 services/ws/server_test.go
create mode 100644 services/ws/session_v0_test.go
discards e96966556520e3d7cd27ad253418656892355c0d (commit)
discards c78289e5956a55c7540c2a3f6a543f16b1eec7c2 (commit)
via 059a62b51d90f82e4286835d26d8bf523a54132b (commit)
via 87f40ab7ba0a3f0fc1f3648c917ff929e6e633b8 (commit)
via 1522e9dc7cd4ccf9a636a8d53091f05560accfb2 (commit)
via ff310f43338a2443f9b11b7a55e619dc1961d234 (commit)
via 55466cec28927431c15e61078b9e56225ce77c72 (commit)
via 957ec5ff80456706aa3bd709669e4a17251f6791 (commit)
via fb08faf4b134a09eee928b596382cf17c75a8c89 (commit)
via a328dd7d4d396d1c2f67d3a74989f0194b04e714 (commit)
via 887ca969a3fa97f2181a089ac22fac1ff1e3ed25 (commit)
via 1883fbbdc269fa0bdf3099984160e02421bc94b1 (commit)
via e56ae6aad06c37d5512537047871d7363dd97620 (commit)
via e39a7d5704932cbec606e85cdca50aa38a1ed053 (commit)
via 88a25d414025c64231f977a9383fd6a69cf6246a (commit)
via 72900c01e197d602e79fda8d306b17fd1e32a3ea (commit)
via 6a7edde0c5b906c58a7e739f2d0c612c67f63dc5 (commit)
via 41a7f3914a6ced0fd374bd903470fb4fc91ea5e4 (commit)
via f5f5de0ae41e12738a380c422417d5a5e5af7f09 (commit)
via e8317521741c3814e824e209f75edf23636e32ff (commit)
via 318c49002aea966128a9d37ab29e601a104d79bb (commit)
via b075d1be1377760f5d8497a29f63c8e416cd5378 (commit)
via 8c5f2973a5c5f042d1d12aef1c470b37519fd416 (commit)
via edfc619e6189c5407d16798c75aaace08a13536d (commit)
via 90209af8fa35bc99c9821db0c815404d1234ef31 (commit)
via 88c241d7c4fbfadb951f370bf2706db687adad75 (commit)
via 137ebf94ff14837c9df773533ea86e821469bda9 (commit)
via 260e85a9d9cf2c20313bcf2edb63da57bdd3a69f (commit)
via 30146198f24c70941d95af714e036ff3c451626c (commit)
via 95e2bdda5afc3ffc6afb2f08ea6d7cba8f8d62f1 (commit)
via 629557aa041a80f0704b02e7c679b2f01d9c0be2 (commit)
via f2f8340b18430738a9527f05e707dd8f03508cc0 (commit)
via ad7294edfcc59c3e67548328a88c9e689c3ae2cf (commit)
via 3ef580c47029ff0fbf959b044f29c183f41cb609 (commit)
via 4ccbea9ef440a7e4252b0df5e710dcb767831c60 (commit)
via c043e133b2646037ed630d571e91dbf77344f855 (commit)
via 93c92875aaebe5b06f8dbfe2822b59a772895c08 (commit)
via bf5d77baad2071af6eea514c76b4892cec4974a0 (commit)
via 04bd6b08b9ac13d29ac05c9281850d430d71066d (commit)
via 840b855ff0317e66f4176ae0f23e9785f72267b4 (commit)
via 1220e2184449ccab288fa41de4749fb029cd317b (commit)
via 17b80c32a5b177ee8c5f32b81dd0889f3399eee8 (commit)
via 9905d124877e5695053cce388d3680c667815de5 (commit)
via 35c2572761bb060aa1c12f417f97aa9e1ccbe7eb (commit)
via a93d95d85ea15c7afd70657abf60635c29043c89 (commit)
via f4661a02245a35f8d223693a5aecaae87083fb16 (commit)
via 52c6f13db207030bdbe063665c0dd524007db828 (commit)
via 0ecea550fde014578e71004360b700cdfeae4909 (commit)
via 7116da151dc8bfd5ac1a9b016b2ed6e4c35572f7 (commit)
via bef5d901f00648e703bb6a3ad58fa481a610ffd7 (commit)
via b04638275cff9b393e1bc04136d44f361b999cf8 (commit)
via c39ba5193005a4e9f619901f8348f11fada88df0 (commit)
via 2333472a4f517a227278f028bbbc4e72687c0e71 (commit)
via 5180238a10bd15302a1c15b9a428f2fdeeabdf4e (commit)
via bfc9660a8b2467893baf131b20e83e76c41ae438 (commit)
via aed7702a67426dfd9d24b512c90df8e909162179 (commit)
via 9aa83ad7b4de05dd2818885ed34111d4dcf322ea (commit)
via 3c34e713aa343d56c7cea00a9c998b06dbf411d6 (commit)
via 65e339856daf4b5c3a4a810cd3a5f1a8e386dc8c (commit)
via 151df8c3b177e4971bfbdf68c87d89599dbe0812 (commit)
via e7284afa8ccb95994dcd2009015cafc6180e7187 (commit)
via 82c40aa7d30cd8e68e2a1bdc0bd8bf03cdfea029 (commit)
via 38a4b3c43a8a6cff5a00624436b8eaa5cbfbc76b (commit)
via f79536fda9dc40f480383caa69a35663702b2ba4 (commit)
via c14ae0edcb3c386e50f46218184e8dabcbc20a37 (commit)
via 04951581a941697d68cdaf9af6661c3c412f1bce (commit)
via de99c0b2effdd43d3843f15475cee84dbde8add8 (commit)
via e3ac17f8a8aa439e21a8bf56a571f91a671313f7 (commit)
via 244c47436f294638271eef637997fd00f7ca49f5 (commit)
via 67ba19113789346005aa61d4234bc33c8677a85c (commit)
via 9609f9a5a4776671f571f765a179506d26df56da (commit)
via 03188ad6eb14ee3dcd6bdf74198624c9358936c5 (commit)
via 692a66affa483483d67931a6b095b361bfd06d24 (commit)
via 243701b66914b69c9f9a94364e84713c8fcbc1da (commit)
via ea40bcae7a5d247ba8667c8c866339c2a8424464 (commit)
via cf311e8e16ba74467c77b5353afedc29b40a6a41 (commit)
via 20364bc1aed2dcad71b006f4314ba0720d20ae05 (commit)
via 72a377c59d972dd64de6e500c140738ff4b3dea6 (commit)
via fc2eaa20275146369e451da6cf14f4461c68117c (commit)
via bf55ee80e71c6503292a44fb377927f2ed908f9b (commit)
via 9cab6a09cca4153104694f0dd4644c5aa5f54b22 (commit)
via cbcb0fc8c3ebc85bf81ba9d50795d62db75efa6c (commit)
via e507e67ee50852fc44011127eb42f535fe2ae493 (commit)
via d64ed33e94700f8204ec8089c7b235cff918f9f7 (commit)
via 88c26c6b2dd8752ec1ff8196f4af11369ea6adbb (commit)
via 91f1e7009305109db0bfb6405adbd11357745bfc (commit)
via 2001423a6eb7937a689414f3fa62be5b124812c1 (commit)
via 3a88a5d8753593be89373c5b124fc5a8398457a0 (commit)
via defb299deab3be85644a7880cba492a73c2e7e62 (commit)
via 5152e0bf159151eaf04d31b788d57bebf7ab089b (commit)
via a3488ff35d219b943f3f52c07914fddf2009a140 (commit)
via 574dc168c559dd680d26be1306c4a3d8b936c6e8 (commit)
via da32ae2a73012ce55cb89b2de9a4716b2800eee1 (commit)
via 2f06f0e4d5b9ef371463c65dd5cae19f5b385a17 (commit)
via 29d77300205e485be6595d9cd9276c246f3f89b7 (commit)
via af78d389b0ad37858108b69fe5100443dc88eb4a (commit)
via 0035033f6bf6db955b116e2e0cc052bc5c79d80e (commit)
via 49a841a5179307f0c8d84f647a71f44fb2b4b26d (commit)
via bafff6941293d4cc12cda4209f1d7a2b10274ea3 (commit)
via cb47df6cc327a59efaa16170f840c2745162bc86 (commit)
via a734789218122d8ab0d8f766bac4d69c04db91bf (commit)
via 00573cf7d28472bf926e8f610a256cd991879c8b (commit)
via 4431b9c71fc08955a89d1af70de3a8d5174c6e9f (commit)
via f61c7d9445c216c2364734fb1da2bea00cfb581d (commit)
via 9ea73e2a66dcb1311732d43ea052412546c625fe (commit)
via 224098499104939fccdb07b39407937c61983687 (commit)
via d3a82af33386c99c0fd3d6471df7e6696560089c (commit)
via f70c457c73f1bff6314f8c3eb4ad7be0c44a5f1a (commit)
via 1b290e512496287e389424f3950f660f83c1c59b (commit)
via cb4f8b337c56dd3e7a648dda86031ceba65ee6c4 (commit)
via d72f1d79c0a53056a7cecad6c65fd57a183059b0 (commit)
via c03283d4da26ac9a6551dd00b25882b14c258da3 (commit)
via e1bc430748edced07f43f6c8efd73bbf2d828ca0 (commit)
via 76e3d80bcc1548daba7bca97711684e5d68c1624 (commit)
via 777e716728a7da63ece00df7e5bb8be7f9a2a1a3 (commit)
via a6be53f6913862b3884c57e9e93a891f3cfec471 (commit)
via 95ef2a6f4145d8c6058738b6de0bce098e3423d6 (commit)
via 8be16cfc7e163cc96995be891e53050febfb1fca (commit)
via 828161a7527c535e5c657cd17b79cd562475fe82 (commit)
via 2c094e28cc4f19df4f6d0bc81355e7fc19e8c493 (commit)
via a779382603d2da2ec38ceb8a21262cc4f151f077 (commit)
via 26eb8f4cba5dd20ae49bf509a9a772ee4fe8b396 (commit)
via de083a9fec0ca08afda5a9369c6cd32dbdcd0965 (commit)
via f5d09a4904e609b5df20edd0194a9f1ade40c28a (commit)
via be2a34c57eab7cc184c08ec1059554cb97911276 (commit)
via 533bf8f1120c0f3fd74a31dfda990cc832b2aa51 (commit)
via 96b6e26749f3a7076b585758d44244777cc628c6 (commit)
via f08a738f1565b2dabde28dc9e8d1bad9622d5529 (commit)
via 466e0e2623bb85870943f48fe1ab3016dc32d652 (commit)
via c1ea9a2fdccc5e24554f8cf28296cbc0764c8bbc (commit)
via f9a1468065776ee71eb43c45e6813bfae69fe0e0 (commit)
via 0d5be4fa36006459e1579f087b695904e4f32ee3 (commit)
via 2f46fb5769f41ac9cddf8c46bd0d2ab094375e82 (commit)
via 77d9c05d89dabc9e9e9a15f46cd12c8ad61ed64e (commit)
via 909313b20ed5055d62113f0eea123f362869c3f4 (commit)
via 4f68551a87ff2cb88c23a2942abe2676a33f7cbb (commit)
via e7876a3ac520b128be7836e30172079ab2af5e45 (commit)
via f49bc2790a18de14e22e69fb39f93805488fdbb3 (commit)
via ab9a73d2c0b567d3c05d1d4d8463633a69eafda2 (commit)
via 3f5c2b95de8483e277a472846ad7e5b2ccb1f79a (commit)
via 86a6e4fe9347570090d1d1471f98675c3fb758f4 (commit)
via 157847615412907e87d24fb1767470d0157a4c30 (commit)
via 1b226fee3268f50ef670289fc5931a00866d69cd (commit)
via 4405570376295039b4c00577535a394eb011f8ad (commit)
via 2f52a6e7d9945f51d33b047466c4d927d494bb32 (commit)
via 0654fa160f872fe20ea4ada42a655f9d154c0833 (commit)
via 330f544dd257a43640eefc64b825b868f6e5be21 (commit)
via 351f06f68e8b079377bea195c67fed171b1e4b73 (commit)
via 75184884ed798b474e8b9e254045dc0f4354379e (commit)
via 2ebd44960d1e7a0431d6ad612298012627c5019c (commit)
via a869fa401696bc481380be239850ccf3edd808f6 (commit)
via 9dae3e6dde2993bc44e90539141b442c899cf114 (commit)
via 1c1c11c2c2d6cfd1d379cdbb166498514768be4e (commit)
via 1d0d28c791e88f817b1c01560ee8efd70bcab41e (commit)
via 3ceb42c882b32fb9e4ef79679576254f98cdfb3d (commit)
via e3c48eaab3bbf538a03e575aab09cef59ee69f18 (commit)
via ed46350a4b4cd947d126b5e1e9a0514aa0b93532 (commit)
via 921d4321201be7542f9198202f75ba39c3f83d3f (commit)
via 1affdcd3cd34424a817ae350fd9ca236927fd538 (commit)
via 38fcd08dda022d0167840fbb65222fe99b75fcf5 (commit)
via 33ec0939cd5853d1c14a621c551ac2705efd1cd7 (commit)
via b594678083d6cd7efe425bb4be63a444f22ce153 (commit)
via 7b31dd40b31bdbf7473b50fd407cd6f636657c69 (commit)
via 8fd18fc4a32797fc3c6255099fc253d7aede12b5 (commit)
via ae69864e07d416d10879e00da416918ac021893f (commit)
via 7ce46899b5ed250aa909fa240b6be3e01637fb79 (commit)
via b50a3bcb38cf9e79416d8cc9b0d8b66249b3d473 (commit)
via c3ae1e2f54d4199a9521bf3d4d515bcbb0711989 (commit)
via 6da9f3666bc0ddee2d0be079cc30ba8b82804706 (commit)
via dfd3260e8b32ac4b9640e3e33bf8cf1e581bd917 (commit)
via 42e6998c32f8d5553133e4b0b3ea02cd0c6f5554 (commit)
via 4bb024ae6903552c29613c851312f934dc6174b9 (commit)
via a03ce4056e503710caa1e95d315b92fb74c96abf (commit)
via 77f5a84ccc2b14438286ed05c6af183b8d8be605 (commit)
via 4a35e06b098bdd44a24fcaf77921aea5f371c84b (commit)
via 313415e33ca374898a371b9f22fc6546793f4688 (commit)
via 2c0c6e6ba25ec56bab8c224865a7979af577adaa (commit)
via 07c92074fe2b493dc8cd0abdad154e5b36d4adfc (commit)
via 1654f776b55bbb861f72c0dd3118ad1beec5db31 (commit)
via 988e9052575bc93db2909f3b9ef576f1043eddcb (commit)
via 3cc77494ac02e0f64a814cd4a898662fb7b329af (commit)
via 17f22a2b220c38ebae5247d09f8c96ceec151957 (commit)
via ff3bb22d4b2bff5666907a6eeb6cd68cd3cbe22b (commit)
via b651984ff68c6f8add9b99427b205a2cb7c87462 (commit)
via 55c34fb97edfba5a014eb43b965130cf11dbda8a (commit)
via 28e59edcec4af09f78be965fa3abfaa9ee3f8dff (commit)
via 4af850d6898dea0c5f460f6acbc52f2e361cbf1d (commit)
via 736a629e16c388a5afecc97268bd7eadfd7ce3c2 (commit)
via 5ee2b9600ced7db8fefe141c837a894f33a1d129 (commit)
via c820bfc91be7635739bad0857ba3a385d1334b6a (commit)
via b9236fbe81426446e1b541a45e219bbe513fe8d0 (commit)
via fb1c8e81a200c11b1130f3a9af586f1bbf8c19b3 (commit)
via b351a877ff2d708acc5fe577d5ed5cc9b0469dde (commit)
via 0b04efefcc49b05df10a202cff5e423bbb587923 (commit)
via 65121f8db54a1ed15207d050e1f48c5fc26d646b (commit)
via 1a4a2f3219906220c0b4d7fd9b90325fa529408a (commit)
via 4437774e863465c0daa41dfd9716174e18d93122 (commit)
via a12ed889f9d0106ea26d0e2d6ff1f74e9ab14aac (commit)
via c507b0b072ad62c0087d059aedeaae8bae9b715f (commit)
via 38141f7261a7a2fa29f9cf3281cc46c1d845c1c3 (commit)
via acb0bd431ced4814b37f703ca63f2b39ad29c5df (commit)
via 0568c2d42703a7b839f2661968c05a23753f67c3 (commit)
via d6703f161c75a780ff645dc1ec980fca8a3e315b (commit)
via bebac87e773d73788de9273d65ca92db6878b2e7 (commit)
via e8e9262a0f5e1e5908d338ac1655a2cdfaecf23a (commit)
via 6fe136c2c7419dfb38a9af42898682701646b518 (commit)
via f34f20a9ac4b7ade7eeb05157a3b190d8a98c37e (commit)
via 154ae0d4b13329bae1033ab99095c00d0b0f66e2 (commit)
via ff8d14acd42952a21f5428e96d86e4a54c41be9a (commit)
via 433c48edb1523809bb8d43e4fc40ebe1a177e103 (commit)
via ae7f5a9c869927336dc81cf0552b955457a09647 (commit)
via 6828728001af20d8b75d841ead727c47d6ee2c96 (commit)
via 37313363a84fc41dcb87a8c9aa8b8502aaac256c (commit)
via de1e1bf2e6cd455135f754878966711db4dae9ec (commit)
via d040869ca4926c0eb39e072bdabf139bc1f25dd3 (commit)
via fbc867e0b02a0482d00000d76c5d0d343b7f252e (commit)
via c6a8839b1888d2eeb302ddfc675772428b8895a9 (commit)
via 78ca1460d58172f4555409298968583cd2ee70a1 (commit)
via 0708d4a0b6db9426b9bb5addc1c592d526bd4ecd (commit)
via 25ab6bebfd55db837aa049e5c0fdb2ce28f98f30 (commit)
via 201ddbd84144a10bbcbc72a3525bb0c4e743570d (commit)
via 692ef5fd300fef4ef1b724016c1600dbcfc8a070 (commit)
via d7d00f5140b7622fdc55a4058be73b89d587b7b2 (commit)
via 7bd9af41d106590856e4d8c317502d1f4f56aefd (commit)
via 5cd99e52e342db19c1a77369a5a8c027ee04feaf (commit)
via 33b9f9bd117931bae54f45566fb77e654dcbe263 (commit)
via 6b0632d7706cbb344331bf5d291cafd541070cbb (commit)
via 820d3244a25aa8b4658ab79cd8368492aeddc739 (commit)
via acefccc4d506ed4bd3f51d3d88bc3a826b28be76 (commit)
via b3d286cda65b90e4dd0aaef88f085f45ea855ed5 (commit)
via 2b27132d13fd72f29dbab2297f0d2dc1c110eed1 (commit)
via 46fac76c9e6e325afcce3e17d51a7c7eb7340e11 (commit)
via 3306ff5835f05b9d1e63a8254ec9d5e6ab41f968 (commit)
via 32430fd402dc70b32c945c72b0bb73abbe00a913 (commit)
via f92654c53d54dac198078d42d810b65383179073 (commit)
via 01da808f446e944873c611b6d229e01980c80f9c (commit)
via fe0751fd604792c7a0884e3533d8acb03b6038d9 (commit)
via 126a8a239853e46cef3d4b7e5acf7620c0bd1f36 (commit)
via 07e060db9abde587a4c56ab47b9c86d3c5a0ba7d (commit)
via 11e4219911b6a3ff8696c7a0401ce4dcaac64d5f (commit)
via 71f0b2ccf5f82c5ff86e51c06060ef4a9234e6d3 (commit)
via fdc7164e11eb019122b6deb9054decb9fe0be0ce (commit)
via 4b8e618c36fae9231601b9012fc18c5c2ee43a90 (commit)
via 189495ad597e9b5b167bd47a1ef2b25393e39692 (commit)
via e1e05845b74ce70712e414830f992ce57d7a8453 (commit)
via 78ff2a600b29f05f522f8e8818967dac88394fd6 (commit)
via 7fd4aa96f997a133d31b3df88a8d2f4820c5b881 (commit)
via f14965fac774465c0179f5e318c9df3df9b6a05d (commit)
via a774873482ade7b9dd0f9a607c97b848b77fb6f2 (commit)
via 2b2c23bf8e997735dbf6c493b168ee3a3ff52be5 (commit)
via dfa41e508c0185d8b933b5d1af0aa5f473a10f3c (commit)
via fb7bb4c8f17a49abab40e42b7a0101cac7478d60 (commit)
via 8b4d5991f9d5691b9fa2898d6f60eef8dbfdf987 (commit)
via 823ef13277f4c5fe6711dc320bf9cd2f76492c2e (commit)
via 8cd68a569df236ff8e150a556cd8cd69169b113f (commit)
via 387376e59b6624703117b2ffc296211712aaf970 (commit)
via c33eb3191d36b7e39023db0c0f1790a1bad2c4f0 (commit)
via 922e79bea1cb6d4df7cf1db48c4b73ebac03b64e (commit)
via ca19a29fa8cf99f87c074a68db25fafde35ec917 (commit)
via 7e9156ae4a449a9a762561ef611d971d9bb763e1 (commit)
via 8d9b12f2a87ffd7183d3a36ca32ee1c7e701a0e2 (commit)
via d42ec212e992a83f8e7fc48b59fb3daf58a62787 (commit)
via c066a2e6d064a270638baea8f8b0d106f5903e0f (commit)
via c36272a5f83ba70980160c4cb205bdfb8a1c660b (commit)
via 045bace65c2395b6efe9f3d8c93bec74196f58e1 (commit)
via 7c6852e1b3675b3c1de7e9792373333cb752d40d (commit)
via dfd8c4bbd6f126b90d436e9d242cd30e15e70d2e (commit)
via de4df7f80c531ab16e59ea36671a8efa9e6ff33d (commit)
via 126dd750f48654cb3b1a4e53c5b7d337003e112f (commit)
via 30dbddd3b311653652fa731dbff950aba0712301 (commit)
via ab314b9ea3618c71556a6a5f6dd7c769beaf2737 (commit)
via 390af6a13f7c8974329aecc2f23fbfa81f8e298b (commit)
via 9090c60b28de593b8bb2ce606a9ab35b62b57608 (commit)
via 84ad215752fde4291070143411a945fa7a94241c (commit)
via c9a361f7fd3b1cf7f4959e9b0292d0f495d82771 (commit)
via 05d453ec38b10a022ea6db77867957e7115b9b35 (commit)
via 09dcf71e59907c2eaf4b94918c63da07193481a4 (commit)
via 099a8c62fcb0905855ddf243a3deddc7398c3c10 (commit)
via 13c47e13840caa688711a30a80a35637714e034a (commit)
via e47a4660df55a7f45bcd3df5d4c041e13f194ac7 (commit)
via b7a664f09052ac048e506bed9bb48b54bc2a9bd4 (commit)
via b3fe30840e96e7fa77de047fae2488d703a49d89 (commit)
via 2d0872f936df8c357bbbf9ec2aa8e35cccb2c5bd (commit)
via ce4970b9546b586c8caa8416ea13dab8c4866d59 (commit)
via d31988b6da2d779a8f3ba4ba3c40760f9729c59f (commit)
via 0dea965e36e7ac52a789e31b45fc70f1925c4190 (commit)
via fe446e10da189d3d3e0ea5f19061389cc2200a08 (commit)
via bbacca53ce2e9eabe3c8e02cee8d3650864bd3f1 (commit)
via 727c1e475afcb1a8fda1f9b689bb3e941ae93cec (commit)
via cebc9af013fbe65d83cb4a60813e3d1871f7ca3a (commit)
via 4e3263eaac83ede993110f1842c557c28be765e1 (commit)
via 86ec536f01179ecc1bca0f32a4f41ad307b23c7e (commit)
via 4afa501317cc04596377bcff8a7b2fccf7ab8d8d (commit)
via ae8aaa4c55762222c837fcce8e9ad6800ff8b128 (commit)
via b8000c3cb38b77c5c429e0fd591a43f5eeee64d1 (commit)
via 2e32ef1657b439c0398e66930c3d17437032fb1a (commit)
via 8ada36c931712304c4b2c70bdcbc316b1ad2c4e2 (commit)
via 4600343d1bff7ac4f7b9f08486541444c31af8b6 (commit)
via fd7767148061d21b77bd97a8856191d6c9bbc077 (commit)
via 6722b420effcab24dffd9b47fa277f8830bd4cca (commit)
via a8378b8deaa2bbf9d2c154d9d9bb072538c288cc (commit)
via 2aef6ca08d80c0fd25d74ddb9ab52cf535a33d3e (commit)
via 5aeebd0cdbabb1cfc815b21b26fb87622b05f6fe (commit)
via e8cc0d73309236d6efc243371969f83808e42d30 (commit)
via 1667f9860de21d29bbe32bb827db29eca62d9aeb (commit)
via c56743e301b49163a56482c13e49a01c9a0fd7dc (commit)
via ae970cb115251915c0a8e1052b23acdd2ab70fee (commit)
via a67faeeb159323d35d2a3229c7b5d014dc175767 (commit)
via 82ff0337a99b7aaed626a624633b8c068dc5e142 (commit)
via 950ae9635334cd1ca6a2738b185f6481cc3d771f (commit)
via 83203f5c739ee0b0199e76babccb60e832a0de8e (commit)
via 7772dca4096e64b1033fb9f42e604699ce07f782 (commit)
via 514cd364c3cb27b633c1368cd06d6a54927c98a8 (commit)
via 366780077def317818759e999263577d8a9f5064 (commit)
via e47fe8663303df51081a77646e061b11aa892df1 (commit)
via f0a34ecb9b41b7d4e35575803ba3dc283f369724 (commit)
via 8d2dd8003b6e865033e372b5db76fc2244378964 (commit)
via dc6c3fccb583ae98eee808addb526c45ebdbf2c6 (commit)
via bc8a4a8863f147e4c0b95d0aa3e2f3e549637ee4 (commit)
via 262d1e44ddaf3f014423a4acf96a3a6200279820 (commit)
via a54e88868ac259443e2cd8d5f6fddb4b8154acb9 (commit)
via 432e71aea50074b1674e96fb1a03cf512952ab75 (commit)
via 6b2005a2fa3e7c040f8db222010fa870f87336bf (commit)
via 5976c751048100e813edd638632927794df072f2 (commit)
via b50e323ec94e9c7355c6f1c5b93f488540d08ec3 (commit)
via 6498c7751cd0305a28494df45a70965ccc6c3737 (commit)
via 49510014c88646ef4320b137240966ba8f6d5108 (commit)
via 5689f1de6e1a263237303b73013dcebb4ad77e1f (commit)
via 659b49449d313cdb218a46ca36ac124674a4d00b (commit)
via 2fd606b328508babad9af6c0a30c159568b525c2 (commit)
via 2741b54c38ed1e32cc9f0129614a00d84f51bca8 (commit)
via 8b278cdd80f8969a954a2c789281f8f63195e894 (commit)
via 077878d94771c25c25edfe01a98a523898916d9e (commit)
via 05c97120decfeeb9ba2faa20561ee1f37c8293ba (commit)
via bbe8547e183a66fd551adffe59fbd4f5c146677c (commit)
via f8084a54742def1915c9f4be290f9076033af152 (commit)
via 37e995fb7423b2b353c599e2a1b00bda7c29ee6f (commit)
via 79e53c0eed77396cb37f60b48be0c60fe7e0ab89 (commit)
via b77893f2a8ae755f22615054f2c267d990995e1c (commit)
via e20dfe63dea30fc45bd4fa50aa9d6b5ab1040c99 (commit)
via f31475dfeb37c0e4d6b5244cba3bbd06e323b8e8 (commit)
via db7c2ba7523fbce1dc47ea1a715a738a28b3bb3b (commit)
via 433cd703220880784c8dab316501d1c74b09e37b (commit)
via 9c99316ba4a62ab15b383a8e3b2ec6f4d7165a3e (commit)
via 03589784d8bc566305e1ea3473a8b37941147517 (commit)
via fd42d69ffa558918ec40f9aeaceb2cbf93de1e8a (commit)
via 99ee47018fcb7cff2adc9184e2063eeba9d55798 (commit)
via 2accec1f7ca3e2dd1e7fe9ee28bb6a8a6cb74abc (commit)
via de283bd8dd383a4177bb714212cf7c59f38a23d8 (commit)
via b30e81ee46c196476a03bc244fbc4419573ba34e (commit)
via da8c9048bf4f3a36f5691aa52e56e2db672dff3a (commit)
via 47178c71032b476e34fd0c6b10065e1b96a568f1 (commit)
via bf03dd4f523463b896428527fa0685631e9ac649 (commit)
via 996b635700d7270229200a56d2c2b9f7c96a84fb (commit)
via b60a21fe3482e1f7ca1815e2a90e276a8c377636 (commit)
via 2c69d491fbbd1461bb5a6dd9c0f0dd493081b45e (commit)
via 9f34ff6f6a6ea1d384528a093bad1c72bd2cea89 (commit)
via 73dbf5bf94b162e5e9ed74cb60f17ee2c7018059 (commit)
via 386faadf691e444b71d6c96e7c00792d9a0ba2c7 (commit)
via 8513e042b0033599146546bd3a2ad903c67c9ff5 (commit)
via 1230d8a106c5c62edcbb9fcf6d1b94585e5596b2 (commit)
via 54837bcae94d30f37f19e4ee436c2bb96bd8f21a (commit)
via b1aa6c85c3db947f0963b1bddb2784c115f5c97d (commit)
via 98329b75276412e605d54b3a0f907a5cf204384f (commit)
via 91118e3af51c7fa655f14f2da99216f8ff0e11e0 (commit)
via bdaa9de9882fee122fd2274d92ea500113df8195 (commit)
via d363323bfea33aee9182e71fd93387b0c4f944a2 (commit)
via 449d780f0a470f67d1a28fe1459a8bab79562069 (commit)
via eabc13f27dfb178069546202bca772f893bac81c (commit)
via dee634b21e48e467b0d7b5ef1b2965c1df5e41d1 (commit)
via f074ef8181c2b93cbfcd870eb67c8c95cb0e442a (commit)
via 2ed5325b37efa7aa9d38a60c1d5c8b4980df8489 (commit)
via 55c719bff1b34d037506639fd4cf7f0a74f4c3cb (commit)
via 6058f336a4562b6d6780c4fcfc4d28b6b2a51948 (commit)
via 1d7577d08b6ca646fcca0e941ce614c37051264e (commit)
via 205b07766565f3ce7b80bcdfee88f83af451fb01 (commit)
via 0eb521827f6a64e567722527f36f0b4d130af504 (commit)
via 5fffad607e39e331f1051c35c5b70ecd5a30939a (commit)
via 355fe24bf5a4ac9e45372333e8bbc8e39b5b86a1 (commit)
via 25296def9590c8a29bdcf75c78a03444d39ca6b6 (commit)
via c04608e40b971b2fc342db8e5e44817b568a3a4c (commit)
via a13833894cda6bc1c872b3eb4215dec5c67aad62 (commit)
via 7eb2eff1864696bb51b2f4913499da5b62fb74ec (commit)
via 6ea807b2caf6c934f170b2e4d89c23c4a08ca69c (commit)
via c7515954731c6b7c0d8fb241ec4316a5e6d62d0c (commit)
via dbb0d22a96fa2de606430d78c05c254598f501df (commit)
via 918e16de43e993894dcaffbe0cafa0fc1d2f16b3 (commit)
via a72205728f94f5261b657766e01f5767dc15d4b5 (commit)
via e1e0bec5d9828fff1b9269322d415789675e6fab (commit)
via f4a7c5e6b1e6e30ad8a31a704642fcc360239e03 (commit)
via f63c160fd1cec8dddc673900f5cda824bed30d88 (commit)
via 605d11f27e73ce60794fa9858aeed8ed961261e8 (commit)
via fa8c5cdb36fa89af92087d6465b207d65ffc9618 (commit)
via 82697fea93b1c87cdee27d2b9a76c1b7ac07497e (commit)
via a15fc58f280171660afd2b9f1938f0a6bc5ede4a (commit)
via c7143dc92806d7b0c6f434e91744a04e5283284d (commit)
via 005595fb1a7da851a863118fba7e3d00026fb3a3 (commit)
via 273a233818ae39e843fab0276f9e381da6645d28 (commit)
via 533a50bbcee4ece451a65e87066563a5b33ef150 (commit)
via c97408a51dab3e968c76cf8c1d873fbe0f99a0dd (commit)
via 4812b5639cfaf724540786fcd331aaa227635c77 (commit)
via 101e3227b25c16874fa73660bfd7e338fbfe0da2 (commit)
via 9dae71315a83504493952f9039de958594e45f31 (commit)
via a1b0149879593df786807afbefb26d4687ebe161 (commit)
via b6423b5e5261f1ddaa88db2548e2190f82de21e8 (commit)
via cb0b666f86ce87d35667e8e23e3775b703a37841 (commit)
via a4a3227c634d8cfd54a23205be727e910032cbe9 (commit)
via 47c56297f949a1bebaa758cb8ce1684ffed22744 (commit)
via 2e5c44a64ea51f7ae61e286f2c88b057af1bc22f (commit)
via 660a6143ecf1e777f33bd84183ba9e821e1d7a8e (commit)
via f7d32ebcf2e0641cf92d079387dc325d65e35879 (commit)
via 07e4083ea451913b988d77e8e4c926da8ad844a4 (commit)
via dd08615e98e656ae07c6ca26eaa635f6ce8f01b7 (commit)
via 594e00f9311da95f73843f55b6e1c7c3ad55d8df (commit)
via 6fe6fb4a307dade78b4f64a3f0f06a9caa8a056d (commit)
via c7a44e530c2ecb036ac46d71a0306c6f64c439ee (commit)
via 2ab1b540a710fd454f33e9ba22db601e67f3d217 (commit)
via cad4856b84ff09f8d66faf16cc02ce68ef87995f (commit)
via 345dfd5a605c9171182cd8acb2918e899f64160b (commit)
via 766ddd6d958826049c2811f6d058480246e423a6 (commit)
via d7c84d69bb62d61bc671b2d5e0ad4ed42dbeb7c0 (commit)
via 2db0c3a44d8f12e3a566c796bdecaa1de150b155 (commit)
via a58e9ca25aaa0963545f256985eb75b2f840e80f (commit)
via f36162457a771824059fefa098a3ffb89c59263f (commit)
via b3fa9983ac0b7b38a5b3787af56a7bb1502ae3be (commit)
via a98594f82f1786b09d9d1e0f57a651d4eae3474a (commit)
via aea8596a74dabdc894fc1139c4d8dc195e6c86b2 (commit)
via ca812f58e63bd4673bb62aa8528e07d6020bfc9a (commit)
via c106221bf8c90fd80ca2c19a578fd7faec985229 (commit)
via 2ac112e2364b009166e0f67a3455fffb3cccc16c (commit)
This update added new revisions after undoing existing revisions. That is
to say, the old revision is not a strict subset of the new revision. This
situation occurs when you --force push a change and generate a repository
containing something like this:
* -- * -- B -- O -- O -- O (e96966556520e3d7cd27ad253418656892355c0d)
\
N -- N -- N (059a62b51d90f82e4286835d26d8bf523a54132b)
When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.
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 059a62b51d90f82e4286835d26d8bf523a54132b
Author: Tom Clegg <tom at curoverse.com>
Date: Fri Apr 28 17:04:20 2017 -0400
11183: In docker-compose test, wait for checks only on head node.
diff --git a/server/arvados-server/docker_compose_test.go b/server/arvados-server/docker_compose_test.go
index f80577d..089db46 100644
--- a/server/arvados-server/docker_compose_test.go
+++ b/server/arvados-server/docker_compose_test.go
@@ -1,26 +1,43 @@
package main
import (
+ "log"
"os"
"os/exec"
"testing"
)
func TestDockerCompose(t *testing.T) {
+ run := func(cmdline []string) error {
+ log.Printf("TestDockerCompose: %q", cmdline)
+ cmd := exec.Command(cmdline[0], cmdline[1:]...)
+ cmd.Stdout = os.Stderr
+ cmd.Stderr = os.Stderr
+ return cmd.Run()
+ }
for _, cmdline := range [][]string{
{"go", "build"},
{"docker-compose", "--file", "test-docker-compose/docker-compose.yml", "-p", "arvados_setup_test", "down", "-v"},
- {"docker-compose", "--file", "test-docker-compose/docker-compose.yml", "-p", "arvados_setup_test", "up"},
+ {"docker-compose", "--file", "test-docker-compose/docker-compose.yml", "-p", "arvados_setup_test", "up", "-d"},
+ {"docker-compose", "--file", "test-docker-compose/docker-compose.yml", "-p", "arvados_setup_test", "logs", "--timestamps", "--follow"},
{"docker", "wait", "arvadossetuptest_sys0_1"},
- {"docker", "wait", "arvadossetuptest_sys1_1"},
- {"docker", "wait", "arvadossetuptest_sys2_1"},
} {
- cmd := exec.Command(cmdline[0], cmdline[1:]...)
- cmd.Stdout = os.Stderr
- cmd.Stderr = os.Stderr
- err := cmd.Run()
+ if cmdline[len(cmdline)-1] == "--follow" {
+ go run(cmdline)
+ continue
+ }
+ err := run(cmdline)
if err != nil {
t.Fatal(err)
}
}
+ defer func() {
+ for _, cmdline := range [][]string{
+ {"docker", "stop", "arvadossetuptest_sys0_1"},
+ {"docker", "stop", "arvadossetuptest_sys1_1"},
+ {"docker", "stop", "arvadossetuptest_sys2_1"},
+ } {
+ run(cmdline)
+ }
+ }()
}
diff --git a/server/arvados-server/test-docker-compose/docker-compose.yml b/server/arvados-server/test-docker-compose/docker-compose.yml
index 73ba0f3..d18a954 100644
--- a/server/arvados-server/test-docker-compose/docker-compose.yml
+++ b/server/arvados-server/test-docker-compose/docker-compose.yml
@@ -12,6 +12,8 @@ services:
- ./master-token.txt:/var/lib/arvados/master-token.txt:ro
- vault:/var/lib/arvados/vault
command: ["bash", "-c", "runsvdir /etc/sv & arvados-server setup -init-vault=true -run-api -wait"]
+ ports:
+ - "18500"
sys1:
build: ../test-setup
cap_add:
@@ -23,7 +25,9 @@ services:
- ./encrypt-key.txt:/var/lib/arvados/encrypt-key.txt:ro
- ./master-token.txt:/var/lib/arvados/master-token.txt:ro
- vault:/var/lib/arvados/vault
- command: ["bash", "-c", "runsvdir /etc/sv & arvados-server setup -wait"]
+ command: ["bash", "-c", "runsvdir /etc/sv & arvados-server setup && wait"]
+ ports:
+ - "18500"
sys2:
build: ../test-setup
cap_add:
@@ -35,6 +39,8 @@ services:
- ./encrypt-key.txt:/var/lib/arvados/encrypt-key.txt:ro
- ./master-token.txt:/var/lib/arvados/master-token.txt:ro
- vault:/var/lib/arvados/vault
- command: ["bash", "-c", "runsvdir /etc/sv & arvados-server setup -wait"]
+ command: ["bash", "-c", "runsvdir /etc/sv & arvados-server setup && wait"]
+ ports:
+ - "18500"
volumes:
vault:
diff --git a/server/setup/setup.go b/server/setup/setup.go
index 8886946..a476268 100644
--- a/server/setup/setup.go
+++ b/server/setup/setup.go
@@ -68,10 +68,17 @@ func (s *Setup) Run() error {
return err
}
}
+ if s.Wait {
+ return s.wait()
+ } else {
+ return nil
+ }
+}
+func (s *Setup) wait() error {
checkStatus := map[string]string{}
- wait := 2 * time.Second
- for ok := false; s.Wait && !ok; time.Sleep(wait) {
+ sleep := 2 * time.Second
+ for {
cc, err := s.ConsulMaster()
if err != nil {
log.Printf("setup: consulMaster(): %s", err)
@@ -83,14 +90,14 @@ func (s *Setup) Run() error {
log.Printf("setup: consul.Catalog().Service(): %s", err)
continue
} else if len(apiSvcs) == 0 {
- if wait <= 2*time.Second {
- wait = wait * 2
+ if sleep <= 2*time.Second {
+ sleep = sleep * 2
log.Printf("setup: waiting for arvados-api service to appear")
}
continue
}
- ok = true
+ ok := true
svcs, _, err := cc.Catalog().Services(nil)
if err != nil {
log.Printf("setup: consul.Catalog().Services(): %s", err)
@@ -115,16 +122,10 @@ func (s *Setup) Run() error {
}
if ok {
log.Printf("All services are passing: %+v", svcs)
- // Wait to ensure any other "setup -wait"
- // processes have a chance to see the
- // all-passing state before we return (if this
- // is a test or image-building scenario, the
- // whole system might shut down and stop
- // passing as soon as we return).
- time.Sleep(2 * wait)
+ return nil
}
+ time.Sleep(sleep)
}
- return nil
}
func (s *Setup) makeDirs() error {
commit 87f40ab7ba0a3f0fc1f3648c917ff929e6e633b8
Author: Tom Clegg <tom at curoverse.com>
Date: Fri Apr 28 15:52:07 2017 -0400
11183: Fix "just setup" test.
diff --git a/server/arvados-server/setup_docker_compose_test.go b/server/arvados-server/docker_compose_test.go
similarity index 93%
rename from server/arvados-server/setup_docker_compose_test.go
rename to server/arvados-server/docker_compose_test.go
index a8f405d..f80577d 100644
--- a/server/arvados-server/setup_docker_compose_test.go
+++ b/server/arvados-server/docker_compose_test.go
@@ -6,7 +6,7 @@ import (
"testing"
)
-func TestSetupDockerCompose(t *testing.T) {
+func TestDockerCompose(t *testing.T) {
for _, cmdline := range [][]string{
{"go", "build"},
{"docker-compose", "--file", "test-docker-compose/docker-compose.yml", "-p", "arvados_setup_test", "down", "-v"},
diff --git a/server/arvados-server/main.go b/server/arvados-server/main.go
index 4159438..cfa0b17 100644
--- a/server/arvados-server/main.go
+++ b/server/arvados-server/main.go
@@ -13,6 +13,7 @@ import (
var cmds = map[string]cmd.Command{
"agent": agent.Command(),
+ "init": setup.Command(),
"setup": setup.Command(),
"configure": configure.Command(),
}
diff --git a/server/arvados-server/setup_debian8_test.go b/server/arvados-server/setup_test.go
similarity index 86%
rename from server/arvados-server/setup_debian8_test.go
rename to server/arvados-server/setup_test.go
index 7bcd48e..cd93837 100644
--- a/server/arvados-server/setup_debian8_test.go
+++ b/server/arvados-server/setup_test.go
@@ -8,7 +8,7 @@ import (
"testing"
)
-func TestSetupDebian8(t *testing.T) {
+func TestSetup(t *testing.T) {
cwd, err := os.Getwd()
if err != nil {
t.Fatal(err)
@@ -28,8 +28,8 @@ func TestSetupDebian8(t *testing.T) {
log.Printf("Publishing consul webgui at %v", ln.Addr())
for _, cmdline := range [][]string{
{"go", "build"},
- {"docker", "build", "--tag=arvados-server-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-server:/usr/bin/arvados-server:ro", "--volume=/var/cache/arvados:/var/cache/arvados:ro", "arvados-server-debian8-test"},
+ {"docker", "build", "--tag=arvados-setup-test", "test-setup"},
+ {"docker", "run", "--rm", "--publish=" + port + ":18500", "--cap-add=IPC_LOCK", "--cap-add=SYS_ADMIN", "--volume=/sys/fs/cgroup", "--volume=" + cwd + "/arvados-server:/usr/bin/arvados-server:ro", "--volume=/var/cache/arvados:/var/cache/arvados:ro", "arvados-setup-test"},
} {
cmd := exec.Command(cmdline[0], cmdline[1:]...)
cmd.Stdout = os.Stderr
diff --git a/server/arvados-server/test-docker-compose/docker-compose.yml b/server/arvados-server/test-docker-compose/docker-compose.yml
index 8c362e9..73ba0f3 100644
--- a/server/arvados-server/test-docker-compose/docker-compose.yml
+++ b/server/arvados-server/test-docker-compose/docker-compose.yml
@@ -1,7 +1,7 @@
version: '2'
services:
sys0:
- build: ../test-debian8
+ build: ../test-setup
cap_add:
- IPC_LOCK
- SYS_ADMIN
@@ -13,7 +13,7 @@ services:
- vault:/var/lib/arvados/vault
command: ["bash", "-c", "runsvdir /etc/sv & arvados-server setup -init-vault=true -run-api -wait"]
sys1:
- build: ../test-debian8
+ build: ../test-setup
cap_add:
- IPC_LOCK
- SYS_ADMIN
@@ -25,7 +25,7 @@ services:
- vault:/var/lib/arvados/vault
command: ["bash", "-c", "runsvdir /etc/sv & arvados-server setup -wait"]
sys2:
- build: ../test-debian8
+ build: ../test-setup
cap_add:
- IPC_LOCK
- SYS_ADMIN
diff --git a/server/arvados-server/test-debian8/Dockerfile b/server/arvados-server/test-setup/Dockerfile
similarity index 91%
rename from server/arvados-server/test-debian8/Dockerfile
rename to server/arvados-server/test-setup/Dockerfile
index 09261e5..04c4640 100644
--- a/server/arvados-server/test-debian8/Dockerfile
+++ b/server/arvados-server/test-setup/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 & service postgresql start & arvados-server setup -init-vault && arvados-server setup -wait"]
+CMD ["bash", "-c", "runsvdir /etc/sv & service postgresql start & arvados-server init -init-vault"]
commit 1522e9dc7cd4ccf9a636a8d53091f05560accfb2
Author: Tom Clegg <tom at curoverse.com>
Date: Fri Apr 28 13:39:42 2017 -0400
11183: Rearrange source tree
diff --git a/build/run-build-packages-one-target.sh b/build/run-build-packages-one-target.sh
index 78adfbb..b4fca9c 100755
--- a/build/run-build-packages-one-target.sh
+++ b/build/run-build-packages-one-target.sh
@@ -129,7 +129,7 @@ popd
if test -z "$packages" ; then
packages="arvados-api-server
- arvados-admin
+ arvados-server
arvados-docker-cleaner
arvados-git-httpd
arvados-node-manager
diff --git a/build/run-build-packages.sh b/build/run-build-packages.sh
index 5c6875d..06d36e3 100755
--- a/build/run-build-packages.sh
+++ b/build/run-build-packages.sh
@@ -338,7 +338,7 @@ package_go_binary sdk/go/crunchrunner crunchrunner \
"Crunchrunner executes a command inside a container and uploads the output"
package_go_binary services/arv-git-httpd arvados-git-httpd \
"Provide authenticated http access to Arvados-hosted git repositories"
-package_go_binary cmd/arvados-admin arvados-admin \
+package_go_binary server/arvados-server arvados-server \
"Arvados cluster administration tool"
package_go_binary services/crunch-dispatch-local crunch-dispatch-local \
"Dispatch Crunch containers on the local system"
diff --git a/build/run-tests.sh b/build/run-tests.sh
index e2e6f34..fd52e95 100755
--- a/build/run-tests.sh
+++ b/build/run-tests.sh
@@ -101,10 +101,10 @@ tools/crunchstat-summary
tools/keep-exercise
tools/keep-rsync
tools/keep-block-check
-lib/agent
lib/crunchstat
-lib/setup
-cmd/arvados-admin
+server/agent
+server/setup
+server/arvados-server
(*) apps/workbench is shorthand for apps/workbench_units +
apps/workbench_functionals + apps/workbench_integration
@@ -796,9 +796,7 @@ gostuff=(
sdk/go/streamer
sdk/go/crunchrunner
sdk/go/stats
- lib/agent
lib/crunchstat
- lib/setup
services/arv-git-httpd
services/crunchstat
services/keep-web
@@ -814,7 +812,9 @@ gostuff=(
tools/keep-block-check
tools/keep-exercise
tools/keep-rsync
- cmd/arvados-admin
+ server/agent
+ server/setup
+ server/arvados-server
)
for g in "${gostuff[@]}"
do
diff --git a/cmd/arvados-admin/.gitignore b/cmd/arvados-admin/.gitignore
deleted file mode 100644
index 87fbbf4..0000000
--- a/cmd/arvados-admin/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-arvados-admin
diff --git a/cmd/dispatch.go b/lib/cmd/dispatch.go
similarity index 100%
rename from cmd/dispatch.go
rename to lib/cmd/dispatch.go
diff --git a/lib/configure/configure.go b/lib/configure/configure.go
index 2f78534..88c5399 100644
--- a/lib/configure/configure.go
+++ b/lib/configure/configure.go
@@ -4,8 +4,8 @@ import (
"flag"
"os"
- "git.curoverse.com/arvados.git/lib/setup"
"git.curoverse.com/arvados.git/sdk/go/config"
+ "git.curoverse.com/arvados.git/server/setup"
)
func Command() *Configure {
diff --git a/lib/agent/agent.go b/server/agent/agent.go
similarity index 100%
rename from lib/agent/agent.go
rename to server/agent/agent.go
diff --git a/server/arvados-server/.gitignore b/server/arvados-server/.gitignore
new file mode 100644
index 0000000..b6bb7f0
--- /dev/null
+++ b/server/arvados-server/.gitignore
@@ -0,0 +1 @@
+arvados-server
diff --git a/cmd/arvados-admin/main.go b/server/arvados-server/main.go
similarity index 75%
rename from cmd/arvados-admin/main.go
rename to server/arvados-server/main.go
index d4b25a6..4159438 100644
--- a/cmd/arvados-admin/main.go
+++ b/server/arvados-server/main.go
@@ -5,10 +5,10 @@ import (
"fmt"
"os"
- "git.curoverse.com/arvados.git/cmd"
- "git.curoverse.com/arvados.git/lib/agent"
+ "git.curoverse.com/arvados.git/lib/cmd"
"git.curoverse.com/arvados.git/lib/configure"
- "git.curoverse.com/arvados.git/lib/setup"
+ "git.curoverse.com/arvados.git/server/agent"
+ "git.curoverse.com/arvados.git/server/setup"
)
var cmds = map[string]cmd.Command{
diff --git a/cmd/arvados-admin/setup_debian8_test.go b/server/arvados-server/setup_debian8_test.go
similarity index 77%
rename from cmd/arvados-admin/setup_debian8_test.go
rename to server/arvados-server/setup_debian8_test.go
index 671f8c7..7bcd48e 100644
--- a/cmd/arvados-admin/setup_debian8_test.go
+++ b/server/arvados-server/setup_debian8_test.go
@@ -28,8 +28,8 @@ func TestSetupDebian8(t *testing.T) {
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"},
+ {"docker", "build", "--tag=arvados-server-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-server:/usr/bin/arvados-server:ro", "--volume=/var/cache/arvados:/var/cache/arvados:ro", "arvados-server-debian8-test"},
} {
cmd := exec.Command(cmdline[0], cmdline[1:]...)
cmd.Stdout = os.Stderr
diff --git a/cmd/arvados-admin/setup_docker_compose_test.go b/server/arvados-server/setup_docker_compose_test.go
similarity index 100%
rename from cmd/arvados-admin/setup_docker_compose_test.go
rename to server/arvados-server/setup_docker_compose_test.go
diff --git a/cmd/arvados-admin/test-debian8/Dockerfile b/server/arvados-server/test-debian8/Dockerfile
similarity index 91%
rename from cmd/arvados-admin/test-debian8/Dockerfile
rename to server/arvados-server/test-debian8/Dockerfile
index 7db1224..09261e5 100644
--- a/cmd/arvados-admin/test-debian8/Dockerfile
+++ b/server/arvados-server/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 & service postgresql start & arvados-admin setup -init-vault && arvados-admin setup -wait"]
+CMD ["bash", "-c", "runsvdir /etc/sv & service postgresql start & arvados-server setup -init-vault && arvados-server setup -wait"]
diff --git a/cmd/arvados-admin/test-docker-compose/agent.yml b/server/arvados-server/test-docker-compose/agent.yml
similarity index 100%
rename from cmd/arvados-admin/test-docker-compose/agent.yml
rename to server/arvados-server/test-docker-compose/agent.yml
diff --git a/cmd/arvados-admin/test-docker-compose/docker-compose.yml b/server/arvados-server/test-docker-compose/docker-compose.yml
similarity index 70%
rename from cmd/arvados-admin/test-docker-compose/docker-compose.yml
rename to server/arvados-server/test-docker-compose/docker-compose.yml
index 85390ce..8c362e9 100644
--- a/cmd/arvados-admin/test-docker-compose/docker-compose.yml
+++ b/server/arvados-server/test-docker-compose/docker-compose.yml
@@ -6,35 +6,35 @@ services:
- IPC_LOCK
- SYS_ADMIN
volumes:
- - ../arvados-admin:/usr/bin/arvados-admin:ro
+ - ../arvados-server:/usr/bin/arvados-server: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
- vault:/var/lib/arvados/vault
- command: ["bash", "-c", "runsvdir /etc/sv & arvados-admin setup -init-vault=true -run-api -wait"]
+ command: ["bash", "-c", "runsvdir /etc/sv & arvados-server setup -init-vault=true -run-api -wait"]
sys1:
build: ../test-debian8
cap_add:
- IPC_LOCK
- SYS_ADMIN
volumes:
- - ../arvados-admin:/usr/bin/arvados-admin:ro
+ - ../arvados-server:/usr/bin/arvados-server: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
- vault:/var/lib/arvados/vault
- command: ["bash", "-c", "runsvdir /etc/sv & arvados-admin setup -wait"]
+ command: ["bash", "-c", "runsvdir /etc/sv & arvados-server setup -wait"]
sys2:
build: ../test-debian8
cap_add:
- IPC_LOCK
- SYS_ADMIN
volumes:
- - ../arvados-admin:/usr/bin/arvados-admin:ro
+ - ../arvados-server:/usr/bin/arvados-server: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
- vault:/var/lib/arvados/vault
- command: ["bash", "-c", "runsvdir /etc/sv & arvados-admin setup -wait"]
+ command: ["bash", "-c", "runsvdir /etc/sv & arvados-server setup -wait"]
volumes:
vault:
diff --git a/cmd/arvados-admin/test-docker-compose/encrypt-key.txt b/server/arvados-server/test-docker-compose/encrypt-key.txt
similarity index 100%
rename from cmd/arvados-admin/test-docker-compose/encrypt-key.txt
rename to server/arvados-server/test-docker-compose/encrypt-key.txt
diff --git a/cmd/arvados-admin/test-docker-compose/master-token.txt b/server/arvados-server/test-docker-compose/master-token.txt
similarity index 100%
rename from cmd/arvados-admin/test-docker-compose/master-token.txt
rename to server/arvados-server/test-docker-compose/master-token.txt
diff --git a/lib/setup/arvados_services.go b/server/setup/arvados_services.go
similarity index 98%
rename from lib/setup/arvados_services.go
rename to server/setup/arvados_services.go
index ca3b68f..39b401a 100644
--- a/lib/setup/arvados_services.go
+++ b/server/setup/arvados_services.go
@@ -221,7 +221,7 @@ func (s *Setup) installArvadosServices() error {
})
}
// f = append(f, func() error {
- // return s.consulTemplateExec("arvados-agent", "./agent.json", tmplArvadosAgent, 0640, "arvados-admin", "agent", "-config", "./agent.json")
+ // return s.consulTemplateExec("arvados-agent", "./agent.json", tmplArvadosAgent, 0640, "arvados-server", "agent", "-config", "./agent.json")
// })
for _, f := range todo {
err := f()
diff --git a/lib/setup/cert.go b/server/setup/cert.go
similarity index 100%
rename from lib/setup/cert.go
rename to server/setup/cert.go
diff --git a/lib/setup/check.go b/server/setup/check.go
similarity index 100%
rename from lib/setup/check.go
rename to server/setup/check.go
diff --git a/lib/setup/command.go b/server/setup/command.go
similarity index 100%
rename from lib/setup/command.go
rename to server/setup/command.go
diff --git a/lib/setup/configure.go b/server/setup/configure.go
similarity index 100%
rename from lib/setup/configure.go
rename to server/setup/configure.go
diff --git a/lib/setup/consul.go b/server/setup/consul.go
similarity index 100%
rename from lib/setup/consul.go
rename to server/setup/consul.go
diff --git a/lib/setup/curoverse_package.go b/server/setup/curoverse_package.go
similarity index 100%
rename from lib/setup/curoverse_package.go
rename to server/setup/curoverse_package.go
diff --git a/lib/setup/daemon.go b/server/setup/daemon.go
similarity index 100%
rename from lib/setup/daemon.go
rename to server/setup/daemon.go
diff --git a/lib/setup/download.go b/server/setup/download.go
similarity index 100%
rename from lib/setup/download.go
rename to server/setup/download.go
diff --git a/lib/setup/os_package.go b/server/setup/os_package.go
similarity index 100%
rename from lib/setup/os_package.go
rename to server/setup/os_package.go
diff --git a/lib/setup/runit.go b/server/setup/runit.go
similarity index 100%
rename from lib/setup/runit.go
rename to server/setup/runit.go
diff --git a/lib/setup/setup.go b/server/setup/setup.go
similarity index 98%
rename from lib/setup/setup.go
rename to server/setup/setup.go
index fdc7fb7..8886946 100644
--- a/lib/setup/setup.go
+++ b/server/setup/setup.go
@@ -7,8 +7,8 @@ import (
"os"
"time"
- "git.curoverse.com/arvados.git/lib/agent"
"git.curoverse.com/arvados.git/sdk/go/config"
+ "git.curoverse.com/arvados.git/server/agent"
)
func Command() *Setup {
diff --git a/lib/setup/systemd.go b/server/setup/systemd.go
similarity index 100%
rename from lib/setup/systemd.go
rename to server/setup/systemd.go
diff --git a/lib/setup/tmpl_nginx_api.go b/server/setup/tmpl_nginx_api.go
similarity index 100%
rename from lib/setup/tmpl_nginx_api.go
rename to server/setup/tmpl_nginx_api.go
diff --git a/lib/setup/vault.go b/server/setup/vault.go
similarity index 100%
rename from lib/setup/vault.go
rename to server/setup/vault.go
diff --git a/lib/setup/write_file.go b/server/setup/write_file.go
similarity index 100%
rename from lib/setup/write_file.go
rename to server/setup/write_file.go
commit ff310f43338a2443f9b11b7a55e619dc1961d234
Author: Tom Clegg <tom at curoverse.com>
Date: Fri Apr 28 13:11:42 2017 -0400
11183: Fix setup-already-done check.
diff --git a/lib/setup/configure.go b/lib/setup/configure.go
index 9c22b3e..7f63aa8 100644
--- a/lib/setup/configure.go
+++ b/lib/setup/configure.go
@@ -16,8 +16,10 @@ func (s *Setup) maybeConfigure() error {
}
kv := cc.KV()
- _, _, err = kv.Get("arvados/service/API/port", nil)
- if err == nil {
+ cur, _, err := kv.Get("arvados/service/API/port", nil)
+ if err != nil {
+ return err
+ } else if cur != nil {
// already configured
return nil
}
@@ -48,8 +50,8 @@ func (s *Setup) Reconfigure() error {
cur, _, err := kv.Get(pair.Key, nil)
if err != nil {
- log.Print(err)
- } else if bytes.Compare(cur.Value, pair.Value) == 0 {
+ return err
+ } else if cur != nil && bytes.Compare(cur.Value, pair.Value) == 0 {
continue
}
commit 55466cec28927431c15e61078b9e56225ce77c72
Author: Tom Clegg <tom at curoverse.com>
Date: Sun Apr 9 03:57:43 2017 -0400
11183: Avoid reusing httpclient via vault config to prevent "protocol https already registered" error from ConfigureTransport.
diff --git a/lib/setup/setup.go b/lib/setup/setup.go
index f578d20..fdc7fb7 100644
--- a/lib/setup/setup.go
+++ b/lib/setup/setup.go
@@ -9,7 +9,6 @@ import (
"git.curoverse.com/arvados.git/lib/agent"
"git.curoverse.com/arvados.git/sdk/go/config"
- vaultAPI "github.com/hashicorp/vault/api"
)
func Command() *Setup {
@@ -35,7 +34,6 @@ type Setup struct {
encryptKey string
masterToken string
- vaultCfg *vaultAPI.Config
}
func (s *Setup) ParseFlags(args []string) error {
diff --git a/lib/setup/vault.go b/lib/setup/vault.go
index 2a25578..4b134fb 100644
--- a/lib/setup/vault.go
+++ b/lib/setup/vault.go
@@ -19,9 +19,6 @@ func (s *Setup) installVault() error {
if err := s.consulInit(); err != nil {
return err
}
- if err := s.vaultInit(); err != nil {
- return err
- }
if s.vaultCheck() == nil {
return nil
}
@@ -215,14 +212,10 @@ func (s *Setup) vaultBootstrap() error {
return nil
}
-func (s *Setup) vaultInit() error {
- s.vaultCfg = vaultAPI.DefaultConfig()
- s.vaultCfg.Address = fmt.Sprintf("http://%s:%d", s.LANHost, s.Ports.VaultServer)
- return nil
-}
-
func (s *Setup) vaultClient() (*vaultAPI.Client, error) {
- return vaultAPI.NewClient(s.vaultCfg)
+ cfg := vaultAPI.DefaultConfig()
+ cfg.Address = fmt.Sprintf("http://%s:%d", s.LANHost, s.Ports.VaultServer)
+ return vaultAPI.NewClient(cfg)
}
func (s *Setup) vaultCheck() error {
commit 957ec5ff80456706aa3bd709669e4a17251f6791
Author: Tom Clegg <tom at curoverse.com>
Date: Thu Mar 23 15:54:49 2017 -0400
11183: Less noise while waiting for health checks.
diff --git a/lib/setup/setup.go b/lib/setup/setup.go
index a4c8c43..f578d20 100644
--- a/lib/setup/setup.go
+++ b/lib/setup/setup.go
@@ -71,6 +71,7 @@ func (s *Setup) Run() error {
}
}
+ checkStatus := map[string]string{}
wait := 2 * time.Second
for ok := false; s.Wait && !ok; time.Sleep(wait) {
cc, err := s.ConsulMaster()
@@ -90,7 +91,6 @@ func (s *Setup) Run() error {
}
continue
}
- log.Printf("arvados-api service: %#v", apiSvcs)
ok = true
svcs, _, err := cc.Catalog().Services(nil)
@@ -106,10 +106,13 @@ func (s *Setup) Run() error {
}
for _, check := range checks {
+ if checkStatus[check.CheckID] != check.Status {
+ log.Printf("setup: node %q service %q check %q state %q", check.Node, check.ServiceName, check.CheckID, check.Status)
+ }
if check.Status != "passing" {
- log.Printf("waiting for node %q service %q check %q state %q", check.Node, check.ServiceName, check.CheckID, check.Status)
ok = false
}
+ checkStatus[check.CheckID] = check.Status
}
}
if ok {
commit fb08faf4b134a09eee928b596382cf17c75a8c89
Author: Tom Clegg <tom at curoverse.com>
Date: Wed Mar 15 02:22:03 2017 -0400
11183: More consul setup.
diff --git a/cmd/arvados-admin/main.go b/cmd/arvados-admin/main.go
index de532cb..d4b25a6 100644
--- a/cmd/arvados-admin/main.go
+++ b/cmd/arvados-admin/main.go
@@ -7,12 +7,14 @@ import (
"git.curoverse.com/arvados.git/cmd"
"git.curoverse.com/arvados.git/lib/agent"
+ "git.curoverse.com/arvados.git/lib/configure"
"git.curoverse.com/arvados.git/lib/setup"
)
var cmds = map[string]cmd.Command{
- "agent": agent.Command(),
- "setup": setup.Command(),
+ "agent": agent.Command(),
+ "setup": setup.Command(),
+ "configure": configure.Command(),
}
func main() {
diff --git a/cmd/arvados-admin/setup_docker_compose_test.go b/cmd/arvados-admin/setup_docker_compose_test.go
index e88dc16..a8f405d 100644
--- a/cmd/arvados-admin/setup_docker_compose_test.go
+++ b/cmd/arvados-admin/setup_docker_compose_test.go
@@ -9,8 +9,11 @@ import (
func TestSetupDockerCompose(t *testing.T) {
for _, cmdline := range [][]string{
{"go", "build"},
- {"docker-compose", "--file", "test-docker-compose/docker-compose.yml", "down", "-v"},
- {"docker-compose", "--file", "test-docker-compose/docker-compose.yml", "up"},
+ {"docker-compose", "--file", "test-docker-compose/docker-compose.yml", "-p", "arvados_setup_test", "down", "-v"},
+ {"docker-compose", "--file", "test-docker-compose/docker-compose.yml", "-p", "arvados_setup_test", "up"},
+ {"docker", "wait", "arvadossetuptest_sys0_1"},
+ {"docker", "wait", "arvadossetuptest_sys1_1"},
+ {"docker", "wait", "arvadossetuptest_sys2_1"},
} {
cmd := exec.Command(cmdline[0], cmdline[1:]...)
cmd.Stdout = os.Stderr
diff --git a/lib/configure/configure.go b/lib/configure/configure.go
new file mode 100644
index 0000000..2f78534
--- /dev/null
+++ b/lib/configure/configure.go
@@ -0,0 +1,32 @@
+package configure
+
+import (
+ "flag"
+ "os"
+
+ "git.curoverse.com/arvados.git/lib/setup"
+ "git.curoverse.com/arvados.git/sdk/go/config"
+)
+
+func Command() *Configure {
+ return &Configure{
+ Setup: setup.Command(),
+ }
+}
+
+type Configure struct {
+ *setup.Setup
+}
+
+func (c *Configure) ParseFlags(args []string) error {
+ fs := flag.NewFlagSet("configure", flag.ContinueOnError)
+ return fs.Parse(args)
+}
+
+func (c *Configure) Run() error {
+ err := config.LoadFile(c, c.DefaultConfigFile())
+ if err != nil && !os.IsNotExist(err) {
+ return err
+ }
+ return c.Setup.Reconfigure()
+}
diff --git a/lib/setup/arvados_services.go b/lib/setup/arvados_services.go
index f15e693..ca3b68f 100644
--- a/lib/setup/arvados_services.go
+++ b/lib/setup/arvados_services.go
@@ -195,17 +195,17 @@ func (s *Setup) installArvadosServices() error {
func() error {
return os.Symlink("../sites-available/arvados-api.conf", "/etc/nginx/sites-enabled/arvados-api.conf")
})
- c, err := s.consulMaster()
+ c, err := s.ConsulMaster()
if err != nil {
return err
}
err = c.Agent().ServiceRegister(&consul.AgentServiceRegistration{
ID: "arvados-api:" + s.LANHost,
- Name: "api",
+ Name: "arvados-api",
Port: s.Agent.Ports.API,
Checks: consul.AgentServiceChecks{
{
- HTTP: fmt.Sprintf("http://%s:%d/discovery/v1/apis/arvados/v1/rest", s.LANHost, s.Agent.Ports.API),
+ HTTP: fmt.Sprintf("http://127.0.0.1:%d/discovery/v1/apis/arvados/v1/rest", s.Agent.Ports.API),
Interval: "15s",
},
},
diff --git a/lib/setup/configure.go b/lib/setup/configure.go
new file mode 100644
index 0000000..9c22b3e
--- /dev/null
+++ b/lib/setup/configure.go
@@ -0,0 +1,63 @@
+package setup
+
+import (
+ "bytes"
+ "encoding/json"
+ "log"
+ "strconv"
+
+ consul "github.com/hashicorp/consul/api"
+)
+
+func (s *Setup) maybeConfigure() error {
+ cc, err := s.ConsulMaster()
+ if err != nil {
+ return err
+ }
+ kv := cc.KV()
+
+ _, _, err = kv.Get("arvados/service/API/port", nil)
+ if err == nil {
+ // already configured
+ return nil
+ }
+ return s.Reconfigure()
+}
+
+func (s *Setup) Reconfigure() error {
+ cc, err := s.ConsulMaster()
+ if err != nil {
+ return err
+ }
+ kv := cc.KV()
+
+ var portmap map[string]int
+ buf, err := json.Marshal(s.Ports)
+ if err != nil {
+ return err
+ }
+ err = json.Unmarshal(buf, &portmap)
+ if err != nil {
+ return err
+ }
+ for name, port := range portmap {
+ pair := &consul.KVPair{
+ Key: "arvados/service/" + name + "/port",
+ Value: []byte(strconv.Itoa(port)),
+ }
+
+ cur, _, err := kv.Get(pair.Key, nil)
+ if err != nil {
+ log.Print(err)
+ } else if bytes.Compare(cur.Value, pair.Value) == 0 {
+ continue
+ }
+
+ log.Printf("%q => %q", pair.Key, pair.Value)
+ _, err = kv.Put(pair, nil)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/lib/setup/consul.go b/lib/setup/consul.go
index e1a70d0..0af119b 100644
--- a/lib/setup/consul.go
+++ b/lib/setup/consul.go
@@ -143,15 +143,18 @@ func (s *Setup) installConsul() error {
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
+func (s *Setup) ConsulMaster() (*api.Client, error) {
+ if s.masterToken == "" {
+ t, err := ioutil.ReadFile(path.Join(s.DataDir, "master-token.txt"))
+ if err != nil {
+ return nil, err
+ }
+ s.masterToken = string(t)
}
ccfg := api.DefaultConfig()
ccfg.Address = fmt.Sprintf("127.0.0.1:%d", s.Ports.ConsulHTTP)
ccfg.Datacenter = s.ClusterID
- ccfg.Token = string(masterToken)
+ ccfg.Token = s.masterToken
return api.NewClient(ccfg)
}
@@ -185,7 +188,7 @@ func (s *Setup) consulInit() error {
}
func (s *Setup) consulCheck() error {
- consul, err := s.consulMaster()
+ consul, err := s.ConsulMaster()
if err != nil {
return err
}
@@ -195,7 +198,7 @@ func (s *Setup) consulCheck() error {
// OnlyNode returns true if this is the only consul node.
func (s *Setup) OnlyNode() (bool, error) {
- c, err := s.consulMaster()
+ c, err := s.ConsulMaster()
if err != nil {
return false, err
}
diff --git a/lib/setup/daemon.go b/lib/setup/daemon.go
index 3985259..a7b902f 100644
--- a/lib/setup/daemon.go
+++ b/lib/setup/daemon.go
@@ -33,7 +33,7 @@ func (s *Setup) installService(d daemon) error {
if d.noRegister {
return nil
}
- consul, err := s.consulMaster()
+ consul, err := s.ConsulMaster()
if err != nil {
return err
}
diff --git a/lib/setup/setup.go b/lib/setup/setup.go
index cdbb5db..a4c8c43 100644
--- a/lib/setup/setup.go
+++ b/lib/setup/setup.go
@@ -61,6 +61,7 @@ func (s *Setup) Run() error {
s.installConsul,
s.installConsulTemplate,
s.installVault,
+ s.maybeConfigure,
s.generateSelfSignedCert,
s.installArvadosServices,
} {
@@ -72,7 +73,7 @@ func (s *Setup) Run() error {
wait := 2 * time.Second
for ok := false; s.Wait && !ok; time.Sleep(wait) {
- cc, err := s.consulMaster()
+ cc, err := s.ConsulMaster()
if err != nil {
log.Printf("setup: consulMaster(): %s", err)
continue
diff --git a/lib/setup/tmpl_nginx_api.go b/lib/setup/tmpl_nginx_api.go
index c2c07bf..6a448f7 100644
--- a/lib/setup/tmpl_nginx_api.go
+++ b/lib/setup/tmpl_nginx_api.go
@@ -1,7 +1,7 @@
package setup
const tmplNginxAPI = `server {
- listen 127.0.0.1:8000;
+ listen 127.0.0.1:{{ key "arvados/service/API/port" }};
server_name localhost-api;
root /var/www/arvados-api/current/public;
@@ -21,11 +21,11 @@ const tmplNginxAPI = `server {
}
upstream api {
- server 127.0.0.1:8000 fail_timeout=10s;
+ server 127.0.0.1:{{ key "arvados/service/API/port" }} fail_timeout=10s;
}
upstream websockets {
- server 127.0.0.1:8100 fail_timeout=10s;
+ server 127.0.0.1:{{ key "arvados/service/Websocket/port" }} fail_timeout=10s;
}
proxy_http_version 1.1;
diff --git a/lib/setup/vault.go b/lib/setup/vault.go
index 8443764..2a25578 100644
--- a/lib/setup/vault.go
+++ b/lib/setup/vault.go
@@ -154,7 +154,7 @@ func (s *Setup) vaultBootstrap() error {
if s.InitVault {
// Use master token to create a management token
- master, err := s.consulMaster()
+ master, err := s.ConsulMaster()
if err != nil {
return err
}
commit a328dd7d4d396d1c2f67d3a74989f0194b04e714
Author: Tom Clegg <tom at curoverse.com>
Date: Tue Mar 14 19:09:07 2017 -0400
11183: Start API server
diff --git a/cmd/arvados-admin/test-debian8/Dockerfile b/cmd/arvados-admin/test-debian8/Dockerfile
index 6886fd3..7db1224 100644
--- a/cmd/arvados-admin/test-debian8/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 & arvados-admin setup -init-vault && arvados-admin setup -wait"]
+CMD ["bash", "-c", "runsvdir /etc/sv & service postgresql start & arvados-admin setup -init-vault && arvados-admin setup -wait"]
diff --git a/cmd/arvados-admin/test-docker-compose/docker-compose.yml b/cmd/arvados-admin/test-docker-compose/docker-compose.yml
index aa5cb48..85390ce 100644
--- a/cmd/arvados-admin/test-docker-compose/docker-compose.yml
+++ b/cmd/arvados-admin/test-docker-compose/docker-compose.yml
@@ -11,7 +11,7 @@ services:
- ./encrypt-key.txt:/var/lib/arvados/encrypt-key.txt:ro
- ./master-token.txt:/var/lib/arvados/master-token.txt:ro
- vault:/var/lib/arvados/vault
- command: ["bash", "-c", "runsvdir /etc/sv & arvados-admin setup -init-vault=true -wait"]
+ command: ["bash", "-c", "runsvdir /etc/sv & arvados-admin setup -init-vault=true -run-api -wait"]
sys1:
build: ../test-debian8
cap_add:
diff --git a/lib/agent/agent.go b/lib/agent/agent.go
index 2456423..d16917a 100644
--- a/lib/agent/agent.go
+++ b/lib/agent/agent.go
@@ -42,6 +42,13 @@ type PortsConfig struct {
NomadRPC int
NomadSerf int
VaultServer int
+
+ API int
+ GitHTTP int
+ KeepWeb int
+ Keepproxy int
+ Keepstore int
+ Websocket int
}
type RepoConfig struct {
@@ -87,6 +94,13 @@ func Command() *Agent {
NomadRPC: 14647,
NomadSerf: 14648,
VaultServer: 18200,
+
+ API: 8000,
+ GitHTTP: 9001,
+ KeepWeb: 9002,
+ Keepproxy: 25100,
+ Keepstore: 25107,
+ Websocket: 8100,
},
DataDir: "/var/lib/arvados",
UsrDir: "/usr/local/arvados",
diff --git a/lib/setup/arvados_services.go b/lib/setup/arvados_services.go
new file mode 100644
index 0000000..f15e693
--- /dev/null
+++ b/lib/setup/arvados_services.go
@@ -0,0 +1,242 @@
+package setup
+
+import (
+ "bytes"
+ "crypto/rand"
+ "fmt"
+ "io"
+ "log"
+ "net/http"
+ "os"
+ "os/exec"
+ "os/user"
+ "path"
+ "strconv"
+ "time"
+
+ consul "github.com/hashicorp/consul/api"
+)
+
+func (s *Setup) installPassenger() error {
+ if _, err := os.Stat("/etc/nginx/conf.d/passenger.conf"); err == nil {
+ return nil
+ }
+
+ err := command("apt-get", "install", "-y", "apt-transport-https", "ca-certificates").Run()
+ if err != nil {
+ return err
+ }
+ err = atomicWriteFile("/etc/apt/sources.list.d/passenger.list", []byte("deb https://oss-binaries.phusionpassenger.com/apt/passenger jessie main\n"), 0644)
+ if err != nil {
+ return err
+ }
+ err = command("apt-get", "update").Run()
+ if err != nil {
+ return err
+ }
+ err = command("apt-get", "install", "-y", "nginx-extras", "passenger").Run()
+ if err != nil {
+ return err
+ }
+ err = os.Symlink("../passenger.conf", "/etc/nginx/conf.d/passenger.conf")
+ if err != nil {
+ return err
+ }
+ return command("service", "nginx", "restart").Run()
+}
+
+func (s *Setup) installArvadosServices() error {
+ var todo []func() error
+ var cvPkgs []string
+ if s.RunAPI {
+ err := (&osPackage{Debian: "curl"}).install()
+ if err != nil {
+ return err
+ }
+ resp, err := http.Get("https://get.rvm.io")
+ if err != nil {
+ return err
+ }
+ rvmCmd := command("bash", "-s", "stable", "--ruby=2.3")
+ rvmCmd.Stdin = resp.Body
+
+ todo = append(todo,
+ command("bash", "-c", `gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3`).Run,
+ rvmCmd.Run,
+ )
+ todo = append(todo,
+ command("apt-get", "install", "-y", "--no-install-recommends",
+ "bison", "build-essential", "libcurl4-openssl-dev", "git").Run,
+ )
+
+ err = (&osPackage{Debian: "postgresql"}).install()
+ if err != nil {
+ return err
+ }
+
+ wwwUser, err := user.Lookup("www-data")
+ if err != nil {
+ return err
+ }
+ wwwGID, err := strconv.Atoi(wwwUser.Gid)
+ if err != nil {
+ return err
+ }
+
+ gitRepoDir := path.Join(s.Agent.DataDir, "git", "repositories")
+ {
+ if err := os.MkdirAll(gitRepoDir, 0755); err != nil {
+ return err
+ }
+ err = os.Chown(gitRepoDir, 0, wwwGID)
+ if err != nil {
+ return err
+ }
+ }
+
+ appYml := "/etc/arvados/api/application.yml"
+ {
+ secretToken, err := s.newSecret(32)
+ if err != nil {
+ return err
+ }
+ blobSigningKey, err := s.newSecret(32)
+ if err != nil {
+ return err
+ }
+ err = atomicWriteJSON(appYml, map[string]interface{}{
+ "production": map[string]interface{}{
+ "uuid_prefix": s.Agent.ClusterID,
+ "secret_token": secretToken,
+ "blob_signing_key": blobSigningKey,
+ "sso_app_secret": "TODO",
+ "sso_app_id": "TODO",
+ "sso_provider_url": "https://TODO/",
+ "workbench_address": "https://TODO/",
+ "websocket_address": "wss://TODO/",
+ "git_repositories_dir": gitRepoDir,
+ "git_internal_dir": path.Join(s.Agent.DataDir, "internal.git"),
+ }}, 0640)
+ err = os.Chown(appYml, 0, wwwGID)
+ if err != nil {
+ return err
+ }
+ }
+
+ dbYml := "/etc/arvados/api/database.yml"
+ if _, err = os.Stat(dbYml); err != nil && !os.IsNotExist(err) {
+ return err
+ } else if os.IsNotExist(err) {
+ saidWaiting := false
+ waitPg:
+ for {
+ err := command("pg_isready").Run()
+ switch err := err.(type) {
+ case nil:
+ break waitPg
+ case *exec.ExitError:
+ if !saidWaiting {
+ err := command("service", "postgresql", "start").Run()
+ if err != nil {
+ return err
+ }
+ log.Print("waiting for postgres to be ready")
+ saidWaiting = true
+ }
+ time.Sleep(time.Second)
+ continue
+ default:
+ return err
+ }
+ }
+ password, err := s.newSecret(16)
+ if err != nil {
+ return err
+ }
+ // TODO: write password to a file here, so if
+ // running "create user" succeeds but writing
+ // database.yml fails, we can recover on a
+ // subsequent attempt.
+
+ sql := fmt.Sprintf("create user arvados with createdb encrypted password '%s'", password)
+ cmd := command("su", "-c", "psql", "postgres")
+ cmd.Stdin = bytes.NewBufferString(sql)
+ err = cmd.Run()
+ if err != nil {
+ return err
+ }
+ err = atomicWriteJSON(dbYml, map[string]interface{}{
+ "production": map[string]interface{}{
+ "adapter": "postgresql",
+ "template": "template0",
+ "encoding": "utf8",
+ "database": "arvados_" + s.Agent.ClusterID,
+ "username": "arvados",
+ "password": password,
+ "host": "localhost",
+ }}, 0640)
+ if err != nil {
+ return err
+ }
+ err = os.Chown(dbYml, 0, wwwGID)
+ if err != nil {
+ return err
+ }
+ }
+ cvPkgs = append(cvPkgs,
+ "arvados-api-server",
+ )
+ todo = append(todo,
+ command("apt-key", "adv", "--keyserver", "hkp://keyserver.ubuntu.com:80", "--recv-keys", "561F9B9CAC40B2F7").Run,
+ s.installPassenger,
+ func() error {
+ return s.consulTemplateTrigger("arvados-api", "/etc/nginx/sites-available/arvados-api.conf", tmplNginxAPI, 0640, "service nginx reload")
+ },
+ func() error {
+ return os.Symlink("../sites-available/arvados-api.conf", "/etc/nginx/sites-enabled/arvados-api.conf")
+ })
+ c, err := s.consulMaster()
+ if err != nil {
+ return err
+ }
+ err = c.Agent().ServiceRegister(&consul.AgentServiceRegistration{
+ ID: "arvados-api:" + s.LANHost,
+ Name: "api",
+ Port: s.Agent.Ports.API,
+ Checks: consul.AgentServiceChecks{
+ {
+ HTTP: fmt.Sprintf("http://%s:%d/discovery/v1/apis/arvados/v1/rest", s.LANHost, s.Agent.Ports.API),
+ Interval: "15s",
+ },
+ },
+ })
+ if err != nil {
+ return err
+ }
+ }
+ for _, pkg := range cvPkgs {
+ pkg := pkg
+ todo = append(todo, func() error {
+ return s.installCuroversePackage(pkg)
+ })
+ }
+ // f = append(f, func() error {
+ // return s.consulTemplateExec("arvados-agent", "./agent.json", tmplArvadosAgent, 0640, "arvados-admin", "agent", "-config", "./agent.json")
+ // })
+ for _, f := range todo {
+ err := f()
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (s *Setup) newSecret(n int) (string, error) {
+ buf := &bytes.Buffer{}
+ _, err := io.CopyN(buf, rand.Reader, 16)
+ if err != nil {
+ return "", err
+ }
+ return fmt.Sprintf("%x", buf), nil
+}
diff --git a/lib/setup/cert.go b/lib/setup/cert.go
new file mode 100644
index 0000000..b54735e
--- /dev/null
+++ b/lib/setup/cert.go
@@ -0,0 +1,24 @@
+package setup
+
+import (
+ "os"
+ "path"
+)
+
+func (s *Setup) generateSelfSignedCert() error {
+ path := path.Join(s.DataDir, "certs")
+ if err := os.MkdirAll(path, 0700); err != nil {
+ return err
+ }
+ for _, f := range []func() error{
+ command("openssl", "genrsa", "-out", path+"/selfsigned.key", "2048").Run,
+ command("openssl", "req", "-new", "-batch", "-subj", "/C=US/ST=MA/O=Example, Inc./CN=example.com", "-key", path+"/selfsigned.key", "-out", path+"/selfsigned.csr").Run,
+ command("openssl", "x509", "-req", "-days", "3650", "-in", path+"/selfsigned.csr", "-signkey", path+"/selfsigned.key", "-out", path+"/selfsigned.crt").Run,
+ } {
+ err := f()
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/lib/setup/consul.go b/lib/setup/consul.go
index 9cc2f29..e1a70d0 100644
--- a/lib/setup/consul.go
+++ b/lib/setup/consul.go
@@ -13,6 +13,51 @@ import (
"github.com/hashicorp/consul/api"
)
+func (s *Setup) consulTemplateTrigger(name, dst, tmpl string, mode os.FileMode, reload string) error {
+ atomicWriteFile(dst+".tmpl", []byte(tmpl), mode)
+
+ svdir := "/etc/sv/" + name
+ cfgPath := svdir + "/consul.json"
+ atomicWriteJSON(cfgPath, map[string]interface{}{
+ "consul": map[string]interface{}{
+ "address": fmt.Sprintf("%s:%d", s.LANHost, s.Agent.Ports.ConsulHTTP),
+ "token": s.masterToken,
+ },
+ "vault": map[string]interface{}{
+ "address": fmt.Sprintf("http://%s:%d", s.LANHost, s.Agent.Ports.VaultServer),
+ },
+ }, 0600)
+
+ ct := path.Join(s.UsrDir, "bin", "consul-template")
+ args := []string{
+ "-config", cfgPath, "-template", dst + ".tmpl:" + dst + ":" + reload,
+ }
+ script := fmt.Sprintf("#!/bin/sh\nexec %q ", ct)
+ for _, a := range args {
+ script = script + fmt.Sprintf(" %q", a)
+ }
+ script = script + "\n"
+
+ atomicWriteFile(svdir+"/run", []byte(script), 0755)
+ err := command("sv", "term", svdir).Run()
+ if _, ok := err.(*exec.ExitError); err != nil && !ok {
+ // "sv could not send term" is ok, but "sv not found" is not ok
+ return err
+ }
+ return nil
+}
+
+func (s *Setup) installConsulTemplate() error {
+ prog := path.Join(s.UsrDir, "bin", "consul-template")
+ return (&download{
+ URL: "https://releases.hashicorp.com/consul-template/0.18.1/consul-template_0.18.1_linux_amd64.zip",
+ Dest: prog,
+ Size: 6932736,
+ Mode: 0755,
+ PreloadDir: s.PreloadDir,
+ }).install()
+}
+
func (s *Setup) installConsul() error {
prog := path.Join(s.UsrDir, "bin", "consul")
err := (&download{
diff --git a/lib/setup/curoverse_package.go b/lib/setup/curoverse_package.go
new file mode 100644
index 0000000..3f7f529
--- /dev/null
+++ b/lib/setup/curoverse_package.go
@@ -0,0 +1,36 @@
+package setup
+
+import (
+ "fmt"
+ "os"
+)
+
+func (s *Setup) installCuroversePackage(name string) error {
+ rel := s.Agent.ArvadosAptRepo.Release
+ if rel == "" {
+ return fmt.Errorf("os release not known: cannot add arvados package repo")
+ }
+ listFn := "/etc/apt/sources.list.d/arvados.list"
+ {
+ err := command("apt-key", "adv", "--keyserver", "pool.sks-keyservers.net", "--recv", "1078ECD7").Run()
+ if err != nil {
+ return err
+ }
+ _, err = os.Stat(listFn)
+ if os.IsNotExist(err) {
+ err = atomicWriteFile(listFn, []byte(fmt.Sprintf("deb http://apt.arvados.org/ %s main\n", rel)), 0644)
+ }
+ if err != nil {
+ return err
+ }
+ err = command("apt-get", "update").Run()
+ if err != nil {
+ os.Remove(listFn)
+ return err
+ }
+ }
+ return (&osPackage{
+ Debian: name,
+ RedHat: name,
+ }).install()
+}
diff --git a/lib/setup/setup.go b/lib/setup/setup.go
index 25c4d25..cdbb5db 100644
--- a/lib/setup/setup.go
+++ b/lib/setup/setup.go
@@ -30,6 +30,7 @@ type Setup struct {
InitVault bool
LANHost string
PreloadDir string
+ RunAPI bool
Wait bool
encryptKey string
@@ -42,6 +43,7 @@ func (s *Setup) ParseFlags(args []string) error {
fs.StringVar(&s.ClusterID, "cluster-id", s.ClusterID, "five-character cluster ID")
fs.BoolVar(&s.InitVault, "init-vault", s.InitVault, "initialize the vault if needed")
fs.BoolVar(&s.Unseal, "unseal", s.Unseal, "unseal the vault automatically")
+ fs.BoolVar(&s.RunAPI, "run-api", s.RunAPI, "run API server on this node")
fs.BoolVar(&s.Wait, "wait", s.Wait, "wait for all nodes to come up before exiting")
return fs.Parse(args)
}
@@ -57,7 +59,10 @@ func (s *Setup) Run() error {
(&osPackage{Debian: "nginx"}).install,
s.installRunit,
s.installConsul,
+ s.installConsulTemplate,
s.installVault,
+ s.generateSelfSignedCert,
+ s.installArvadosServices,
} {
err := f()
if err != nil {
@@ -72,6 +77,20 @@ func (s *Setup) Run() error {
log.Printf("setup: consulMaster(): %s", err)
continue
}
+
+ apiSvcs, _, err := cc.Catalog().Service("arvados-api", "", nil)
+ if err != nil {
+ log.Printf("setup: consul.Catalog().Service(): %s", err)
+ continue
+ } else if len(apiSvcs) == 0 {
+ if wait <= 2*time.Second {
+ wait = wait * 2
+ log.Printf("setup: waiting for arvados-api service to appear")
+ }
+ continue
+ }
+ log.Printf("arvados-api service: %#v", apiSvcs)
+
ok = true
svcs, _, err := cc.Catalog().Services(nil)
if err != nil {
diff --git a/lib/setup/tmpl_nginx_api.go b/lib/setup/tmpl_nginx_api.go
new file mode 100644
index 0000000..c2c07bf
--- /dev/null
+++ b/lib/setup/tmpl_nginx_api.go
@@ -0,0 +1,95 @@
+package setup
+
+const tmplNginxAPI = `server {
+ listen 127.0.0.1:8000;
+ server_name localhost-api;
+
+ root /var/www/arvados-api/current/public;
+ index index.html index.htm index.php;
+
+ passenger_enabled on;
+ # if using RVM:
+ passenger_ruby /usr/local/rvm/wrappers/default/ruby;
+
+ # This value effectively limits the size of API objects users can
+ # create, especially collections. If you change this, you should
+ # also ensure the following settings match it:
+ # * "client_max_body_size" in the server section below
+ # * "client_max_body_size" in the Workbench Nginx configuration (twice)
+ # * "max_request_size" in the API server's application.yml file
+ client_max_body_size 128m;
+}
+
+upstream api {
+ server 127.0.0.1:8000 fail_timeout=10s;
+}
+
+upstream websockets {
+ server 127.0.0.1:8100 fail_timeout=10s;
+}
+
+proxy_http_version 1.1;
+
+# When Keep clients request a list of Keep services from the API server, the
+# server will automatically return the list of available proxies if
+# the request headers include X-External-Client: 1. Following the example
+# here, at the end of this section, add a line for each netmask that has
+# direct access to Keep storage daemons to set this header value to 0.
+geo $external_client {
+ default 1;
+ 10.0.0.0/8 0;
+ 172.16.0.0/12 0;
+ 192.168.0.0/16 0;
+}
+
+server {
+ listen 0.0.0.0:443 ssl;
+ server_name uuid_prefix.your.domain;
+
+ ssl on;
+ ssl_certificate {{ keyOrDefault "arvados/api/sslCertPath" "/var/lib/arvados/certs/selfsigned.crt" }};
+ ssl_certificate_key {{ keyOrDefault "arvados/api/sslKeyPath" "/var/lib/arvados/certs/selfsigned.key" }};
+
+ index index.html index.htm index.php;
+
+ # Refer to the comment about this setting in the server section above.
+ client_max_body_size 128m;
+
+ location / {
+ proxy_pass http://api;
+ proxy_redirect off;
+ proxy_connect_timeout 90s;
+ proxy_read_timeout 300s;
+
+ proxy_set_header X-Forwarded-Proto https;
+ proxy_set_header Host $http_host;
+ proxy_set_header X-External-Client $external_client;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ }
+}
+
+server {
+ listen 0.0.0.0:443 ssl;
+ server_name ws.uuid_prefix.your.domain;
+
+ ssl on;
+ ssl_certificate {{ keyOrDefault "arvados/ws/sslCertPath" "/var/lib/arvados/certs/selfsigned.crt" }};
+ ssl_certificate_key {{ keyOrDefault "arvados/ws/sslKeyPath" "/var/lib/arvados/certs/selfsigned.key" }};
+
+ index index.html index.htm index.php;
+
+ location / {
+ proxy_pass http://websockets;
+ proxy_redirect off;
+ proxy_connect_timeout 90s;
+ proxy_read_timeout 300s;
+
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "upgrade";
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ }
+}
+`
commit 887ca969a3fa97f2181a089ac22fac1ff1e3ed25
Author: Tom Clegg <tom at curoverse.com>
Date: Thu Mar 2 01:04:27 2017 -0500
11183: Add "setup -wait" flag
diff --git a/cmd/arvados-admin/test-debian8/Dockerfile b/cmd/arvados-admin/test-debian8/Dockerfile
index 645aec2..6886fd3 100644
--- a/cmd/arvados-admin/test-debian8/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 & arvados-admin setup && arvados-admin setup"]
+CMD ["bash", "-c", "runsvdir /etc/sv & arvados-admin setup -init-vault && arvados-admin setup -wait"]
diff --git a/cmd/arvados-admin/test-docker-compose/docker-compose.yml b/cmd/arvados-admin/test-docker-compose/docker-compose.yml
index 34e7cd4..aa5cb48 100644
--- a/cmd/arvados-admin/test-docker-compose/docker-compose.yml
+++ b/cmd/arvados-admin/test-docker-compose/docker-compose.yml
@@ -11,7 +11,7 @@ services:
- ./encrypt-key.txt:/var/lib/arvados/encrypt-key.txt:ro
- ./master-token.txt:/var/lib/arvados/master-token.txt:ro
- vault:/var/lib/arvados/vault
- command: ["bash", "-c", "runsvdir /etc/sv & arvados-admin setup -unseal=true -init-vault=true && wait"]
+ command: ["bash", "-c", "runsvdir /etc/sv & arvados-admin setup -init-vault=true -wait"]
sys1:
build: ../test-debian8
cap_add:
@@ -23,7 +23,7 @@ services:
- ./encrypt-key.txt:/var/lib/arvados/encrypt-key.txt:ro
- ./master-token.txt:/var/lib/arvados/master-token.txt:ro
- vault:/var/lib/arvados/vault
- command: ["bash", "-c", "runsvdir /etc/sv & arvados-admin setup -unseal=true && wait"]
+ command: ["bash", "-c", "runsvdir /etc/sv & arvados-admin setup -wait"]
sys2:
build: ../test-debian8
cap_add:
@@ -35,6 +35,6 @@ services:
- ./encrypt-key.txt:/var/lib/arvados/encrypt-key.txt:ro
- ./master-token.txt:/var/lib/arvados/master-token.txt:ro
- vault:/var/lib/arvados/vault
- command: ["bash", "-c", "runsvdir /etc/sv & arvados-admin setup -unseal=true && wait"]
+ command: ["bash", "-c", "runsvdir /etc/sv & arvados-admin setup -wait"]
volumes:
vault:
diff --git a/lib/agent/agent.go b/lib/agent/agent.go
index 52a3d83..2456423 100644
--- a/lib/agent/agent.go
+++ b/lib/agent/agent.go
@@ -91,6 +91,7 @@ func Command() *Agent {
DataDir: "/var/lib/arvados",
UsrDir: "/usr/local/arvados",
RunitSvDir: "/etc/sv",
+ Unseal: true,
}
}
diff --git a/lib/setup/setup.go b/lib/setup/setup.go
index 379ccb2..25c4d25 100644
--- a/lib/setup/setup.go
+++ b/lib/setup/setup.go
@@ -5,6 +5,7 @@ import (
"fmt"
"log"
"os"
+ "time"
"git.curoverse.com/arvados.git/lib/agent"
"git.curoverse.com/arvados.git/sdk/go/config"
@@ -29,6 +30,7 @@ type Setup struct {
InitVault bool
LANHost string
PreloadDir string
+ Wait bool
encryptKey string
masterToken string
@@ -40,6 +42,7 @@ func (s *Setup) ParseFlags(args []string) error {
fs.StringVar(&s.ClusterID, "cluster-id", s.ClusterID, "five-character cluster ID")
fs.BoolVar(&s.InitVault, "init-vault", s.InitVault, "initialize the vault if needed")
fs.BoolVar(&s.Unseal, "unseal", s.Unseal, "unseal the vault automatically")
+ fs.BoolVar(&s.Wait, "wait", s.Wait, "wait for all nodes to come up before exiting")
return fs.Parse(args)
}
@@ -61,6 +64,45 @@ func (s *Setup) Run() error {
return err
}
}
+
+ wait := 2 * time.Second
+ for ok := false; s.Wait && !ok; time.Sleep(wait) {
+ cc, err := s.consulMaster()
+ if err != nil {
+ log.Printf("setup: consulMaster(): %s", err)
+ continue
+ }
+ ok = true
+ svcs, _, err := cc.Catalog().Services(nil)
+ if err != nil {
+ log.Printf("setup: consul.Catalog().Services(): %s", err)
+ continue
+ }
+ for svc := range svcs {
+ checks, _, err := cc.Health().Checks(svc, nil)
+ if err != nil {
+ log.Printf("setup: consul.Health().Checks(%q): %s", svc, err)
+ continue
+ }
+
+ for _, check := range checks {
+ if check.Status != "passing" {
+ log.Printf("waiting for node %q service %q check %q state %q", check.Node, check.ServiceName, check.CheckID, check.Status)
+ ok = false
+ }
+ }
+ }
+ if ok {
+ log.Printf("All services are passing: %+v", svcs)
+ // Wait to ensure any other "setup -wait"
+ // processes have a chance to see the
+ // all-passing state before we return (if this
+ // is a test or image-building scenario, the
+ // whole system might shut down and stop
+ // passing as soon as we return).
+ time.Sleep(2 * wait)
+ }
+ }
return nil
}
commit 1883fbbdc269fa0bdf3099984160e02421bc94b1
Author: Tom Clegg <tom at curoverse.com>
Date: Tue Feb 28 15:52:18 2017 -0500
11183: Add "arvados-admin setup"
diff --git a/build/package-build-dockerfiles/debian8/Dockerfile b/build/package-build-dockerfiles/debian8/Dockerfile
index d4e77c9..36bba41 100644
--- a/build/package-build-dockerfiles/debian8/Dockerfile
+++ b/build/package-build-dockerfiles/debian8/Dockerfile
@@ -2,7 +2,7 @@ FROM debian:jessie
MAINTAINER Ward Vandewege <ward at curoverse.com>
# Install dependencies and set up system.
-RUN /usr/bin/apt-get update && /usr/bin/apt-get install -q -y python2.7-dev python3 python-setuptools python3-setuptools libcurl4-gnutls-dev curl git procps libattr1-dev libfuse-dev libgnutls28-dev libpq-dev python-pip unzip
+RUN apt-get update && apt-get install -q -y python2.7-dev python3 python-setuptools python3-setuptools libcurl4-gnutls-dev curl git procps libattr1-dev libfuse-dev libgnutls28-dev libpq-dev python-pip unzip && apt-get clean
# Install RVM
RUN gpg --keyserver pool.sks-keyservers.net --recv-keys D39DC0E3 && \
diff --git a/build/package-build-dockerfiles/ubuntu1204/Dockerfile b/build/package-build-dockerfiles/ubuntu1204/Dockerfile
index daeabc9..3a03b9a 100644
--- a/build/package-build-dockerfiles/ubuntu1204/Dockerfile
+++ b/build/package-build-dockerfiles/ubuntu1204/Dockerfile
@@ -2,7 +2,7 @@ FROM ubuntu:precise
MAINTAINER Ward Vandewege <ward at curoverse.com>
# Install dependencies and set up system.
-RUN /usr/bin/apt-get update && /usr/bin/apt-get install -q -y python2.7-dev python3 python-setuptools python3-setuptools libcurl4-gnutls-dev curl git libattr1-dev libfuse-dev libpq-dev python-pip build-essential unzip
+RUN apt-get update && apt-get install -q -y python2.7-dev python3 python-setuptools python3-setuptools libcurl4-gnutls-dev curl git libattr1-dev libfuse-dev libpq-dev python-pip build-essential unzip && apt-get clean
# Install RVM
RUN gpg --keyserver pool.sks-keyservers.net --recv-keys D39DC0E3 && \
diff --git a/build/package-build-dockerfiles/ubuntu1404/Dockerfile b/build/package-build-dockerfiles/ubuntu1404/Dockerfile
index aa92ad2..13e9bc6 100644
--- a/build/package-build-dockerfiles/ubuntu1404/Dockerfile
+++ b/build/package-build-dockerfiles/ubuntu1404/Dockerfile
@@ -1,8 +1,8 @@
FROM ubuntu:trusty
-MAINTAINER Brett Smith <brett at curoverse.com>
+MAINTAINER Ward Vandewege <ward at curoverse.com>
# Install dependencies and set up system.
-RUN /usr/bin/apt-get update && /usr/bin/apt-get install -q -y python2.7-dev python3 python-setuptools python3-setuptools libcurl4-gnutls-dev curl git libattr1-dev libfuse-dev libpq-dev python-pip unzip
+RUN apt-get update && apt-get install -q -y python2.7-dev python3 python-setuptools python3-setuptools libcurl4-gnutls-dev curl git libattr1-dev libfuse-dev libpq-dev python-pip unzip && apt-get clean
# Install RVM
RUN gpg --keyserver pool.sks-keyservers.net --recv-keys D39DC0E3 && \
diff --git a/build/package-build-dockerfiles/ubuntu1604/Dockerfile b/build/package-build-dockerfiles/ubuntu1604/Dockerfile
index fec55e6..d85e8b2 100644
--- a/build/package-build-dockerfiles/ubuntu1604/Dockerfile
+++ b/build/package-build-dockerfiles/ubuntu1604/Dockerfile
@@ -2,7 +2,7 @@ FROM ubuntu:xenial
MAINTAINER Ward Vandewege <ward at curoverse.com>
# Install dependencies and set up system.
-RUN /usr/bin/apt-get update && /usr/bin/apt-get install -q -y python2.7-dev python3 python-setuptools python3-setuptools libcurl4-gnutls-dev libgnutls-dev curl git libattr1-dev libfuse-dev libpq-dev python-pip unzip
+RUN apt-get update && apt-get install -q -y python2.7-dev python3 python-setuptools python3-setuptools libcurl4-gnutls-dev libgnutls-dev curl git libattr1-dev libfuse-dev libpq-dev python-pip unzip && apt-get clean
# Install RVM
RUN gpg --keyserver pool.sks-keyservers.net --recv-keys D39DC0E3 && \
diff --git a/build/run-build-packages-all-targets.sh b/build/run-build-packages-all-targets.sh
index a4dd9a6..2d16147 100755
--- a/build/run-build-packages-all-targets.sh
+++ b/build/run-build-packages-all-targets.sh
@@ -38,7 +38,7 @@ fi
set -e
PARSEDOPTS=$(getopt --name "$0" --longoptions \
- help,test-packages,debug,command:,only-test: \
+ help,test-packages,debug,command:,only-test:,only-build: \
-- "" "$@")
if [ $? -ne 0 ]; then
exit 1
@@ -66,6 +66,9 @@ while [ $# -gt 0 ]; do
--test-packages)
TEST_PACKAGES="--test-packages"
;;
+ --only-build)
+ ONLY_BUILD="$1 $2"; shift
+ ;;
--only-test)
ONLY_TEST="$1 $2"; shift
;;
@@ -84,7 +87,7 @@ cd $(dirname $0)
FINAL_EXITCODE=0
for dockerfile_path in $(find -name Dockerfile | grep package-build-dockerfiles); do
- if ./run-build-packages-one-target.sh --target "$(basename $(dirname "$dockerfile_path"))" --command "$COMMAND" $DEBUG $TEST_PACKAGES $ONLY_TEST ; then
+ if ./run-build-packages-one-target.sh --target "$(basename $(dirname "$dockerfile_path"))" --command "$COMMAND" $DEBUG $TEST_PACKAGES $ONLY_TEST $ONLY_BUILD ; then
true
else
FINAL_EXITCODE=$?
diff --git a/build/run-build-packages-one-target.sh b/build/run-build-packages-one-target.sh
index 685ca51..78adfbb 100755
--- a/build/run-build-packages-one-target.sh
+++ b/build/run-build-packages-one-target.sh
@@ -129,6 +129,7 @@ popd
if test -z "$packages" ; then
packages="arvados-api-server
+ arvados-admin
arvados-docker-cleaner
arvados-git-httpd
arvados-node-manager
diff --git a/build/run-build-packages.sh b/build/run-build-packages.sh
index 777cd3c..5c6875d 100755
--- a/build/run-build-packages.sh
+++ b/build/run-build-packages.sh
@@ -338,6 +338,8 @@ package_go_binary sdk/go/crunchrunner crunchrunner \
"Crunchrunner executes a command inside a container and uploads the output"
package_go_binary services/arv-git-httpd arvados-git-httpd \
"Provide authenticated http access to Arvados-hosted git repositories"
+package_go_binary cmd/arvados-admin arvados-admin \
+ "Arvados cluster administration tool"
package_go_binary services/crunch-dispatch-local crunch-dispatch-local \
"Dispatch Crunch containers on the local system"
package_go_binary services/crunch-dispatch-slurm crunch-dispatch-slurm \
diff --git a/build/run-library.sh b/build/run-library.sh
index 3d61962..4f259f9 100755
--- a/build/run-library.sh
+++ b/build/run-library.sh
@@ -114,6 +114,8 @@ package_go_binary() {
fi
fi
+ go generate || return 1
+
cd $WORKSPACE/packages/$TARGET
test_package_presence $prog $version go
diff --git a/build/run-tests.sh b/build/run-tests.sh
index afaa834..e2e6f34 100755
--- a/build/run-tests.sh
+++ b/build/run-tests.sh
@@ -101,6 +101,10 @@ tools/crunchstat-summary
tools/keep-exercise
tools/keep-rsync
tools/keep-block-check
+lib/agent
+lib/crunchstat
+lib/setup
+cmd/arvados-admin
(*) apps/workbench is shorthand for apps/workbench_units +
apps/workbench_functionals + apps/workbench_integration
@@ -198,6 +202,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() {
@@ -547,12 +554,14 @@ do_test_once() {
then
covername="coverage-$(echo "$1" | sed -e 's/\//_/g')"
coverflags=("-covermode=count" "-coverprofile=$WORKSPACE/tmp/.$covername.tmp")
+ gopkgpath="git.curoverse.com/arvados.git/$1"
# We do "go get -t" here to catch compilation errors
# before trying "go test". Otherwise, coverage-reporting
# mode makes Go show the wrong line numbers when reporting
# compilation errors.
go get -t "git.curoverse.com/arvados.git/$1" && \
cd "$WORKSPACE/$1" && \
+ go generate && \
[[ -z "$(gofmt -e -d . | tee /dev/stderr)" ]] && \
if [[ -n "${testargs[$1]}" ]]
then
@@ -562,7 +571,7 @@ do_test_once() {
else
# The above form gets verbose even when testargs is
# empty, so use this form in such cases:
- go test ${short:+-short} ${coverflags[@]} "git.curoverse.com/arvados.git/$1"
+ go test ${short:+-short} ${coverflags[@]} .
fi
result=${result:-$?}
if [[ -f "$WORKSPACE/tmp/.$covername.tmp" ]]
@@ -594,6 +603,9 @@ do_test_once() {
else
"test_$1"
fi
+ if [[ -e "${WORKSPACE}/${1}/package.json" ]]; then
+ cd "${WORKSPACE}/${1}" && npm test || result=1
+ fi
result=${result:-$?}
checkexit $result "$1 tests"
title "End of $1 tests (`timer`)"
@@ -611,9 +623,15 @@ do_install() {
do_install_once() {
title "Running $1 install"
timer_reset
+ cd "${WORKSPACE}/${1}" || return 1
+ if [[ -e "${WORKSPACE}/${1}/package.json" ]]; then
+ npm install || return 1
+ fi
if [[ "$2" == "go" ]]
then
- go get -t "git.curoverse.com/arvados.git/$1"
+ go get -d -t "git.curoverse.com/arvados.git/$1" \
+ && go generate \
+ && go get "git.curoverse.com/arvados.git/$1"
elif [[ "$2" == "pip" ]]
then
# $3 can name a path directory for us to use, including trailing
@@ -628,8 +646,7 @@ do_install_once() {
# install" ensures that the dependencies are met, the second "pip
# install" ensures that we've actually installed the local package
# we just built.
- cd "$WORKSPACE/$1" \
- && "${3}python" setup.py sdist rotate --keep=1 --match .tar.gz \
+ "${3}python" setup.py sdist rotate --keep=1 --match .tar.gz \
&& cd "$WORKSPACE" \
&& "${3}pip" install --quiet "$WORKSPACE/$1/dist"/*.tar.gz \
&& "${3}pip" install --quiet --no-deps --ignore-installed "$WORKSPACE/$1/dist"/*.tar.gz
@@ -779,7 +796,9 @@ gostuff=(
sdk/go/streamer
sdk/go/crunchrunner
sdk/go/stats
+ lib/agent
lib/crunchstat
+ lib/setup
services/arv-git-httpd
services/crunchstat
services/keep-web
@@ -791,9 +810,11 @@ gostuff=(
services/crunch-dispatch-slurm
services/crunch-run
services/ws
+ services/boot
tools/keep-block-check
tools/keep-exercise
tools/keep-rsync
+ cmd/arvados-admin
)
for g in "${gostuff[@]}"
do
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
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/cmd/arvados-admin/setup_docker_compose_test.go b/cmd/arvados-admin/setup_docker_compose_test.go
new file mode 100644
index 0000000..e88dc16
--- /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", "-v"},
+ {"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-debian8/Dockerfile b/cmd/arvados-admin/test-debian8/Dockerfile
new file mode 100644
index 0000000..645aec2
--- /dev/null
+++ b/cmd/arvados-admin/test-debian8/Dockerfile
@@ -0,0 +1,14 @@
+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 locales nginx postgresql 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"]
+
+RUN DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends ca-certificates locales nginx postgresql runit
+
+CMD ["bash", "-c", "runsvdir /etc/sv & arvados-admin setup && arvados-admin setup"]
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..34e7cd4
--- /dev/null
+++ b/cmd/arvados-admin/test-docker-compose/docker-compose.yml
@@ -0,0 +1,40 @@
+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
+ - vault:/var/lib/arvados/vault
+ command: ["bash", "-c", "runsvdir /etc/sv & arvados-admin setup -unseal=true -init-vault=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
+ - vault:/var/lib/arvados/vault
+ command: ["bash", "-c", "runsvdir /etc/sv & arvados-admin setup -unseal=true && 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
+ - vault:/var/lib/arvados/vault
+ command: ["bash", "-c", "runsvdir /etc/sv & arvados-admin setup -unseal=true && wait"]
+volumes:
+ vault:
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/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..9cc2f29
--- /dev/null
+++ b/lib/setup/consul.go
@@ -0,0 +1,167 @@
+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 := path.Join(s.UsrDir, "bin", "consul")
+ err := (&download{
+ URL: "https://releases.hashicorp.com/consul/0.7.5/consul_0.7.5_linux_amd64.zip",
+ Dest: prog,
+ Size: 36003713,
+ Mode: 0755,
+ PreloadDir: s.PreloadDir,
+ }).install()
+ if err != nil {
+ return err
+ }
+
+ if err := s.consulInit(); err != nil {
+ return err
+ }
+ if s.consulCheck() == nil {
+ return nil
+ }
+
+ dataDir := path.Join(s.DataDir, "consul")
+ if err := os.MkdirAll(dataDir, 0700); err != nil {
+ return err
+ }
+
+ cf := path.Join(s.DataDir, "consul-config.json")
+ {
+ c := map[string]interface{}{
+ "acl_agent_token": s.masterToken,
+ "acl_datacenter": s.ClusterID,
+ "acl_default_policy": "deny",
+ "acl_enforce_version_8": true,
+ "acl_master_token": s.masterToken,
+ "bootstrap_expect": len(s.ControlHosts),
+ "client_addr": "0.0.0.0",
+ "data_dir": dataDir,
+ "datacenter": s.ClusterID,
+ "encrypt": s.encryptKey,
+ "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,
+ },
+ }
+ err = atomicWriteJSON(cf, c, 0600)
+ if err != nil {
+ return err
+ }
+ }
+
+ err = s.installService(daemon{
+ name: "arvados-consul",
+ prog: prog,
+ 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 {
+ 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()
+ if err != nil {
+ return fmt.Errorf("consul join: %s", err)
+ }
+ }
+ return nil
+}
+
+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) consulInit() error {
+ prog := path.Join(s.UsrDir, "bin", "consul")
+ 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
+ }
+ err = atomicWriteFile(keyPath, key, 0400)
+ }
+ if err != nil {
+ return err
+ }
+ s.encryptKey = strings.TrimSpace(string(key))
+
+ tokPath := path.Join(s.DataDir, "master-token.txt")
+ if tok, err := ioutil.ReadFile(tokPath); err != nil {
+ s.masterToken = generateToken()
+ err = atomicWriteFile(tokPath, []byte(s.masterToken), 0600)
+ if err != nil {
+ return err
+ }
+ } else {
+ s.masterToken = string(tok)
+ }
+ return nil
+}
+
+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..379ccb2
--- /dev/null
+++ b/lib/setup/setup.go
@@ -0,0 +1,79 @@
+package setup
+
+import (
+ "flag"
+ "fmt"
+ "log"
+ "os"
+
+ "git.curoverse.com/arvados.git/lib/agent"
+ "git.curoverse.com/arvados.git/sdk/go/config"
+ vaultAPI "github.com/hashicorp/vault/api"
+)
+
+func Command() *Setup {
+ hostname, err := os.Hostname()
+ if err != nil {
+ log.Fatalf("hostname: %s", err)
+ }
+
+ return &Setup{
+ Agent: agent.Command(),
+ LANHost: hostname,
+ PreloadDir: "/var/cache/arvados",
+ }
+}
+
+type Setup struct {
+ *agent.Agent
+ InitVault bool
+ LANHost string
+ PreloadDir string
+
+ encryptKey string
+ masterToken string
+ vaultCfg *vaultAPI.Config
+}
+
+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.InitVault, "init-vault", s.InitVault, "initialize the vault if needed")
+ 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,
+ s.installVault,
+ } {
+ 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/vault.go b/lib/setup/vault.go
new file mode 100644
index 0000000..8443764
--- /dev/null
+++ b/lib/setup/vault.go
@@ -0,0 +1,244 @@
+package setup
+
+import (
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "path"
+ "strings"
+ "time"
+
+ consulAPI "github.com/hashicorp/consul/api"
+ vaultAPI "github.com/hashicorp/vault/api"
+)
+
+func (s *Setup) installVault() error {
+ if err := s.consulInit(); err != nil {
+ return err
+ }
+ if err := s.vaultInit(); err != nil {
+ return err
+ }
+ if s.vaultCheck() == nil {
+ return nil
+ }
+
+ log.Printf("download & install vault")
+ bin := s.UsrDir + "/bin/vault"
+ err := (&download{
+ URL: "https://releases.hashicorp.com/vault/0.6.4/vault_0.6.4_linux_amd64.zip",
+ Dest: bin,
+ Size: 52518022,
+ Mode: 0755,
+ PreloadDir: s.PreloadDir,
+ }).install()
+ if err != nil {
+ return err
+ }
+
+ haAddr := fmt.Sprintf("http://%s:%d", s.LANHost, s.Ports.VaultServer)
+
+ cfgPath := path.Join(s.DataDir, "vault.hcl")
+ err = atomicWriteFile(cfgPath, []byte(fmt.Sprintf(`
+ cluster_name = %q
+ backend "consul" {
+ address = "127.0.0.1:%d"
+ redirect_addr = %q
+ cluster_addr = %q
+ path = %q
+ token = %q
+ }
+ listener "tcp" {
+ address = %q
+ tls_disable = 1
+ }
+ `,
+ s.ClusterID,
+ s.Ports.ConsulHTTP,
+ haAddr,
+ haAddr,
+ "vault-"+s.ClusterID+"/",
+ s.masterToken,
+ fmt.Sprintf("%s:%d", s.LANHost, s.Ports.VaultServer),
+ )), 0600)
+ if err != nil {
+ return err
+ }
+
+ args := []string{"server", "-config=" + cfgPath}
+ err = s.installService(daemon{
+ name: "arvados-vault",
+ prog: bin,
+ args: args,
+ noRegister: true,
+ })
+ if err != nil {
+ return err
+ }
+
+ if !s.Unseal {
+ return nil
+ }
+
+ if err := s.vaultBootstrap(); err != nil {
+ return err
+ }
+ return waitCheck(30*time.Second, s.vaultCheck)
+}
+
+func (s *Setup) vaultBootstrap() error {
+ var vault *vaultAPI.Client
+ var initialized bool
+ resp := &vaultAPI.InitResponse{}
+ if err := waitCheck(time.Minute, func() error {
+ var err error
+ vault, err = s.vaultClient()
+ if err != nil {
+ return err
+ }
+ initialized, err = vault.Sys().InitStatus()
+ if err != nil {
+ return err
+ } else if s.InitVault {
+ return nil
+ }
+ _, err = os.Stat(path.Join(s.DataDir, "vault", "mgmt-token.txt"))
+ if err != nil {
+ log.Print("vault is not initialized, waiting")
+ return fmt.Errorf("vault is not initialized")
+ }
+ return nil
+ }); err != nil {
+ return err
+ } else if !initialized && s.InitVault {
+ resp, err = vault.Sys().Init(&vaultAPI.InitRequest{
+ SecretShares: 5,
+ SecretThreshold: 3,
+ })
+ if err != nil {
+ return fmt.Errorf("vault-init: %s", err)
+ }
+ atomicWriteJSON(path.Join(s.DataDir, "vault", "keys.json"), resp, 0400)
+ atomicWriteFile(path.Join(s.DataDir, "vault", "root-token.txt"), []byte(resp.RootToken), 0400)
+ } else {
+ j, err := ioutil.ReadFile(path.Join(s.DataDir, "vault", "keys.json"))
+ if err != nil {
+ return err
+ }
+ err = json.Unmarshal(j, resp)
+ if err != nil {
+ return err
+ }
+ }
+ vault.SetToken(resp.RootToken)
+
+ ok := false
+ for _, key := range resp.Keys {
+ resp, err := vault.Sys().Unseal(key)
+ if err != nil {
+ log.Printf("error: unseal: %s", err)
+ continue
+ }
+ if !resp.Sealed {
+ log.Printf("unseal successful")
+ ok = true
+ break
+ }
+ }
+ if !ok {
+ return fmt.Errorf("vault unseal failed!")
+ }
+
+ if s.InitVault {
+ // Use master token to create a management token
+ master, err := s.consulMaster()
+ if err != nil {
+ return err
+ }
+ mgmtToken, _, err := master.ACL().Create(&consulAPI.ACLEntry{Name: "vault", Type: "management"}, nil)
+ if err != nil {
+ return err
+ }
+
+ // Mount+configure consul backend
+ alreadyMounted := false
+ if err = waitCheck(30*time.Second, func() error {
+ // Typically this first fails "500 node not active but
+ // active node not found" but then succeeds.
+ err := vault.Sys().Mount("consul", &vaultAPI.MountInput{Type: "consul"})
+ if err != nil && strings.Contains(err.Error(), "existing mount at consul") {
+ alreadyMounted = true
+ err = nil
+ }
+ return err
+ }); err != nil {
+ return err
+ }
+ _, err = vault.Logical().Write("consul/config/access", map[string]interface{}{
+ "address": fmt.Sprintf("127.0.0.1:%d", s.Ports.ConsulHTTP),
+ "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" }`)),
+ })
+ if err != nil {
+ return err
+ }
+
+ // Write mgmtToken after bootstrapping is done. If
+ // other nodes share our vault data dir, this is their
+ // signal to try unseal.
+ if err = atomicWriteFile(path.Join(s.DataDir, "vault", "mgmt-token.txt"), []byte(mgmtToken), 0400); err != nil {
+ return err
+ }
+ }
+
+ // Test: 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 (s *Setup) vaultInit() error {
+ s.vaultCfg = vaultAPI.DefaultConfig()
+ s.vaultCfg.Address = fmt.Sprintf("http://%s:%d", s.LANHost, s.Ports.VaultServer)
+ return nil
+}
+
+func (s *Setup) vaultClient() (*vaultAPI.Client, error) {
+ return vaultAPI.NewClient(s.vaultCfg)
+}
+
+func (s *Setup) vaultCheck() error {
+ vault, err := s.vaultClient()
+ if err != nil {
+ return err
+ }
+ token, err := ioutil.ReadFile(path.Join(s.DataDir, "vault", "root-token.txt"))
+ if err != nil {
+ return err
+ }
+ vault.SetToken(string(token))
+ if init, err := vault.Sys().InitStatus(); err != nil {
+ return err
+ } else if !init {
+ return fmt.Errorf("vault is not initialized")
+ }
+ return nil
+}
diff --git a/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)
+}
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list