├── .github ├── dependabot.yml └── workflows │ ├── codeql-analysis.yml │ └── dockerimage.yml ├── .gitignore ├── .tern-project ├── .travis.yml ├── .vscode ├── spellchecker.json └── tasks.json ├── API.md ├── CODE_OF_CONDUCT.md ├── DEVELOPMENT.md ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── Vagrantfile ├── backend ├── Makefile ├── config │ ├── config.go │ └── config_test.go ├── connection.go ├── consul │ ├── catalog │ │ └── datacenters.go │ ├── helper │ │ └── helper.go │ ├── kv │ │ ├── delete.go │ │ ├── delete_tree.go │ │ ├── info.go │ │ ├── list.go │ │ └── set.go │ ├── nodes │ │ ├── info.go │ │ ├── list.go │ │ └── shared_structs.go │ ├── services │ │ ├── deregister.go │ │ ├── deregister_check.go │ │ ├── info.go │ │ └── list.go │ └── sessions │ │ ├── destroy.go │ │ ├── info.go │ │ └── list.go ├── go.mod ├── go.sum ├── handler_consul.go ├── handler_nomad_http.go ├── handler_nomad_ws.go ├── handler_shared.go ├── handler_status.go ├── main.go ├── nomad │ ├── allocations │ │ ├── dir.go │ │ ├── file.go │ │ ├── health.go │ │ ├── helper.go │ │ ├── info.go │ │ ├── list.go │ │ └── stats.go │ ├── cluster │ │ ├── evaluate_all_jobs.go │ │ ├── force_gc.go │ │ ├── reconcile_summaries.go │ │ ├── regions.go │ │ └── stats.go │ ├── deployments │ │ ├── allocations.go │ │ ├── change_status.go │ │ ├── info.go │ │ └── list.go │ ├── evaluations │ │ ├── info.go │ │ └── list.go │ ├── helper │ │ └── helper.go │ ├── jobs │ │ ├── allocations.go │ │ ├── deployments.go │ │ ├── force_evaluate.go │ │ ├── health.go │ │ ├── helpers.go │ │ ├── info.go │ │ ├── list.go │ │ ├── periodic_force.go │ │ ├── restart.go │ │ ├── rolling_restart.go │ │ ├── scale.go │ │ ├── stop.go │ │ ├── submit.go │ │ └── versions.go │ ├── members │ │ ├── info.go │ │ └── list.go │ └── nodes │ │ ├── drain.go │ │ ├── info.go │ │ ├── list.go │ │ ├── remove.go │ │ └── stats.go ├── structs │ └── actions.go └── subscriber │ ├── functions.go │ └── manager.go ├── build_dev.sh ├── docs └── authentication_example.md ├── example-jobs ├── hashi-ui-docker.nomad └── hashi-ui-exec.nomad ├── frontend ├── .editorconfig ├── .eslintrc.js ├── Makefile ├── assets │ ├── data-table.css │ ├── hashi-ui.css │ ├── hashi-ui.scss │ └── img │ │ ├── consul-medium.png │ │ ├── consul-small.png │ │ ├── consul.png │ │ ├── favicon.png │ │ └── nomad.png ├── index.html.ejs ├── package.json ├── src │ ├── components │ │ ├── AllocationConsulHealth │ │ │ └── AllocationConsulHealth.js │ │ ├── AllocationConsulHealthCell │ │ │ └── AllocationConsulHealthCell.js │ │ ├── AllocationDistribution │ │ │ └── AllocationDistribution.js │ │ ├── AllocationFiles │ │ │ └── AllocationFiles.js │ │ ├── AllocationInfo │ │ │ └── AllocationInfo.js │ │ ├── AllocationLink │ │ │ └── AllocationLink.js │ │ ├── AllocationList │ │ │ └── AllocationList.js │ │ ├── AllocationRaw │ │ │ └── AllocationRaw.js │ │ ├── AllocationStats │ │ │ └── AllocationStats.js │ │ ├── AllocationStatsCell │ │ │ └── AllocationStatsCell.js │ │ ├── AllocationStatusIcon │ │ │ └── AllocationStatusIcon.js │ │ ├── AllocationTopbar │ │ │ └── AllocationTopbar.js │ │ ├── ClientActionMenu │ │ │ └── ClientActionMenu.js │ │ ├── ClientAllocations │ │ │ └── ClientAllocations.js │ │ ├── ClientEvaluations │ │ │ └── ClientEvaluations.js │ │ ├── ClientInfo │ │ │ └── ClientInfo.js │ │ ├── ClientLink │ │ │ └── ClientLink.js │ │ ├── ClientRaw │ │ │ └── ClientRaw.js │ │ ├── ClientStats │ │ │ └── ClientStats.js │ │ ├── ClientTopbar │ │ │ └── ClientTopbar.js │ │ ├── ClusterEvents │ │ │ └── ClusterEvents.js │ │ ├── ClusterStatistics │ │ │ └── ClusterStatistics.js │ │ ├── ConstraintRow │ │ │ └── ConstraintRow.js │ │ ├── ConstraintTable │ │ │ └── ConstraintTable.js │ │ ├── ConsulMainNav │ │ │ └── ConsulMainNav.js │ │ ├── ConsulTopbar │ │ │ ├── ConsulTopbar.js │ │ │ └── ConsulTopbar.scss │ │ ├── DeploymentAction │ │ │ └── DeploymentAction.js │ │ ├── DeploymentAllocations │ │ │ └── DeploymentAllocations.js │ │ ├── DeploymentDistribution │ │ │ └── DeploymentDistribution.js │ │ ├── DeploymentInfo │ │ │ └── DeploymentInfo.js │ │ ├── DeploymentLink │ │ │ └── DeploymentLink.js │ │ ├── DeploymentList │ │ │ └── DeploymentList.js │ │ ├── DeploymentRaw │ │ │ └── DeploymentRaw.js │ │ ├── DeploymentStatusFilter │ │ │ └── DeploymentStatusFilter.js │ │ ├── DeploymentTopbar │ │ │ └── DeploymentTopbar.js │ │ ├── DiskUtilizationTable │ │ │ └── DiskUtilizationTable.js │ │ ├── EvaluationAllocations │ │ │ └── EvaluationAllocations.js │ │ ├── EvaluationInfo │ │ │ └── EvaluationInfo.js │ │ ├── EvaluationLink │ │ │ └── EvaluationLink.js │ │ ├── EvaluationList │ │ │ └── EvaluationList.js │ │ ├── EvaluationRaw │ │ │ └── EvaluationRaw.js │ │ ├── EvaluationTopbar │ │ │ └── EvaluationTopbar.js │ │ ├── FilterFreetext │ │ │ └── FilterFreetext.js │ │ ├── FormatBoolean │ │ │ └── FormatBoolean.js │ │ ├── FormatTime │ │ │ └── FormatTime.js │ │ ├── JobActionEvaluate │ │ │ └── JobActionEvaluate.js │ │ ├── JobActionMenu │ │ │ └── JobActionMenu.js │ │ ├── JobActionRollingRestart │ │ │ └── JobActionRollingRestart.js │ │ ├── JobActionStop │ │ │ └── JobActionStop.js │ │ ├── JobActionStopStart │ │ │ └── JobActionStopStart.js │ │ ├── JobAllocations │ │ │ └── JobAllocations.js │ │ ├── JobChildren │ │ │ └── JobChildren.js │ │ ├── JobDeployments │ │ │ └── JobDeployments.js │ │ ├── JobEditRawJSON │ │ │ └── JobEditRawJSON.js │ │ ├── JobEvaluations │ │ │ └── JobEvaluations.js │ │ ├── JobHealth │ │ │ └── JobHealth.js │ │ ├── JobInfo │ │ │ └── JobInfo.js │ │ ├── JobLink │ │ │ └── JobLink.js │ │ ├── JobList │ │ │ └── JobList.js │ │ ├── JobRaw │ │ │ └── JobRaw.js │ │ ├── JobStatusFilter │ │ │ └── JobStatusFilter.js │ │ ├── JobTaskGroupActionRestart │ │ │ └── JobTaskGroupActionRestart.js │ │ ├── JobTaskGroupActionScale │ │ │ └── JobTaskGroupActionScale.js │ │ ├── JobTaskGroupActionStop │ │ │ └── JobTaskGroupActionStop.js │ │ ├── JobTaskGroups │ │ │ └── JobTaskGroups.js │ │ ├── JobTasks │ │ │ └── JobTasks.js │ │ ├── JobTopbar │ │ │ └── JobTopbar.js │ │ ├── JobTypeFilter │ │ │ └── JobTypeFilter.js │ │ ├── MetaPayload │ │ │ └── MetaPayload.js │ │ ├── NodeStatus │ │ │ └── NodeStatus.js │ │ ├── NomadMainNav │ │ │ └── NomadMainNav.js │ │ ├── NomadTopbar │ │ │ ├── NomadTopbar.js │ │ │ └── NomadTopbar.scss │ │ ├── NotificationsBar │ │ │ └── NotificationsBar.js │ │ ├── PortBindings │ │ │ └── PortBindings.js │ │ ├── Progressbar │ │ │ └── Progressbar.js │ │ ├── RawJson │ │ │ └── RawJson.js │ │ ├── SelectField │ │ │ └── SelectField.js │ │ ├── ServerInfo │ │ │ └── ServerInfo.js │ │ ├── ServerLink │ │ │ └── ServerLink.js │ │ ├── ServerRaw │ │ │ └── ServerRaw.js │ │ ├── ServerTopbar │ │ │ └── ServerTopbar.js │ │ ├── Table │ │ │ ├── Table.js │ │ │ ├── TableBody.js │ │ │ ├── TableFooter.js │ │ │ ├── TableHeader.js │ │ │ ├── TableHeaderColumn.js │ │ │ ├── TableRow.js │ │ │ ├── TableRowColumn.js │ │ │ └── index.js │ │ ├── TableHelper │ │ │ └── TableHelper.js │ │ ├── UtilizationAreaChart │ │ │ └── UtilizationAreaChart.js │ │ ├── UtilizationPieChart │ │ │ └── UtilizationPieChart.js │ │ ├── app.js │ │ └── error_app.js │ ├── config.js │ ├── containers │ │ ├── allocation.js │ │ ├── allocations.js │ │ ├── client.js │ │ ├── clients.js │ │ ├── cluster.js │ │ ├── consul_kv.js │ │ ├── consul_nodes.js │ │ ├── consul_services.js │ │ ├── consul_sessions.js │ │ ├── deployment.js │ │ ├── deployments.js │ │ ├── evaluation.js │ │ ├── evaluations.js │ │ ├── job.js │ │ ├── jobs.js │ │ ├── select_consul_region.js │ │ ├── select_nomad_region.js │ │ ├── server.js │ │ ├── servers.js │ │ └── system.js │ ├── helpers │ │ └── uuid.js │ ├── history.js │ ├── main.js │ ├── reducers │ │ ├── allocation.js │ │ ├── app.js │ │ ├── cluster.js │ │ ├── consul.js │ │ ├── deployment.js │ │ ├── evaluation.js │ │ ├── filesystem.js │ │ ├── job.js │ │ ├── member.js │ │ ├── node.js │ │ ├── nomad.js │ │ ├── root.js │ │ └── utils.js │ ├── router.js │ ├── sagas │ │ └── event.js │ └── store.js ├── webpack-prod.config.js ├── webpack.config.js └── yarn.lock ├── node_modules └── .yarn-integrity ├── scripts ├── consul-acl-node │ ├── acl.hcl │ ├── config.json │ ├── install.sh │ └── start.sh ├── nginx-frontend-proxy │ ├── mime.types │ ├── site.conf │ └── start.sh ├── nomad-mutli-region-cluster │ ├── Makefile │ ├── dc-eu.hcl │ ├── dc-us.hcl │ ├── install.sh │ ├── job-eu.nomad │ ├── job-us.nomad │ └── start.sh └── traefik-proxy │ ├── README.md │ ├── config.hcl │ └── traefik-proxy.nomad ├── travis.Dockerfile ├── travis.Dockerfile.dockerignore └── yarn.lock /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: gomod 4 | directory: "/backend" 5 | schedule: 6 | interval: daily 7 | time: "04:00" 8 | open-pull-requests-limit: 10 9 | reviewers: 10 | - jippi 11 | ignore: 12 | - dependency-name: github.com/sirupsen/logrus 13 | versions: 14 | - 1.7.1 15 | - 1.8.0 16 | - 1.8.1 17 | - package-ecosystem: docker 18 | directory: "/" 19 | schedule: 20 | interval: daily 21 | time: "04:00" 22 | open-pull-requests-limit: 10 23 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ master ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ master ] 20 | schedule: 21 | - cron: '20 19 * * 2' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | 28 | strategy: 29 | fail-fast: false 30 | matrix: 31 | language: [ 'go', 'javascript' ] 32 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 33 | # Learn more: 34 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 35 | 36 | steps: 37 | - name: Checkout repository 38 | uses: actions/checkout@v2 39 | 40 | # Initializes the CodeQL tools for scanning. 41 | - name: Initialize CodeQL 42 | uses: github/codeql-action/init@v1 43 | with: 44 | languages: ${{ matrix.language }} 45 | # If you wish to specify custom queries, you can do so here or in a config file. 46 | # By default, queries listed here will override any specified in a config file. 47 | # Prefix the list here with "+" to use these queries and those in the config file. 48 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 49 | 50 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 51 | # If this step fails, then you should remove it and run the build manually (see below) 52 | - name: Autobuild 53 | uses: github/codeql-action/autobuild@v1 54 | 55 | # ℹ️ Command-line programs to run using the OS shell. 56 | # 📚 https://git.io/JvXDl 57 | 58 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 59 | # and modify them (or add more) to build your code if your project 60 | # uses a compiled language 61 | 62 | #- run: | 63 | # make bootstrap 64 | # make release 65 | 66 | - name: Perform CodeQL Analysis 67 | uses: github/codeql-action/analyze@v1 68 | -------------------------------------------------------------------------------- /.github/workflows/dockerimage.yml: -------------------------------------------------------------------------------- 1 | name: Docker Image CI 2 | 3 | on: 4 | push: 5 | branches: master 6 | schedule: 7 | - cron: 0 0 * * * 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v1 14 | - name: Build the Docker image 15 | run: docker build . --file Dockerfile --tag hashi-ui:latest 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | frontend/node_modules 2 | backend/backend 3 | backend/bindata.go 4 | 5 | .tern-port 6 | .sass-cache 7 | npm-debug.log 8 | bindata_assetfs.go 9 | dist/ 10 | 11 | # PyCharm & WebStorm 12 | .idea 13 | 14 | # Makefile 15 | build 16 | 17 | # Vagrant 18 | .vagrant 19 | 20 | .DS_Store 21 | stats.json 22 | -------------------------------------------------------------------------------- /.tern-project: -------------------------------------------------------------------------------- 1 | { 2 | "libs": [ "browser" ], 3 | "plugins": { 4 | "node": {}, 5 | "complete_strings": {}, 6 | "es_modules": {} 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.vscode/spellchecker.json: -------------------------------------------------------------------------------- 1 | { 2 | "language": "en_US", 3 | "ignoreWordsList": [ 4 | "hashi", 5 | "jippi" 6 | ], 7 | "documentTypes": [ 8 | "markdown", 9 | "latex", 10 | "plaintext" 11 | ], 12 | "ignoreRegExp": [], 13 | "ignoreFileExtensions": [], 14 | "checkInterval": 5000 15 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "command": "hclfmt", 4 | "isShellCommand": true, 5 | "isBuildCommand": true, 6 | "isWatching": true, 7 | "showOutput": "silent", 8 | "args": [ 9 | "-w", 10 | "${file}" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /API.md: -------------------------------------------------------------------------------- 1 | # HTTP API 2 | 3 | All requests need the same format in the payload: `{"type":"NOMAD_WATCH_NODES"}` 4 | 5 | Some requests all take arguments, those belong in JSON field called `payload`: `{"type":"NOMAD_WATCH_NODES", "payload": "something_here"}` 6 | 7 | ## Example 8 | 9 | `curl -i -X POST localhost:3000/api/nomad/$region -d '{"type":"NOMAD_WATCH_NODES"}'` 10 | 11 | `curl -i -X POST localhost:3000/api/nomad/$region -d '{"type":"NOMAD_WATCH_JOBS", "payload:" { "prefix": "app-"}}'` 12 | 13 | ## Nomad 14 | 15 | ### Jobs 16 | 17 | #### List 18 | 19 | List all jobs, optionally with a prefix 20 | 21 | - `type` `NOMAD_WATCH_JOBS` 22 | - `payload` optional 23 | - `prefix` optional string 24 | 25 | Example: `{"type":"NOMAD_WATCH_JOBS"}` or `{"type":"NOMAD_WATCH_JOBS", "payload:" { "prefix": "app-"}}` 26 | 27 | #### Info 28 | 29 | Show a single job information 30 | 31 | - `type` `NOMAD_WATCH_JOB` 32 | - `payload` required 33 | - `id` required string (job id) 34 | - `version` optional string (version number) 35 | 36 | Example: `{"type":"NOMAD_WATCH_JOB", "payload": {"id": "demo-app"} }` or `{"type":"NOMAD_WATCH_JOB", "payload:" {"id": "demo-app", "version": "10"} }` 37 | 38 | --- 39 | 40 | All the actions can be found in `backend/nomad/*/.go` - and the required formats can be found the the method `Key()` or `Parse()` for each method. 41 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # build-env container 2 | FROM golang:1.16.5 AS build-env 3 | 4 | ENV CGO_ENABLED=0 GO111MODULE=on GOPROXY=https://proxy.golang.org 5 | 6 | RUN apt-get update -q -y && \ 7 | apt-get install -q -y apt-transport-https ca-certificates gnupg && \ 8 | apt-key adv --fetch-keys https://dl.yarnpkg.com/debian/pubkey.gpg && \ 9 | echo "deb https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list && \ 10 | # https://github.com/yarnpkg/yarn/issues/6914 11 | curl -sL https://deb.nodesource.com/setup_10.x | bash - && \ 12 | apt-get update -q -y && \ 13 | apt-get install -q -y yarn nodejs 14 | 15 | ADD . /go/src/github.com/jippi/hashi-ui 16 | WORKDIR /go/src/github.com/jippi/hashi-ui 17 | RUN make -j rebuild 18 | 19 | # application container 20 | FROM alpine 21 | 22 | # we need ca-certificates for any external https communication 23 | RUN apk --update upgrade && \ 24 | apk add curl ca-certificates && \ 25 | update-ca-certificates && \ 26 | rm -rf /var/cache/apk/* 27 | 28 | COPY --from=build-env /go/src/github.com/jippi/hashi-ui/backend/build/hashi-ui-linux-amd64 /hashi-ui 29 | EXPOSE 3000 30 | CMD ["/hashi-ui"] 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Christian Winther 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | export DOCKER_BUILDKIT=1 2 | export CGO_ENABLED=0 3 | export GO111MODULE=on 4 | export GOPROXY=https://proxy.golang.org 5 | 6 | .PHONY: frontend 7 | frontend: 8 | @echo "=> building frontend ..." 9 | $(MAKE) -j -C frontend build 10 | 11 | .PHONY: backend 12 | backend: 13 | $(MAKE) -j -C backend build 14 | $(MAKE) -j -C backend test 15 | 16 | # Since backend will call the frontend/Makefile when need be, this target will 17 | # just trigger a pure bakcend build 18 | # 19 | .PHONY: build 20 | build: backend 21 | 22 | .PHONY: rebuild 23 | rebuild: clean 24 | $(MAKE) -j build 25 | 26 | .PHONY: install 27 | install: 28 | @echo "=> install ..." 29 | $(MAKE) -j -C backend install 30 | $(MAKE) -j -C frontend install 31 | 32 | .PHONY: clean 33 | clean: 34 | @echo "=> cleaning ..." 35 | $(MAKE) -j -C backend clean 36 | $(MAKE) -j -C frontend clean 37 | 38 | PHONY: dist-clean 39 | dist-clean: 40 | @echo "=> dist-cleaning ..." 41 | $(MAKE) -j -C frontend dist-clean 42 | 43 | .PHONY: docker 44 | docker: 45 | @echo "=> build and push Docker image ..." 46 | docker build -f travis.Dockerfile -t jippi/hashi-ui:$(COMMIT) . 47 | docker tag jippi/hashi-ui:$(COMMIT) jippi/hashi-ui:$(TAG) 48 | docker push jippi/hashi-ui:$(TAG) 49 | 50 | .PHONY: docker-dev 51 | docker-dev: 52 | @echo "=> build Docker image ..." 53 | docker build -f travis.Dockerfile -t jippi/hashi-ui:local-dev . 54 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | $script = <