mirror of
https://github.com/OliveTin/OliveTin
synced 2025-12-12 00:55:34 +00:00
Compare commits
121 Commits
2022-01-06
...
2023.02.16
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9df61ab044 | ||
|
|
11bb3f129f | ||
|
|
0335e58b12 | ||
|
|
2d173266df | ||
|
|
f05de1c726 | ||
|
|
b6196a4b3f | ||
|
|
e18df74d5a | ||
|
|
edf10fdd9f | ||
|
|
81934355ed | ||
|
|
e318084300 | ||
|
|
476f74efa8 | ||
|
|
e309dd6e67 | ||
|
|
49cb2e5c0a | ||
|
|
66370508ff | ||
|
|
875186ee24 | ||
|
|
384ef9787b | ||
|
|
dbcd39e91b | ||
|
|
2244d2c3ef | ||
|
|
37c54b5f77 | ||
|
|
f48e7dac83 | ||
|
|
21b33086ae | ||
|
|
6143b2f8ed | ||
|
|
d53c88f314 | ||
|
|
f42ac5d744 | ||
|
|
58f3aaf47d | ||
|
|
244404afbc | ||
|
|
eca3145b1a | ||
|
|
b560f9c749 | ||
|
|
cf582e7152 | ||
|
|
8b9932f85c | ||
|
|
4ec6f8f014 | ||
|
|
1a8659f81f | ||
|
|
e950a00a1e | ||
|
|
f9ac78d27f | ||
|
|
65afdeca36 | ||
|
|
8e59ac9fb4 | ||
|
|
984dae7450 | ||
|
|
be7effd317 | ||
|
|
9e7d785ede | ||
|
|
434e998151 | ||
|
|
b97e75dd67 | ||
|
|
5424aff946 | ||
|
|
08a1ac2591 | ||
|
|
fb70cf7dfe | ||
|
|
b14a1f411d | ||
|
|
fadc616a67 | ||
|
|
cfde9e5148 | ||
|
|
cc8cad10db | ||
|
|
d15461a67b | ||
|
|
917857d213 | ||
|
|
770c6c06bf | ||
|
|
95c589478d | ||
|
|
b51c139264 | ||
|
|
2ef86beea5 | ||
|
|
d029f7b5bd | ||
|
|
dfaec75e94 | ||
|
|
9df1a127c2 | ||
|
|
d28c24d8c9 | ||
|
|
70c4f0db50 | ||
|
|
061033e5da | ||
|
|
7cea239a43 | ||
|
|
736c9dee2d | ||
|
|
28753bfabd | ||
|
|
2d9335a1b9 | ||
|
|
40acb86e10 | ||
|
|
9cbeb9edc6 | ||
|
|
051ede1280 | ||
|
|
bb67ea58b6 | ||
|
|
e3a5312614 | ||
|
|
adbed0d037 | ||
|
|
99238d21b3 | ||
|
|
bfe38e03c3 | ||
|
|
cfb337f992 | ||
|
|
e7b7a73176 | ||
|
|
31db838bfd | ||
|
|
1c0a57abea | ||
|
|
f4fdde9b54 | ||
|
|
462efe74c4 | ||
|
|
e9fbcce220 | ||
|
|
c38b0351e4 | ||
|
|
a92ac09235 | ||
|
|
8a7bf7d565 | ||
|
|
0949999840 | ||
|
|
7824ce176d | ||
|
|
83ce4a3165 | ||
|
|
a140201267 | ||
|
|
f9b6d60ca8 | ||
|
|
9286536fda | ||
|
|
496cb400d0 | ||
|
|
b816884e94 | ||
|
|
ed7fd2e6ef | ||
|
|
c322a50329 | ||
|
|
0b75bce275 | ||
|
|
d3581e4829 | ||
|
|
8485a0e446 | ||
|
|
4f708648e8 | ||
|
|
2d7157703c | ||
|
|
17c1804129 | ||
|
|
e05083ebeb | ||
|
|
0a77f89374 | ||
|
|
ebd1c4e938 | ||
|
|
5115aa1142 | ||
|
|
76971603b4 | ||
|
|
6f5fd20a2c | ||
|
|
42cde3ba70 | ||
|
|
86a48f4ace | ||
|
|
a725b377cc | ||
|
|
63068dfdea | ||
|
|
3ad640aee0 | ||
|
|
bb96072682 | ||
|
|
24b8857165 | ||
|
|
51112aa2f4 | ||
|
|
5bd90adc1f | ||
|
|
81c26d997d | ||
|
|
af78385759 | ||
|
|
420105ec99 | ||
|
|
10e380a03b | ||
|
|
c985d31e4a | ||
|
|
cabf045202 | ||
|
|
8ea431b2e4 | ||
|
|
62a45bd214 |
@@ -11,6 +11,9 @@ print("Commit message is: " + commitmsg)
|
||||
|
||||
ALLOWED_COMMIT_TYPES = [
|
||||
"cicd",
|
||||
"test",
|
||||
"refactor",
|
||||
"depbump",
|
||||
"typo",
|
||||
"fmt",
|
||||
"doc",
|
||||
|
||||
11
.github/PULL_REQUEST_TEMPLATE.md
vendored
11
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -6,14 +6,17 @@ Don’t be afraid to ask for advice before working on a contribution. If you’r
|
||||
|
||||
The preferred way to communicate is probably via Discord or GitHub issues.
|
||||
|
||||
Helpful information to understand the project can be found here: [CONTRIBUTING](https://github.com/jamesread/OliveTin/blob/main/CONTRIBUTING.adoc)
|
||||
Helpful information to understand the project can be found here: [CONTRIBUTING](https://github.com/OliveTin/OliveTin/blob/main/CONTRIBUTING.adoc)
|
||||
|
||||
^^^ please delete the lines above when raising a PR to keep the request to the bare essentials ^^^
|
||||
|
||||
# Checklist
|
||||
Please put a X in the boxes as evidence of reading through the checklist.
|
||||
|
||||
- [ ] I have forked the project, and raised this PR on a freature branch.
|
||||
- [ ] `make daemon-compile`, `make daemon-codestyle` and `make daemon-unittests` runs cleanly.
|
||||
- [ ] `make webui-codestyle` should runs cleanly.
|
||||
- [ ] I have forked the project, and raised this PR on a feature branch.
|
||||
- [ ] `make githooks` has been run, and my git commit message was accepted by the git hook.
|
||||
- [ ] `make daemon-compile` runs without any issues.
|
||||
- [ ] `make daemon-codestyle` runs without any issues.
|
||||
- [ ] `make daemon-unittests` runs without any issues.
|
||||
- [ ] `make webui-codestyle` runs without any issues.
|
||||
- [ ] I understand and accept the [AGPL-3.0 license](LICENSE) and [code of conduct](CODE_OF_CONDUCT.md), and my contributions fall under these.
|
||||
|
||||
38
.github/workflows/build-snapshot.yml
vendored
38
.github/workflows/build-snapshot.yml
vendored
@@ -1,44 +1,54 @@
|
||||
---
|
||||
name: "Build Snapshot"
|
||||
|
||||
on: [push]
|
||||
on:
|
||||
- push
|
||||
- workflow_dispatch
|
||||
|
||||
jobs:
|
||||
build-snapshot:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up QEMU
|
||||
id: qemu
|
||||
uses: docker/setup-qemu-action@v1
|
||||
uses: docker/setup-qemu-action@v2
|
||||
with:
|
||||
image: tonistiigi/binfmt:latest
|
||||
platforms: arm64,arm
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: webui/package-lock.json
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '^1.16.0'
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '>=1.18.0'
|
||||
cache: true
|
||||
|
||||
- name: grpc
|
||||
run: make grpc
|
||||
|
||||
- name: goreleaser
|
||||
uses: goreleaser/goreleaser-action@v2
|
||||
with:
|
||||
uses: goreleaser/goreleaser-action@v3
|
||||
with:
|
||||
distribution: goreleaser
|
||||
version: latest
|
||||
args: release --snapshot --rm-dist
|
||||
args: release --snapshot --rm-dist --parallelism 1
|
||||
|
||||
- name: Archive binaries
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: dist
|
||||
uses: actions/upload-artifact@v3.1.0
|
||||
with:
|
||||
name: "OliveTin-snapshot-${{ github.ref_name }}-${{ github.sha }}-dist"
|
||||
path: dist/OliveTin*.*
|
||||
|
||||
- name: Archive integration tests
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
uses: actions/upload-artifact@v3.1.0
|
||||
with:
|
||||
name: integration-tests
|
||||
path: integration-tests
|
||||
|
||||
30
.github/workflows/build-tag.yml
vendored
30
.github/workflows/build-tag.yml
vendored
@@ -1,8 +1,9 @@
|
||||
---
|
||||
name: "Build Tag"
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
@@ -10,19 +11,26 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up QEMU
|
||||
id: qemu
|
||||
uses: docker/setup-qemu-action@v1
|
||||
uses: docker/setup-qemu-action@v2
|
||||
with:
|
||||
image: tonistiigi/binfmt:latest
|
||||
platforms: arm64,arm
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: webui/package-lock.json
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '^1.16.0'
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '^1.18.0'
|
||||
cache: true
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v1
|
||||
@@ -35,21 +43,21 @@ jobs:
|
||||
|
||||
- name: goreleaser
|
||||
uses: goreleaser/goreleaser-action@v2
|
||||
with:
|
||||
with:
|
||||
distribution: goreleaser
|
||||
version: latest
|
||||
args: release --rm-dist
|
||||
env:
|
||||
args: release --rm-dist --parallelism 1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
|
||||
- name: Archive binaries
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
with:
|
||||
name: dist
|
||||
path: dist/OliveTin*.*
|
||||
|
||||
- name: Archive integration tests
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
with:
|
||||
name: integration-tests
|
||||
path: integration-tests
|
||||
|
||||
51
.github/workflows/codeql-analysis.yml
vendored
51
.github/workflows/codeql-analysis.yml
vendored
@@ -1,3 +1,4 @@
|
||||
---
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
@@ -13,16 +14,15 @@ name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
paths:
|
||||
- 'cmd/**'
|
||||
- 'internal/**'
|
||||
- 'webui/**'
|
||||
- 'integration-tests/**'
|
||||
- 'OliveTin.proto'
|
||||
branches: [ main ]
|
||||
branches: [main]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ main ]
|
||||
branches: [main]
|
||||
schedule:
|
||||
- cron: '25 10 * * 5'
|
||||
|
||||
@@ -38,40 +38,17 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'go', 'javascript' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
||||
# Learn more:
|
||||
# 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
|
||||
language: ['go', 'javascript']
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
#- name: Autobuild
|
||||
# uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
||||
3
.github/workflows/codestyle.yml
vendored
3
.github/workflows/codestyle.yml
vendored
@@ -1,3 +1,4 @@
|
||||
---
|
||||
name: "Codestyle checks"
|
||||
|
||||
on:
|
||||
@@ -19,7 +20,7 @@ jobs:
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
with:
|
||||
go-version: '^1.16.0'
|
||||
|
||||
- name: deps
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,4 +1,3 @@
|
||||
webui/package-lock.json
|
||||
webui/node_modules
|
||||
**/*.swp
|
||||
**/*.swo
|
||||
@@ -9,3 +8,4 @@ gen/
|
||||
reports
|
||||
releases/
|
||||
dist/
|
||||
installation-id.txt
|
||||
|
||||
@@ -34,18 +34,32 @@ builds:
|
||||
goarch: arm64
|
||||
|
||||
ldflags:
|
||||
- -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{ .CommitDate }}
|
||||
- -s -w -X main.version={{.Version}} -X main.commit={{.ShortCommit}} -X main.date={{ .CommitDate }}
|
||||
|
||||
checksum:
|
||||
name_template: 'checksums.txt'
|
||||
snapshot:
|
||||
name_template: "{{ .Commit }}"
|
||||
name_template: "{{ .Branch }}-{{ .ShortCommit }}"
|
||||
changelog:
|
||||
sort: asc
|
||||
groups:
|
||||
- title: 'Security'
|
||||
regexp: '^.*?security(\([[:word:]]+\))??!?:.+$'
|
||||
order: 0
|
||||
- title: 'Features'
|
||||
regexp: '^.*?feature(\([[:word:]]+\))??!?:.+$'
|
||||
order: 1
|
||||
- title: 'Bug fixes'
|
||||
regexp: '^.*?bugfix(\([[:word:]]+\))??!?:.+$'
|
||||
order: 2
|
||||
- title: Others
|
||||
order: 999
|
||||
filters:
|
||||
exclude:
|
||||
- '^docs:'
|
||||
- '^test:'
|
||||
- '^cicd:'
|
||||
- '^refactor:'
|
||||
|
||||
archives:
|
||||
-
|
||||
@@ -58,12 +72,13 @@ archives:
|
||||
- Dockerfile
|
||||
- webui
|
||||
- OliveTin.service
|
||||
- ./var/
|
||||
|
||||
replacements:
|
||||
darwin: macOS
|
||||
arm: arm32v
|
||||
|
||||
name_template: "{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ .Arm }}"
|
||||
name_template: "{{ .ProjectName }}-{{ .Os }}-{{ .Arch }}{{ .Arm }}"
|
||||
|
||||
wrap_in_directory: true
|
||||
|
||||
@@ -78,7 +93,6 @@ dockers:
|
||||
goos: linux
|
||||
goarch: amd64
|
||||
skip_push: false
|
||||
|
||||
build_flag_templates:
|
||||
- "--platform=linux/amd64"
|
||||
- "--label=org.opencontainers.image.title={{.ProjectName}}"
|
||||
@@ -94,7 +108,6 @@ dockers:
|
||||
goos: linux
|
||||
goarch: arm64
|
||||
skip_push: false
|
||||
|
||||
build_flag_templates:
|
||||
- "--platform=linux/arm64"
|
||||
- "--label=org.opencontainers.image.title={{.ProjectName}}"
|
||||
@@ -103,46 +116,31 @@ dockers:
|
||||
extra_files:
|
||||
- webui
|
||||
|
||||
# This container image actually uses the goarm v5 binary, because v5 helps
|
||||
# support rpi 1's, but it seems most container images start with v7.
|
||||
- image_templates:
|
||||
- "docker.io/jamesread/olivetin:{{ .Tag }}-armv7"
|
||||
dockerfile: Dockerfile.armv7
|
||||
goos: linux
|
||||
goarch: arm
|
||||
goarm: 7
|
||||
skip_push: false
|
||||
|
||||
build_flag_templates:
|
||||
- "--platform=linux/arm/v7"
|
||||
- "--label=org.opencontainers.image.title={{.ProjectName}}"
|
||||
- "--label=org.opencontainers.image.revision={{.FullCommit}}"
|
||||
- "--label=org.opencontainers.image.version={{.Tag}}"
|
||||
extra_files:
|
||||
- webui
|
||||
|
||||
docker_manifests:
|
||||
- name_template: docker.io/jamesread/olivetin:{{ .Version }}
|
||||
image_templates:
|
||||
- docker.io/jamesread/olivetin:{{ .Version }}-amd64
|
||||
- docker.io/jamesread/olivetin:{{ .Version }}-arm64
|
||||
- docker.io/jamesread/olivetin:{{ .Version }}-armv7
|
||||
|
||||
- name_template: docker.io/jamesread/olivetin:latest
|
||||
image_templates:
|
||||
- docker.io/jamesread/olivetin:{{ .Version }}-amd64
|
||||
- docker.io/jamesread/olivetin:{{ .Version }}-arm64
|
||||
- docker.io/jamesread/olivetin:{{ .Version }}-armv7
|
||||
|
||||
nfpms:
|
||||
- maintainer: James Read <contact@jread.com>
|
||||
- id: default
|
||||
maintainer: James Read <contact@jread.com>
|
||||
description: OliveTin is a web interface for running Linux shell commands.
|
||||
homepage: https://github.com/jamesread/OliveTin
|
||||
homepage: https://github.com/OliveTin/OliveTin
|
||||
license: AGPL-3.0
|
||||
formats:
|
||||
- deb
|
||||
- rpm
|
||||
|
||||
bindir: /usr/local/bin/
|
||||
|
||||
file_name_template: '{{ .PackageName }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
|
||||
|
||||
contents:
|
||||
- src: OliveTin.service
|
||||
dst: /etc/systemd/system/OliveTin.service
|
||||
@@ -154,8 +152,41 @@ nfpms:
|
||||
dst: /etc/OliveTin/config.yaml
|
||||
type: "config|noreplace"
|
||||
|
||||
- src: var/manpage/OliveTin.1.gz
|
||||
dst: /usr/share/man/man1/OliveTin.1.gz
|
||||
|
||||
- id: openrc
|
||||
maintainer: James Read <contact@jread.com>
|
||||
description: OliveTin is a web interface for running Linux shell commands.
|
||||
homepage: https://github.com/OliveTin/OliveTin
|
||||
license: AGPL-3.0
|
||||
formats:
|
||||
- apk
|
||||
|
||||
bindir: /usr/local/bin/
|
||||
|
||||
file_name_template: '{{ .PackageName }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
|
||||
|
||||
contents:
|
||||
- src: var/openrc/OliveTin
|
||||
dst: /etc/init.d/OliveTin
|
||||
|
||||
- src: webui
|
||||
dst: /var/www/olivetin/
|
||||
|
||||
- src: config.yaml
|
||||
dst: /etc/OliveTin/config.yaml
|
||||
type: "config|noreplace"
|
||||
|
||||
- src: var/manpage/OliveTin.1.gz
|
||||
dst: /usr/share/man/man1/OliveTin.1.gz
|
||||
|
||||
release:
|
||||
footer: |
|
||||
## Container images ([on Docker Hub](https://hub.docker.com/r/jamesread/olivetin/tags?page=1&ordering=last_updated))
|
||||
|
||||
- `docker pull docker.io/jamesread/olivetin:{{ .Version }}`
|
||||
|
||||
## Useful links
|
||||
|
||||
- [Which download do I need?](https://docs.olivetin.app/choose-package.html)
|
||||
|
||||
@@ -29,12 +29,10 @@ dnf install git go protobuf-compiler make -y
|
||||
git clone https://github.com/OliveTin/OliveTin.git
|
||||
cd OliveTin
|
||||
|
||||
# For each dependency in tools.go;
|
||||
go install "github.com/bufbuild/buf/cmd/buf"
|
||||
go install ...
|
||||
|
||||
buf generate
|
||||
|
||||
# `make grpc` will also run `make go-tools`, which installs "buf". This binary
|
||||
# will be put in your GOPATH/bin/, which should be on your path. buf is used to
|
||||
# generate the protobuf / grpc stubs.
|
||||
make grpc
|
||||
make
|
||||
./OliveTin
|
||||
```
|
||||
|
||||
13
Dockerfile
13
Dockerfile
@@ -1,15 +1,14 @@
|
||||
FROM --platform=linux/amd64 docker.io/amd64/fedora
|
||||
|
||||
RUN useradd -rm olivetin -u 1000
|
||||
FROM --platform=linux/amd64 registry.fedoraproject.org/fedora-minimal:36-x86_64
|
||||
|
||||
RUN mkdir -p /config /var/www/olivetin \
|
||||
&& \
|
||||
dnf install -y \
|
||||
&& microdnf install -y --nodocs --noplugins --setopt=keepcache=0 --setopt=install_weak_deps=0 \
|
||||
iputils \
|
||||
openssh-clients \
|
||||
shadow-utils \
|
||||
docker \
|
||||
&& dnf clean all && \
|
||||
rm -rf /var/cache/dnf
|
||||
&& microdnf clean all
|
||||
|
||||
RUN useradd --system --create-home olivetin -u 1000
|
||||
|
||||
EXPOSE 1337/tcp
|
||||
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
FROM --platform=linux/arm64 docker.io/arm64v8/fedora
|
||||
|
||||
RUN useradd -rm olivetin -u 1000
|
||||
FROM --platform=linux/arm64 registry.fedoraproject.org/fedora-minimal:36-aarch64
|
||||
|
||||
RUN mkdir -p /config /var/www/olivetin \
|
||||
&& \
|
||||
dnf install -y \
|
||||
microdnf install -y --nodocs --noplugins --setopt=keepcache=0 --setopt=install_weak_deps=0 \
|
||||
iputils \
|
||||
openssh-clients \
|
||||
&& dnf clean all && \
|
||||
rm -rf /var/cache/dnf
|
||||
shadow-utils \
|
||||
openssh-clients
|
||||
|
||||
RUN useradd --system --create-home olivetin -u 1000
|
||||
|
||||
EXPOSE 1337/tcp
|
||||
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
FROM --platform=linux/arm/v7 arm32v7/fedora:latest
|
||||
|
||||
RUN useradd -rm olivetin -u 1000
|
||||
FROM --platform=linux/armhfp registry.fedoraproject.org/fedora-minimal:36-armhfp
|
||||
|
||||
RUN mkdir -p /config /var/www/olivetin \
|
||||
&& \
|
||||
dnf install -y \
|
||||
microdnf install -y --nodocs --noplugins --setopt=keepcache=0 --setopt=install_weak_deps=0 \
|
||||
iputils \
|
||||
openssh-clients \
|
||||
&& dnf clean all && \
|
||||
rm -rf /var/cache/dnf
|
||||
shadow-utils \
|
||||
openssh-clients
|
||||
|
||||
RUN useradd --system --create-home olivetin -u 1000
|
||||
|
||||
EXPOSE 1337/tcp
|
||||
|
||||
|
||||
17
Makefile
17
Makefile
@@ -1,13 +1,13 @@
|
||||
compile: daemon-compile-x64-lin
|
||||
|
||||
daemon-compile-armhf:
|
||||
GOARCH=arm GOARM=6 go build -o OliveTin.armhf github.com/jamesread/OliveTin/cmd/OliveTin
|
||||
GOARCH=arm GOARM=6 go build -o OliveTin.armhf github.com/OliveTin/OliveTin/cmd/OliveTin
|
||||
|
||||
daemon-compile-x64-lin:
|
||||
GOOS=linux go build -o OliveTin github.com/jamesread/OliveTin/cmd/OliveTin
|
||||
GOOS=linux go build -o OliveTin github.com/OliveTin/OliveTin/cmd/OliveTin
|
||||
|
||||
daemon-compile-x64-win:
|
||||
GOOS=windows GOARCH=amd64 go build -o OliveTin.exe github.com/jamesread/OliveTin/cmd/OliveTin
|
||||
GOOS=windows GOARCH=amd64 go build -o OliveTin.exe github.com/OliveTin/OliveTin/cmd/OliveTin
|
||||
|
||||
daemon-compile: daemon-compile-armhf daemon-compile-x64-lin daemon-compile-x64-win
|
||||
|
||||
@@ -34,15 +34,20 @@ go-tools:
|
||||
go install "google.golang.org/grpc/cmd/protoc-gen-go-grpc"
|
||||
go install "google.golang.org/protobuf/cmd/protoc-gen-go"
|
||||
|
||||
grpc: githooks go-tools
|
||||
grpc: go-tools
|
||||
buf generate
|
||||
|
||||
dist: protoc
|
||||
|
||||
protoc:
|
||||
protoc --go_out=. --go-grpc_out=. --grpc-gateway_out=. -I .:/usr/include/ OliveTin.proto
|
||||
|
||||
podman-image:
|
||||
buildah bud -t olivetin
|
||||
|
||||
podman-container:
|
||||
podman kill olivetin
|
||||
podman rm olivetin
|
||||
podman kill olivetin || true
|
||||
podman rm olivetin || true
|
||||
podman create --name olivetin -p 1337:1337 -v /etc/OliveTin/:/config:ro olivetin
|
||||
podman start olivetin
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ message ActionArgument {
|
||||
string defaultValue = 4;
|
||||
|
||||
repeated ActionArgumentChoice choices = 5;
|
||||
|
||||
string description = 6;
|
||||
}
|
||||
|
||||
message ActionArgumentChoice {
|
||||
@@ -68,6 +70,7 @@ message LogEntry {
|
||||
string user = 7;
|
||||
string userClass = 8;
|
||||
string actionIcon = 9;
|
||||
repeated string tags = 10;
|
||||
}
|
||||
|
||||
message GetLogsResponse {
|
||||
@@ -84,6 +87,12 @@ message ValidateArgumentTypeResponse {
|
||||
string description = 2;
|
||||
}
|
||||
|
||||
message WhoAmIRequest {}
|
||||
|
||||
message WhoAmIResponse {
|
||||
string authenticatedUser = 1;
|
||||
}
|
||||
|
||||
service OliveTinApi {
|
||||
rpc GetDashboardComponents(GetDashboardComponentsRequest) returns (GetDashboardComponentsResponse) {
|
||||
option (google.api.http) = {
|
||||
@@ -110,4 +119,10 @@ service OliveTinApi {
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
|
||||
rpc WhoAmI(WhoAmIRequest) returns (WhoAmIResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/api/WhoAmI"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,13 @@ All documentation can be found at http://docs.olivetin.app . This includes insta
|
||||
|
||||
This is a quick example of `config.yaml` - but again, lots of documentation for how to write your `config.yaml` can be found at [the documentation site.](https://docs.olivetin.app)
|
||||
|
||||
* (Recommended) [Linux package install (.rpm/.deb)](https://docs.olivetin.app/install-linuxpackage.html) install instructions
|
||||
* [Container (podman/docker)](https://docs.olivetin.app/install-container.html) install instructions
|
||||
* [Docker compose](https://docs.olivetin.app/install-compose.html) install instructions
|
||||
* [Helm on Kubernetes](https://docs.olivetin.app/install-helm.html) install instructions
|
||||
* [Kubernetes (manual)](https://docs.olivetin.app/install-k8s.html) install instructions
|
||||
* [.tar.gz (manual)](https://docs.olivetin.app/install-targz.html) install instructions
|
||||
|
||||
Put this `config.yaml` in `/etc/OliveTin/` if you're running a standard service, or mount it at `/config` if running in a container.
|
||||
|
||||
```yaml
|
||||
|
||||
5
buf.lock
5
buf.lock
@@ -4,7 +4,4 @@ deps:
|
||||
- remote: buf.build
|
||||
owner: googleapis
|
||||
repository: googleapis
|
||||
branch: main
|
||||
commit: d1a849b8f8304950832335723096e954
|
||||
digest: b1-zJkwX0YeOp1Wa0Jaj_RqMLa2-oEzePH6PJEK8aaMeI4=
|
||||
create_time: 2021-08-26T15:07:19.652533Z
|
||||
commit: e9fcfb66f77242e5b8fd4564d7a01033
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
grpcapi "github.com/jamesread/OliveTin/internal/grpcapi"
|
||||
updatecheck "github.com/jamesread/OliveTin/internal/updatecheck"
|
||||
"github.com/OliveTin/OliveTin/internal/executor"
|
||||
grpcapi "github.com/OliveTin/OliveTin/internal/grpcapi"
|
||||
"github.com/OliveTin/OliveTin/internal/oncron"
|
||||
"github.com/OliveTin/OliveTin/internal/onstartup"
|
||||
updatecheck "github.com/OliveTin/OliveTin/internal/updatecheck"
|
||||
|
||||
"github.com/jamesread/OliveTin/internal/httpservers"
|
||||
"github.com/OliveTin/OliveTin/internal/httpservers"
|
||||
|
||||
config "github.com/OliveTin/OliveTin/internal/config"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
config "github.com/jamesread/OliveTin/internal/config"
|
||||
"github.com/spf13/viper"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -22,6 +28,11 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
log.SetFormatter(&log.TextFormatter{
|
||||
ForceQuote: true,
|
||||
DisableTimestamp: true,
|
||||
})
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"version": version,
|
||||
"commit": commit,
|
||||
@@ -30,10 +41,18 @@ func init() {
|
||||
|
||||
log.SetLevel(log.DebugLevel) // Default to debug, to catch cfg issues
|
||||
|
||||
var configDir string
|
||||
flag.StringVar(&configDir, "configdir", ".", "Config directory path")
|
||||
flag.Parse()
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"value": configDir,
|
||||
}).Debugf("Value of -configdir flag")
|
||||
|
||||
viper.AutomaticEnv()
|
||||
viper.SetConfigName("config.yaml")
|
||||
viper.SetConfigType("yaml")
|
||||
viper.AddConfigPath(".")
|
||||
viper.AddConfigPath(configDir)
|
||||
viper.AddConfigPath("/config") // For containers.
|
||||
viper.AddConfigPath("/etc/OliveTin/")
|
||||
|
||||
@@ -54,9 +73,18 @@ func init() {
|
||||
})
|
||||
|
||||
reloadConfig()
|
||||
|
||||
warnIfPuidGuid()
|
||||
|
||||
log.Info("Init complete")
|
||||
}
|
||||
|
||||
func warnIfPuidGuid() {
|
||||
if os.Getenv("PUID") != "" || os.Getenv("PGID") != "" {
|
||||
log.Warnf("PUID or PGID seem to be set to something, but they are ignored by OliveTin. Please check https://docs.olivetin.app/no-puid-pgid.html")
|
||||
}
|
||||
}
|
||||
|
||||
func reloadConfig() {
|
||||
if err := viper.UnmarshalExact(&cfg); err != nil {
|
||||
log.Errorf("Config unmarshal error %+v", err)
|
||||
@@ -67,13 +95,22 @@ func reloadConfig() {
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.Info("OliveTin started")
|
||||
configDir := path.Dir(viper.ConfigFileUsed())
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"configDir": configDir,
|
||||
}).Infof("OliveTin started")
|
||||
|
||||
log.Debugf("Config: %+v", cfg)
|
||||
|
||||
go updatecheck.StartUpdateChecker(version, commit, cfg)
|
||||
executor := executor.DefaultExecutor()
|
||||
|
||||
go grpcapi.Start(cfg)
|
||||
go onstartup.Execute(cfg, executor)
|
||||
go oncron.Schedule(cfg, executor)
|
||||
|
||||
go updatecheck.StartUpdateChecker(version, commit, cfg, configDir)
|
||||
|
||||
go grpcapi.Start(cfg, executor)
|
||||
|
||||
httpservers.StartServers(cfg)
|
||||
}
|
||||
|
||||
@@ -25,11 +25,13 @@ actions:
|
||||
title: host
|
||||
type: ascii_identifier
|
||||
default: example.com
|
||||
description: The host that you want to ping
|
||||
|
||||
- name: count
|
||||
title: Count
|
||||
type: int
|
||||
default: 1
|
||||
description: How many times to do you want to ping?
|
||||
|
||||
# Restart lightdm on host "server1"
|
||||
# Docs: https://docs.olivetin.app/action-ping.html
|
||||
|
||||
88
go.mod
88
go.mod
@@ -1,22 +1,78 @@
|
||||
module github.com/jamesread/OliveTin
|
||||
module github.com/OliveTin/OliveTin
|
||||
|
||||
go 1.16
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/bufbuild/buf v0.54.1
|
||||
github.com/denisbrodbeck/machineid v1.0.1
|
||||
github.com/fsnotify/fsnotify v1.4.9
|
||||
github.com/fzipp/gocyclo v0.3.1
|
||||
github.com/go-co-op/gocron v1.6.2
|
||||
github.com/go-critic/go-critic v0.6.1
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0
|
||||
github.com/bufbuild/buf v1.3.1
|
||||
github.com/fsnotify/fsnotify v1.5.4
|
||||
github.com/fzipp/gocyclo v0.5.0
|
||||
github.com/go-critic/go-critic v0.6.2
|
||||
github.com/golang-jwt/jwt/v4 v4.4.2
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.10.3
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/spf13/viper v1.8.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b // indirect
|
||||
golang.org/x/tools v0.1.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced
|
||||
google.golang.org/grpc v1.40.0-dev.0.20210708170655-30dfb4b933a5
|
||||
github.com/spf13/viper v1.12.0
|
||||
github.com/stretchr/testify v1.7.2
|
||||
golang.org/x/exp v0.0.0-20220823124025-807a23277127
|
||||
google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac
|
||||
google.golang.org/grpc v1.47.0
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0
|
||||
google.golang.org/protobuf v1.27.1
|
||||
google.golang.org/protobuf v1.28.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/go-toolsmith/astcast v1.0.0 // indirect
|
||||
github.com/go-toolsmith/astcopy v1.0.0 // indirect
|
||||
github.com/go-toolsmith/astequal v1.0.1 // indirect
|
||||
github.com/go-toolsmith/astfmt v1.0.0 // indirect
|
||||
github.com/go-toolsmith/astp v1.0.0 // indirect
|
||||
github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5 // indirect
|
||||
github.com/go-toolsmith/strparse v1.0.0 // indirect
|
||||
github.com/go-toolsmith/typep v1.0.2 // indirect
|
||||
github.com/gofrs/flock v0.8.1 // indirect
|
||||
github.com/gofrs/uuid v4.2.0+incompatible // indirect
|
||||
github.com/golang/glog v1.0.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/jdxcode/netrc v0.0.0-20210204082910-926c7f70242a // indirect
|
||||
github.com/jhump/protocompile v0.0.0-20220216033700-d705409f108f // indirect
|
||||
github.com/jhump/protoreflect v1.11.1-0.20220213155251-0c2aedc66cf4 // indirect
|
||||
github.com/klauspost/compress v1.15.1 // indirect
|
||||
github.com/klauspost/pgzip v1.2.5 // indirect
|
||||
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e // indirect
|
||||
github.com/magiconair/properties v1.8.6 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.2 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
|
||||
github.com/pkg/profile v1.6.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/quasilyte/go-ruleguard v0.3.15 // indirect
|
||||
github.com/quasilyte/gogrep v0.0.0-20220103110004-ffaa07af02e3 // indirect
|
||||
github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/spf13/afero v1.8.2 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/cobra v1.4.0 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/subosito/gotenv v1.4.0 // indirect
|
||||
go.opencensus.io v0.23.0 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.8.0 // indirect
|
||||
go.uber.org/zap v1.21.0 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/tools v0.1.12 // indirect
|
||||
gopkg.in/ini.v1 v1.66.6 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
346
go.sum
346
go.sum
@@ -3,6 +3,7 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||
@@ -15,9 +16,7 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
||||
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
|
||||
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
|
||||
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
||||
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
@@ -26,7 +25,6 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
@@ -36,24 +34,17 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
|
||||
github.com/bufbuild/buf v0.54.1 h1:k5zYgSOlNg17mZCBgKo6TWktCiSvBdOx+v591t3JPjY=
|
||||
github.com/bufbuild/buf v0.54.1/go.mod h1:BRVv/lQDPFt0AGt79VgXMQK5HHXRW5VFhAu+mNnOmeM=
|
||||
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
|
||||
github.com/bufbuild/buf v1.3.1 h1:AelWcENnbNEjwxmQXIZaU51GHgnWQ8Mc94kZdDUKgRs=
|
||||
github.com/bufbuild/buf v1.3.1/go.mod h1:CTRUb23N+zlm1U8ZIBKz0Sqluk++qQloB2i/MZNZHIs=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
@@ -61,34 +52,31 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/denisbrodbeck/machineid v1.0.1 h1:geKr9qtkB876mXguW2X6TU4ZynleN6ezuMSRhl4D7AQ=
|
||||
github.com/denisbrodbeck/machineid v1.0.1/go.mod h1:dJUwb7PTidGDeYyUBmXZ2GphQBbjJCrnectwCyxcUSI=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fzipp/gocyclo v0.3.1 h1:A9UeX3HJSXTBzvHzhqoYVuE0eAhe+aM8XBCCwsPMZOc=
|
||||
github.com/fzipp/gocyclo v0.3.1/go.mod h1:DJHO6AUmbdqj2ET4Z9iArSuwWgYDRryYt2wASxc7x3E=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
||||
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
github.com/fzipp/gocyclo v0.5.0 h1:jMgQATRpq/msyXdnO36+sOEDhQ4EWJDta3RIGA9GRqA=
|
||||
github.com/fzipp/gocyclo v0.5.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-co-op/gocron v1.6.2 h1:x5g1tWnWcXIZesdosJJcbziRi4XG6tKB92yKLUpoBkU=
|
||||
github.com/go-co-op/gocron v1.6.2/go.mod h1:DbJm9kdgr1sEvWpHCA7dFFs/PGHPMil9/97EXCRPr4k=
|
||||
github.com/go-critic/go-critic v0.6.1 h1:lS8B9LH/VVsvQQP7Ao5TJyQqteVKVs3E4dXiHMyubtI=
|
||||
github.com/go-critic/go-critic v0.6.1/go.mod h1:SdNCfU0yF3UBjtaZGw6586/WocupMOJuiqgom5DsQxM=
|
||||
github.com/go-critic/go-critic v0.6.2 h1:L5SDut1N4ZfsWZY0sH4DCrsHLHnhuuWak2wa165t9gs=
|
||||
github.com/go-critic/go-critic v0.6.2/go.mod h1:td1s27kfmLpe5G/DPjlnFI7o1UCzePptwU7Az0V5iCM=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@@ -101,29 +89,28 @@ github.com/go-toolsmith/astequal v1.0.1 h1:JbSszi42Jiqu36Gnf363HWS9MTEAz67vTQLpo
|
||||
github.com/go-toolsmith/astequal v1.0.1/go.mod h1:4oGA3EZXTVItV/ipGiOx7NWkY5veFfcsOJVS2YxltLw=
|
||||
github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k=
|
||||
github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw=
|
||||
github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU=
|
||||
github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg=
|
||||
github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI=
|
||||
github.com/go-toolsmith/pkgload v1.0.0 h1:4DFWWMXVfbcN5So1sBNW9+yeiMqLFGl1wFLTL5R0Tgg=
|
||||
github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc=
|
||||
github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5 h1:eD9POs68PHkwrx7hAB78z1cb6PfGq/jyWn3wJywsH1o=
|
||||
github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5/go.mod h1:3NAwwmD4uY/yggRxoEjk/S00MIV3A+H7rrE3i87eYxM=
|
||||
github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4=
|
||||
github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8=
|
||||
github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
|
||||
github.com/go-toolsmith/typep v1.0.2 h1:8xdsa1+FSIH/RhEkgnD1j2CJOy5mNllW1Q9tRiYwvlk=
|
||||
github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
||||
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0=
|
||||
github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/glog v0.0.0-20210429001901-424d2337a529 h1:2voWjNECnrZRbfwXxHB1/j8wa6xdKn85B5NzgVL/pTU=
|
||||
github.com/golang/glog v0.0.0-20210429001901-424d2337a529/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=
|
||||
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
@@ -131,7 +118,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@@ -147,11 +133,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
|
||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
@@ -165,9 +148,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
@@ -180,157 +162,117 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf
|
||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
|
||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0 h1:ajue7SzQMywqRjg2fK7dcpc0QhFGpTR2plWfV4EZWR4=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0/go.mod h1:r1hZAcvfFXuYmcKyCJI9wlyOPIZUJl6FCB8Cpca/NLE=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.10.3 h1:BGNSrTRW4rwfhJiFwvwF4XQ0Y72Jj9YEgxVrtovbD5o=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.10.3/go.mod h1:VHn7KgNsRriXa4mcgtkpR00OXyQY6g67JWMvn+R27A4=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jhump/protoreflect v1.9.1-0.20210817181203-db1a327a393e h1:Yb4fEGk+GtBSNuvy5rs0ZJt/jtopc/z9azQaj3xbies=
|
||||
github.com/jhump/protoreflect v1.9.1-0.20210817181203-db1a327a393e/go.mod h1:7GcYQDdMU/O/BBrl/cX6PNHpXh6cenjd8pneu5yW7Tg=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jdxcode/netrc v0.0.0-20210204082910-926c7f70242a h1:d4+I1YEKVmWZrgkt6jpXBnLgV2ZjO0YxEtLDdfIZfH4=
|
||||
github.com/jdxcode/netrc v0.0.0-20210204082910-926c7f70242a/go.mod h1:Zi/ZFkEqFHTm7qkjyNJjaWH4LQA9LQhGJyF0lTYGpxw=
|
||||
github.com/jhump/protocompile v0.0.0-20220216033700-d705409f108f h1:BNuUg9k2EiJmlMwjoef3e8vZLHplbVw6DrjGFjLL+Yo=
|
||||
github.com/jhump/protocompile v0.0.0-20220216033700-d705409f108f/go.mod h1:qr2b5kx4HbFS7/g4uYO5qv9ei8303JMsC7ESbYiqr2Q=
|
||||
github.com/jhump/protoreflect v1.11.1-0.20220213155251-0c2aedc66cf4 h1:E2CdxLXYSn6Zrj2+u8DWrwMJW3YZLSWtM/7kIL8OL18=
|
||||
github.com/jhump/protoreflect v1.11.1-0.20220213155251-0c2aedc66cf4/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.13.4 h1:0zhec2I8zGnjWcKyLl6i3gPqKANCCn5e9xmviEEeX6s=
|
||||
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583BL1A=
|
||||
github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
|
||||
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e h1:9MlwzLdW7QSDrhDjFlsEYmxpFyIoXmYRon3dt0io31k=
|
||||
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
|
||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
|
||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ=
|
||||
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
|
||||
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pelletier/go-toml/v2 v2.0.2 h1:+jQXlF3scKIcSEKkdHzXhCTDLPFi5r1wnK6yPS+49Gw=
|
||||
github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.6.0 h1:hUDfIISABYI59DyeB3OTay/HxSRwTQ8rB/H83k6r5dM=
|
||||
github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
|
||||
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
|
||||
github.com/quasilyte/go-ruleguard v0.3.1-0.20210203134552-1b5a410e1cc8/go.mod h1:KsAh3x0e7Fkpgs+Q9pNLS5XpFSvYCEVl5gP9Pp1xp30=
|
||||
github.com/quasilyte/go-ruleguard v0.3.13 h1:O1G41cq1jUr3cJmqp7vOUT0SokqjzmS9aESWJuIDRaY=
|
||||
github.com/quasilyte/go-ruleguard v0.3.13/go.mod h1:Ul8wwdqR6kBVOCt2dipDBkE+T6vAV/iixkrKuRTN1oQ=
|
||||
github.com/quasilyte/go-ruleguard v0.3.15 h1:iWYzp1z72IlXTioET0+XI6SjQdPfMGfuAiZiKznOt7g=
|
||||
github.com/quasilyte/go-ruleguard v0.3.15/go.mod h1:NhuWhnlVEM1gT1A4VJHYfy9MuYSxxwHgxWoPsn9llB4=
|
||||
github.com/quasilyte/go-ruleguard/dsl v0.3.0/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU=
|
||||
github.com/quasilyte/go-ruleguard/dsl v0.3.10/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU=
|
||||
github.com/quasilyte/go-ruleguard/dsl v0.3.12-0.20220101150716-969a394a9451/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU=
|
||||
github.com/quasilyte/go-ruleguard/dsl v0.3.12/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU=
|
||||
github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1/go.mod h1:7JTjp89EGyU1d6XfBiXihJNG37wB2VRkd125Q1u7Plc=
|
||||
github.com/quasilyte/go-ruleguard/rules v0.0.0-20210428214800-545e0d2e0bf7/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50=
|
||||
github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50=
|
||||
github.com/quasilyte/gogrep v0.0.0-20220103110004-ffaa07af02e3 h1:P4QPNn+TK49zJjXKERt/vyPbv/mCHB/zQ4flDYOMN+M=
|
||||
github.com/quasilyte/gogrep v0.0.0-20220103110004-ffaa07af02e3/go.mod h1:wSEyW6O61xRV6zb6My3HxrQ5/8ke7NE2OayqCHa3xRM=
|
||||
github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 h1:L8QM9bvf68pVdQ3bCFZMDmnt9yqcMBro1pC7F+IPYMY=
|
||||
github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
|
||||
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw=
|
||||
github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
|
||||
github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo=
|
||||
github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo=
|
||||
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
|
||||
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
|
||||
github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
|
||||
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44=
|
||||
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
|
||||
github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ=
|
||||
github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/twitchtv/twirp v8.1.0+incompatible h1:KGXanpa9LXdVE/V5P/tA27rkKFmXRGCtSNT7zdeeVOY=
|
||||
github.com/twitchtv/twirp v8.1.0+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A=
|
||||
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
github.com/subosito/gotenv v1.4.0 h1:yAzM1+SmVcz5R4tXGsNMu1jUl2aOJXoiWUCEwwnGrvs=
|
||||
github.com/subosito/gotenv v1.4.0/go.mod h1:mZd6rFysKEcUhUHXJk0C/08wAgyDBFuwEYL7vWWGaGo=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
|
||||
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
@@ -340,23 +282,23 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
||||
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec=
|
||||
go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE=
|
||||
go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
|
||||
go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
|
||||
go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
|
||||
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -367,6 +309,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20220823124025-807a23277127 h1:S4NrSKDfihhl3+4jSTgwoIevKxX9p7Iv9x++OEIptDo=
|
||||
golang.org/x/exp v0.0.0-20220823124025-807a23277127/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@@ -380,8 +324,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
@@ -392,12 +334,12 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
@@ -426,13 +368,12 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO1APK1CoO39T4BN/XBw=
|
||||
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -442,10 +383,6 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ
|
||||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210615190721-d04028783cf1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -456,11 +393,8 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -470,7 +404,6 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -493,22 +426,21 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b h1:1VkfZQv42XQlA/jchYumAnv1UPo6RgF9rJFkTgZIxO4=
|
||||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -523,13 +455,11 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
@@ -539,8 +469,6 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
@@ -562,10 +490,7 @@ golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWc
|
||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200812195022-5ae4c3c160a0/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
@@ -576,17 +501,15 @@ golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4f
|
||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201230224404-63754364767c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ=
|
||||
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||
golang.org/x/tools v0.1.9-0.20211228192929-ee1ca4ffc4da/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
@@ -607,9 +530,6 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513
|
||||
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
|
||||
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
|
||||
google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
@@ -652,14 +572,10 @@ google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6D
|
||||
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||
google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced h1:c5geK1iMU3cDKtFrCVQIcjR3W+JOZMuhIyICMCTbtus=
|
||||
google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
|
||||
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac h1:ByeiW1F67iV9o8ipGskA+HWzSkMbRJuKLlwCdPxzn7A=
|
||||
google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
@@ -678,10 +594,9 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv
|
||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.40.0-dev.0.20210708170655-30dfb4b933a5 h1:jeEzNnOogdiVxvaPNbt/QFOggkBTaUPBkQ2/NIngeyk=
|
||||
google.golang.org/grpc v1.40.0-dev.0.20210708170655-30dfb4b933a5/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8=
|
||||
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
@@ -694,25 +609,28 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||
google.golang.org/protobuf v1.27.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI=
|
||||
gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
||||
8
integration-tests/Vagrantfile
vendored
8
integration-tests/Vagrantfile
vendored
@@ -11,10 +11,10 @@ Vagrant.configure("2") do |config|
|
||||
libvirt.management_network_device = 'virbr0'
|
||||
end
|
||||
|
||||
config.vm.define :f34 do |f34|
|
||||
f34.vm.box = "generic/fedora34"
|
||||
f34.vm.provision "file", source: "/opt/OliveTin-vagrant/linux_amd64_rpm/.", destination: "."
|
||||
f34.vm.provision "shell", inline: "rpm -U OliveTin* && systemctl enable --now OliveTin && systemctl disable --now firewalld"
|
||||
config.vm.define :f36 do |f36|
|
||||
f36.vm.box = "generic/fedora36"
|
||||
f36.vm.provision "file", source: "/opt/OliveTin-vagrant/linux_amd64_rpm/.", destination: "."
|
||||
f36.vm.provision "shell", inline: "rpm -U OliveTin* && systemctl enable --now OliveTin && systemctl disable --now firewalld"
|
||||
end
|
||||
|
||||
config.vm.define :debian do |debian|
|
||||
|
||||
12
integration-tests/configs/config.hiddenFooter.yaml
Normal file
12
integration-tests/configs/config.hiddenFooter.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
#
|
||||
# Integration Test Config: General
|
||||
#
|
||||
|
||||
showFooter: false
|
||||
checkForUpdates: false
|
||||
|
||||
# Actions (buttons) to show up on the WebUI:
|
||||
actions:
|
||||
- title: Ping example.com
|
||||
shell: ping example.com -c 1
|
||||
icon: ping
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
listenAddressSingleHTTPFrontend: 0.0.0.0:1337
|
||||
|
||||
hideNavigation: true
|
||||
showNavigation: false
|
||||
checkForUpdates: false
|
||||
|
||||
# Actions (buttons) to show up on the WebUI:
|
||||
|
||||
@@ -8,11 +8,11 @@ describe('Homepage rendering', () => {
|
||||
})
|
||||
|
||||
it('Default buttons are rendered', () => {
|
||||
cy.get("#rootGroup button").should('have.length', 6)
|
||||
cy.get("#root-group button").should('have.length', 6)
|
||||
})
|
||||
|
||||
it('Switcher navigation is visible', () => {
|
||||
cy.get('#sectionSwitcher').then($el => {
|
||||
cy.get('#section-switcher').then($el => {
|
||||
expect(Cypress.dom.isHidden($el)).to.be.false
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
describe('Hidden Footer', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("/")
|
||||
cy.wait(500)
|
||||
});
|
||||
|
||||
it('Footer is hidden', () => {
|
||||
cy.get('footer').then($el => {
|
||||
expect(Cypress.dom.isHidden($el)).to.be.true
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ describe('Hidden Nav', () => {
|
||||
})
|
||||
|
||||
it('Switcher navigation is hidden', () => {
|
||||
cy.get('#sectionSwitcher').then($el => {
|
||||
cy.get('#section-switcher').then($el => {
|
||||
expect(Cypress.dom.isHidden($el)).to.be.true
|
||||
})
|
||||
})
|
||||
|
||||
1900
integration-tests/package-lock.json
generated
1900
integration-tests/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -2,86 +2,135 @@ package acl
|
||||
|
||||
import (
|
||||
"context"
|
||||
config "github.com/jamesread/OliveTin/internal/config"
|
||||
config "github.com/OliveTin/OliveTin/internal/config"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
// User respresents a person.
|
||||
type User struct {
|
||||
Username string
|
||||
type AuthenticatedUser struct {
|
||||
Username string
|
||||
Usergroup string
|
||||
|
||||
acls []string
|
||||
}
|
||||
|
||||
// IsAllowedExec checks if a User is allowed to execute an Action
|
||||
func IsAllowedExec(cfg *config.Config, user *User, action *config.Action) bool {
|
||||
canExec := cfg.DefaultPermissions.Exec
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"User": user.Username,
|
||||
"Action": action.Title,
|
||||
"CanExec": canExec,
|
||||
}).Debug("isAllowedExec Permission Default")
|
||||
|
||||
for _, permissionEntry := range action.Permissions {
|
||||
if isUserInGroup(user, permissionEntry.Usergroup) {
|
||||
// IsAllowedExec checks if a AuthenticatedUser is allowed to execute an Action
|
||||
func IsAllowedExec(cfg *config.Config, user *AuthenticatedUser, action *config.Action) bool {
|
||||
for _, acl := range getRelevantAcls(cfg, action.Acls, user) {
|
||||
if acl.Permissions.Exec {
|
||||
log.WithFields(log.Fields{
|
||||
"User": user.Username,
|
||||
"Action": action.Title,
|
||||
"CanExec": permissionEntry.Exec,
|
||||
}).Debug("isAllowedExec Permission Entry")
|
||||
"User": user.Username,
|
||||
"Action": action.Title,
|
||||
"ACL": acl.Name,
|
||||
}).Debug("isAllowedExec - Matched ACL")
|
||||
|
||||
canExec = permissionEntry.Exec
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"User": user.Username,
|
||||
"Action": action.Title,
|
||||
"CanExec": canExec,
|
||||
}).Debug("isAllowedExec Final Result")
|
||||
"User": user.Username,
|
||||
"Action": action.Title,
|
||||
}).Debug("isAllowedExec - No ACLs matched")
|
||||
|
||||
return canExec
|
||||
return cfg.DefaultPermissions.Exec
|
||||
}
|
||||
|
||||
// IsAllowedView checks if a User is allowed to view an Action
|
||||
func IsAllowedView(cfg *config.Config, user *User, action *config.Action) bool {
|
||||
canView := cfg.DefaultPermissions.View
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"User": user.Username,
|
||||
"Action": action.Title,
|
||||
"CanView": canView,
|
||||
}).Debug("isAllowedView Permission Default")
|
||||
|
||||
for idx, permissionEntry := range action.Permissions {
|
||||
if isUserInGroup(user, permissionEntry.Usergroup) {
|
||||
func IsAllowedView(cfg *config.Config, user *AuthenticatedUser, action *config.Action) bool {
|
||||
for _, acl := range getRelevantAcls(cfg, action.Acls, user) {
|
||||
if acl.Permissions.View {
|
||||
log.WithFields(log.Fields{
|
||||
"User": user.Username,
|
||||
"Action": action.Title,
|
||||
"CanView": permissionEntry.View,
|
||||
"Index": idx,
|
||||
}).Debug("isAllowedView Permission Entry")
|
||||
"User": user.Username,
|
||||
"Action": action.Title,
|
||||
"ACL": acl.Name,
|
||||
}).Debug("isAllowedView - Matched ACL")
|
||||
|
||||
canView = permissionEntry.View
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"User": user.Username,
|
||||
"Action": action.Title,
|
||||
"CanView": canView,
|
||||
}).Debug("isAllowedView Final Result")
|
||||
"User": user.Username,
|
||||
"Action": action.Title,
|
||||
}).Debug("isAllowedView - No ACLs matched")
|
||||
|
||||
return canView
|
||||
return cfg.DefaultPermissions.View
|
||||
}
|
||||
|
||||
func isUserInGroup(user *User, usergroup string) bool {
|
||||
return true
|
||||
func getMetdataKeyOrEmpty(md metadata.MD, key string) string {
|
||||
mdValues := md.Get(key)
|
||||
|
||||
if len(mdValues) > 0 {
|
||||
return mdValues[0]
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// UserFromContext tries to find a user from a grpc context - obviously this is
|
||||
// a stub at the moment.
|
||||
func UserFromContext(ctx context.Context) *User {
|
||||
return &User{
|
||||
Username: "Guest",
|
||||
// UserFromContext tries to find a user from a grpc context
|
||||
func UserFromContext(ctx context.Context, cfg *config.Config) *AuthenticatedUser {
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
|
||||
ret := &AuthenticatedUser{}
|
||||
|
||||
if ok {
|
||||
ret.Username = getMetdataKeyOrEmpty(md, "username")
|
||||
ret.Usergroup = getMetdataKeyOrEmpty(md, "usergroup")
|
||||
}
|
||||
|
||||
buildUserAcls(cfg, ret)
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"username": ret.Username,
|
||||
"usergroup": ret.Usergroup,
|
||||
}).Infof("UserFromContext")
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func buildUserAcls(cfg *config.Config, user *AuthenticatedUser) {
|
||||
for _, acl := range cfg.AccessControlLists {
|
||||
if slices.Contains(acl.MatchUsernames, user.Username) {
|
||||
user.acls = append(user.acls, acl.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
if slices.Contains(acl.MatchUsergroups, user.Usergroup) {
|
||||
user.acls = append(user.acls, acl.Name)
|
||||
continue
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isACLRelevant(cfg *config.Config, actionAcls []string, acl config.AccessControlList, user *AuthenticatedUser) bool {
|
||||
if !slices.Contains(user.acls, acl.Name) {
|
||||
return false
|
||||
}
|
||||
|
||||
if acl.AddToEveryAction {
|
||||
return true
|
||||
}
|
||||
|
||||
if slices.Contains(actionAcls, acl.Name) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func getRelevantAcls(cfg *config.Config, actionAcls []string, user *AuthenticatedUser) []*config.AccessControlList {
|
||||
var ret []*config.AccessControlList
|
||||
|
||||
for _, acl := range cfg.AccessControlLists {
|
||||
if isACLRelevant(cfg, actionAcls, acl, user) {
|
||||
ret = append(ret, &acl)
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -3,23 +3,26 @@ package config
|
||||
// Action represents the core functionality of OliveTin - commands that show up
|
||||
// as buttons in the UI.
|
||||
type Action struct {
|
||||
ID string
|
||||
Title string
|
||||
Icon string
|
||||
Shell string
|
||||
CSS map[string]string `mapstructure:"omitempty"`
|
||||
Timeout int
|
||||
Permissions []PermissionsEntry
|
||||
Arguments []ActionArgument
|
||||
ID string
|
||||
Title string
|
||||
Icon string
|
||||
Shell string
|
||||
CSS map[string]string `mapstructure:"omitempty"`
|
||||
Timeout int
|
||||
Acls []string
|
||||
ExecOnStartup bool
|
||||
ExecOnCron []string
|
||||
Arguments []ActionArgument
|
||||
}
|
||||
|
||||
// ActionArgument objects appear on Actions.
|
||||
type ActionArgument struct {
|
||||
Name string
|
||||
Title string
|
||||
Type string
|
||||
Default string
|
||||
Choices []ActionArgumentChoice
|
||||
Name string
|
||||
Title string
|
||||
Description string
|
||||
Type string
|
||||
Default string
|
||||
Choices []ActionArgumentChoice
|
||||
}
|
||||
|
||||
// ActionArgumentChoice represents a predefined choice for an argument.
|
||||
@@ -37,30 +40,25 @@ type Entity struct {
|
||||
CSS map[string]string
|
||||
}
|
||||
|
||||
// PermissionsEntry defines what users can do with an action.
|
||||
type PermissionsEntry struct {
|
||||
Usergroup string
|
||||
View bool
|
||||
Exec bool
|
||||
}
|
||||
|
||||
// DefaultPermissions will be used when no PermissionsEntry overrides it.
|
||||
type DefaultPermissions struct {
|
||||
// PermissionsList defines what users can do with an action.
|
||||
type PermissionsList struct {
|
||||
View bool
|
||||
Exec bool
|
||||
}
|
||||
|
||||
// UserGroup is a group of users.
|
||||
type UserGroup struct {
|
||||
Name string
|
||||
Members []string
|
||||
// AccessControlList defines what permissions apply to a user or user group.
|
||||
type AccessControlList struct {
|
||||
Name string
|
||||
AddToEveryAction bool
|
||||
MatchUsergroups []string
|
||||
MatchUsernames []string
|
||||
Permissions PermissionsList
|
||||
}
|
||||
|
||||
// Config is the global config used through the whole app.
|
||||
type Config struct {
|
||||
UseSingleHTTPFrontend bool
|
||||
ThemeName string
|
||||
HideNavigation bool
|
||||
ListenAddressSingleHTTPFrontend string
|
||||
ListenAddressWebUI string
|
||||
ListenAddressRestActions string
|
||||
@@ -70,25 +68,39 @@ type Config struct {
|
||||
Actions []Action `mapstructure:"actions"`
|
||||
Entities []Entity `mapstructure:"entities"`
|
||||
CheckForUpdates bool
|
||||
PageTitle string
|
||||
ShowFooter bool
|
||||
ShowNavigation bool
|
||||
ShowNewVersions bool
|
||||
Usergroups []UserGroup
|
||||
DefaultPermissions DefaultPermissions
|
||||
AuthJwtCookieName string
|
||||
AuthJwtSecret string
|
||||
AuthJwtClaimUsername string
|
||||
AuthJwtClaimUserGroup string
|
||||
AuthHttpHeaderUsername string
|
||||
AuthHttpHeaderUserGroup string
|
||||
DefaultPermissions PermissionsList
|
||||
AccessControlLists []AccessControlList
|
||||
}
|
||||
|
||||
// DefaultConfig gets a new Config structure with sensible default values.
|
||||
func DefaultConfig() *Config {
|
||||
config := Config{}
|
||||
config.UseSingleHTTPFrontend = true
|
||||
config.HideNavigation = false
|
||||
config.PageTitle = "OliveTin"
|
||||
config.ShowFooter = true
|
||||
config.ShowNavigation = true
|
||||
config.ShowNewVersions = true
|
||||
config.ListenAddressSingleHTTPFrontend = "0.0.0.0:1337"
|
||||
config.ListenAddressRestActions = "localhost:1338"
|
||||
config.ListenAddressGrpcActions = "localhost:1339"
|
||||
config.ListenAddressWebUI = "localhost:1340"
|
||||
config.ExternalRestAddress = "."
|
||||
config.LogLevel = "INFO"
|
||||
config.CheckForUpdates = true
|
||||
config.ShowNewVersions = true
|
||||
config.DefaultPermissions.Exec = true
|
||||
config.DefaultPermissions.View = true
|
||||
config.AuthJwtClaimUsername = "name"
|
||||
config.AuthJwtClaimUserGroup = "group"
|
||||
|
||||
return &config
|
||||
}
|
||||
|
||||
@@ -21,3 +21,13 @@ func (action *Action) FindArg(name string) *ActionArgument {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cfg *Config) FindAcl(aclTitle string) *AccessControlList {
|
||||
for _, acl := range cfg.AccessControlLists {
|
||||
if acl.Name == aclTitle {
|
||||
return &acl
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -31,3 +31,16 @@ func TestFindAction(t *testing.T) {
|
||||
|
||||
assert.Nil(t, c.FindAction("waffles"), "Find non-existent action")
|
||||
}
|
||||
|
||||
func TestFindAcl(t *testing.T) {
|
||||
c := DefaultConfig()
|
||||
|
||||
acl1 := AccessControlList{
|
||||
Name: "Testing ACL",
|
||||
}
|
||||
|
||||
c.AccessControlLists = append(c.AccessControlLists, acl1)
|
||||
|
||||
assert.NotNil(t, c.FindAcl("Testing ACL"), "Find a ACL that should exist")
|
||||
assert.Nil(t, c.FindAcl("Chocolate Cake"), "Find a ACL that does not exist")
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
func AllowCors(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if origin := r.Header.Get("Origin"); origin != "" {
|
||||
log.Debugf("Adding CORS header origin: %v", origin)
|
||||
log.Debugf("Adding CORS header origin: %q", origin)
|
||||
|
||||
w.Header().Set("Access-Control-Allow-Origin", origin)
|
||||
}
|
||||
|
||||
121
internal/executor/arguments.go
Normal file
121
internal/executor/arguments.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package executor
|
||||
|
||||
import (
|
||||
config "github.com/OliveTin/OliveTin/internal/config"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"errors"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
typecheckRegex = map[string]string{
|
||||
"very_dangerous_raw_string": "",
|
||||
"int": "^[\\d]+$",
|
||||
"ascii": "^[a-zA-Z0-9]+$",
|
||||
"ascii_identifier": "^[a-zA-Z0-9\\-\\.\\_]+$",
|
||||
"ascii_sentence": "^[a-zA-Z0-9 \\,\\.]+$",
|
||||
}
|
||||
)
|
||||
|
||||
func parseActionArguments(rawShellCommand string, values map[string]string, action *config.Action) (string, error) {
|
||||
log.WithFields(log.Fields{
|
||||
"cmd": rawShellCommand,
|
||||
}).Infof("Before Parse Args")
|
||||
|
||||
r := regexp.MustCompile("{{ *?([a-zA-Z0-9_]+?) *?}}")
|
||||
matches := r.FindAllStringSubmatch(rawShellCommand, -1)
|
||||
|
||||
for _, match := range matches {
|
||||
argValue, argProvided := values[match[1]]
|
||||
|
||||
if !argProvided {
|
||||
log.Infof("%v", values)
|
||||
return "", errors.New("Required arg not provided: " + match[1])
|
||||
}
|
||||
|
||||
err := typecheckActionArgument(match[1], argValue, action)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"name": match[1],
|
||||
"value": argValue,
|
||||
}).Debugf("Arg assigned")
|
||||
|
||||
rawShellCommand = strings.ReplaceAll(rawShellCommand, match[0], argValue)
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"cmd": rawShellCommand,
|
||||
}).Infof("After Parse Args")
|
||||
|
||||
return rawShellCommand, nil
|
||||
}
|
||||
|
||||
func typecheckActionArgument(name string, value string, action *config.Action) error {
|
||||
arg := action.FindArg(name)
|
||||
|
||||
if arg == nil {
|
||||
return errors.New("Action arg not defined: " + name)
|
||||
}
|
||||
|
||||
if len(arg.Choices) > 0 {
|
||||
return typecheckChoice(value, arg)
|
||||
}
|
||||
|
||||
return TypeSafetyCheck(name, value, arg.Type)
|
||||
}
|
||||
|
||||
func typecheckChoice(value string, arg *config.ActionArgument) error {
|
||||
for _, choice := range arg.Choices {
|
||||
if value == choice.Value {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return errors.New("argument value is not one of the predefined choices")
|
||||
}
|
||||
|
||||
// TypeSafetyCheck checks argument values match a specific type. The types are
|
||||
// defined in typecheckRegex, and, you guessed it, uses regex to check for allowed
|
||||
// characters.
|
||||
func TypeSafetyCheck(name string, value string, argumentType string) error {
|
||||
if argumentType == "url" {
|
||||
return typeSafetyCheckUrl(name, value)
|
||||
}
|
||||
|
||||
return typeSafetyCheckRegex(name, value, argumentType)
|
||||
}
|
||||
|
||||
func typeSafetyCheckRegex(name string, value string, argumentType string) error {
|
||||
pattern, found := typecheckRegex[argumentType]
|
||||
|
||||
if !found {
|
||||
return errors.New("argument type not implemented " + argumentType)
|
||||
}
|
||||
|
||||
matches, _ := regexp.MatchString(pattern, value)
|
||||
|
||||
if !matches {
|
||||
log.WithFields(log.Fields{
|
||||
"name": name,
|
||||
"value": value,
|
||||
"type": argumentType,
|
||||
}).Warn("Arg type check safety failure")
|
||||
|
||||
return errors.New("invalid argument, doesn't match " + argumentType)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func typeSafetyCheckUrl(name string, value string) error {
|
||||
_, err := url.ParseRequestURI(value)
|
||||
|
||||
return err
|
||||
}
|
||||
69
internal/executor/arguments_test.go
Normal file
69
internal/executor/arguments_test.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package executor
|
||||
|
||||
import (
|
||||
config "github.com/OliveTin/OliveTin/internal/config"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSanitizeUnsafe(t *testing.T) {
|
||||
assert.Nil(t, TypeSafetyCheck("", "_zomg_ c:/ haxxor ' bobby tables && rm -rf ", "very_dangerous_raw_string"))
|
||||
}
|
||||
|
||||
func TestSanitizeUnimplemented(t *testing.T) {
|
||||
err := TypeSafetyCheck("", "I am a happy little argument", "greeting_type")
|
||||
|
||||
assert.NotNil(t, err, "Test an argument type that does not exist")
|
||||
}
|
||||
|
||||
func TestArgumentNameNumbers(t *testing.T) {
|
||||
a1 := config.Action{
|
||||
Title: "Do some tickles",
|
||||
Shell: "echo 'Tickling {{ person1name }}'",
|
||||
Arguments: []config.ActionArgument{
|
||||
{
|
||||
Name: "person1name",
|
||||
Type: "ascii",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
values := map[string]string{
|
||||
"person1name": "Fred",
|
||||
}
|
||||
|
||||
out, err := parseActionArguments(a1.Shell, values, &a1)
|
||||
|
||||
assert.Equal(t, "echo 'Tickling Fred'", out)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestArgumentNotProvided(t *testing.T) {
|
||||
a1 := config.Action{
|
||||
Title: "Do some tickles",
|
||||
Shell: "echo 'Tickling {{ personName }}'",
|
||||
Arguments: []config.ActionArgument{
|
||||
{
|
||||
Name: "person",
|
||||
Type: "ascii",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
values := map[string]string{}
|
||||
|
||||
out, err := parseActionArguments(a1.Shell, values, &a1)
|
||||
|
||||
assert.Equal(t, "", out)
|
||||
assert.Equal(t, err.Error(), "Required arg not provided: personName")
|
||||
}
|
||||
|
||||
func TestTypeSafetyCheckUrl(t *testing.T) {
|
||||
assert.Nil(t, TypeSafetyCheck("test1", "http://google.com", "url"), "Test URL: google.com")
|
||||
assert.Nil(t, TypeSafetyCheck("test2", "http://technowax.net:80?foo=bar", "url"), "Test URL: technowax.net with query arguments")
|
||||
assert.Nil(t, TypeSafetyCheck("test3", "http://localhost:80?foo=bar", "url"), "Test URL: localhost with query arguments")
|
||||
assert.NotNil(t, TypeSafetyCheck("test4", "http://lo host:80", "url"), "Test a badly formed URL")
|
||||
assert.NotNil(t, TypeSafetyCheck("test5", "12345", "url"), "Test a badly formed URL")
|
||||
assert.NotNil(t, TypeSafetyCheck("test6", "_!23;", "url"), "Test a badly formed URL")
|
||||
}
|
||||
@@ -1,29 +1,30 @@
|
||||
package executor
|
||||
|
||||
import (
|
||||
pb "github.com/jamesread/OliveTin/gen/grpc"
|
||||
acl "github.com/jamesread/OliveTin/internal/acl"
|
||||
config "github.com/jamesread/OliveTin/internal/config"
|
||||
pb "github.com/OliveTin/OliveTin/gen/grpc"
|
||||
acl "github.com/OliveTin/OliveTin/internal/acl"
|
||||
config "github.com/OliveTin/OliveTin/internal/config"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"context"
|
||||
"errors"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
"bytes"
|
||||
"context"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
typecheckRegex = map[string]string{
|
||||
"very_dangerous_raw_string": "",
|
||||
"int": "^[\\d]+$",
|
||||
"ascii": "^[a-zA-Z0-9]+$",
|
||||
"ascii_identifier": "^[a-zA-Z0-9\\-\\.\\_]+$",
|
||||
"ascii_sentence": "^[a-zA-Z0-9 \\,\\.]+$",
|
||||
}
|
||||
)
|
||||
// ExecutionRequest is a request to execute an action. It's passed to an
|
||||
// Executor. They're created from the grpcapi.
|
||||
type ExecutionRequest struct {
|
||||
ActionName string
|
||||
Arguments map[string]string
|
||||
Tags []string
|
||||
action *config.Action
|
||||
Cfg *config.Config
|
||||
AuthenticatedUser *acl.AuthenticatedUser
|
||||
logEntry *InternalLogEntry
|
||||
finalParsedCommand string
|
||||
}
|
||||
|
||||
// InternalLogEntry objects are created by an Executor, and represent the final
|
||||
// state of execution (even if the command is not executed). It's designed to be
|
||||
@@ -34,6 +35,7 @@ type InternalLogEntry struct {
|
||||
Stderr string
|
||||
TimedOut bool
|
||||
ExitCode int32
|
||||
Tags []string
|
||||
|
||||
/*
|
||||
The following two properties are obviously on Action normally, but it's useful
|
||||
@@ -44,71 +46,14 @@ type InternalLogEntry struct {
|
||||
ActionIcon string
|
||||
}
|
||||
|
||||
// ExecutionRequest is a request to execute an action. It's passed to an
|
||||
// Executor. They're created from the grpcapi.
|
||||
type ExecutionRequest struct {
|
||||
ActionName string
|
||||
Arguments map[string]string
|
||||
action *config.Action
|
||||
Cfg *config.Config
|
||||
User *acl.User
|
||||
logEntry *InternalLogEntry
|
||||
finalParsedCommand string
|
||||
}
|
||||
|
||||
type executorStep interface {
|
||||
Exec(*ExecutionRequest) bool
|
||||
}
|
||||
type executorStepFunc func(*ExecutionRequest) bool
|
||||
|
||||
// Executor represents a helper class for executing commands. It's main method
|
||||
// is ExecRequest
|
||||
type Executor struct {
|
||||
Logs []InternalLogEntry
|
||||
|
||||
chainOfCommand []executorStep
|
||||
}
|
||||
|
||||
// DefaultExecutor returns an Executor, with a sensible "chain of command" for
|
||||
// executing actions.
|
||||
func DefaultExecutor() *Executor {
|
||||
e := Executor{}
|
||||
e.chainOfCommand = []executorStep{
|
||||
stepFindAction{},
|
||||
stepACLCheck{},
|
||||
stepParseArgs{},
|
||||
stepLogStart{},
|
||||
stepExec{},
|
||||
stepLogFinish{},
|
||||
}
|
||||
|
||||
return &e
|
||||
}
|
||||
|
||||
type stepFindAction struct{}
|
||||
|
||||
func (s stepFindAction) Exec(req *ExecutionRequest) bool {
|
||||
actualAction := req.Cfg.FindAction(req.ActionName)
|
||||
|
||||
if actualAction == nil {
|
||||
log.WithFields(log.Fields{
|
||||
"actionName": req.ActionName,
|
||||
}).Warnf("Action not found")
|
||||
|
||||
req.logEntry.Stderr = "Action not found"
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
req.action = actualAction
|
||||
req.logEntry.ActionIcon = actualAction.Icon
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
type stepACLCheck struct{}
|
||||
|
||||
func (s stepACLCheck) Exec(req *ExecutionRequest) bool {
|
||||
return acl.IsAllowedExec(req.Cfg, req.User, req.action)
|
||||
chainOfCommand []executorStepFunc
|
||||
}
|
||||
|
||||
// ExecRequest processes an ExecutionRequest
|
||||
@@ -122,7 +67,7 @@ func (e *Executor) ExecRequest(req *ExecutionRequest) *pb.StartActionResponse {
|
||||
}
|
||||
|
||||
for _, step := range e.chainOfCommand {
|
||||
if !step.Exec(req) {
|
||||
if !step(req) {
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -142,34 +87,46 @@ func (e *Executor) ExecRequest(req *ExecutionRequest) *pb.StartActionResponse {
|
||||
}
|
||||
}
|
||||
|
||||
type stepLogStart struct{}
|
||||
// DefaultExecutor returns an Executor, with a sensible "chain of command" for
|
||||
// executing actions.
|
||||
func DefaultExecutor() *Executor {
|
||||
e := Executor{}
|
||||
e.chainOfCommand = []executorStepFunc{
|
||||
stepFindAction,
|
||||
stepACLCheck,
|
||||
stepParseArgs,
|
||||
stepLogStart,
|
||||
stepExec,
|
||||
stepLogFinish,
|
||||
}
|
||||
|
||||
func (e stepLogStart) Exec(req *ExecutionRequest) bool {
|
||||
log.WithFields(log.Fields{
|
||||
"title": req.action.Title,
|
||||
"timeout": req.action.Timeout,
|
||||
}).Infof("Action starting")
|
||||
return &e
|
||||
}
|
||||
|
||||
func stepFindAction(req *ExecutionRequest) bool {
|
||||
actualAction := req.Cfg.FindAction(req.ActionName)
|
||||
|
||||
if actualAction == nil {
|
||||
log.WithFields(log.Fields{
|
||||
"actionName": req.ActionName,
|
||||
}).Warnf("Action not found")
|
||||
|
||||
req.logEntry.Stderr = "Action not found"
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
req.action = actualAction
|
||||
req.logEntry.ActionIcon = actualAction.Icon
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
type stepLogFinish struct{}
|
||||
|
||||
func (e stepLogFinish) Exec(req *ExecutionRequest) bool {
|
||||
log.WithFields(log.Fields{
|
||||
"title": req.action.Title,
|
||||
"stdout": req.logEntry.Stdout,
|
||||
"stderr": req.logEntry.Stderr,
|
||||
"timedOut": req.logEntry.TimedOut,
|
||||
"exit": req.logEntry.ExitCode,
|
||||
}).Infof("Action finished")
|
||||
|
||||
return true
|
||||
func stepACLCheck(req *ExecutionRequest) bool {
|
||||
return acl.IsAllowedExec(req.Cfg, req.AuthenticatedUser, req.action)
|
||||
}
|
||||
|
||||
type stepParseArgs struct{}
|
||||
|
||||
func (e stepParseArgs) Exec(req *ExecutionRequest) bool {
|
||||
func stepParseArgs(req *ExecutionRequest) bool {
|
||||
var err error
|
||||
|
||||
req.finalParsedCommand, err = parseActionArguments(req.action.Shell, req.Arguments, req.action)
|
||||
@@ -185,21 +142,48 @@ func (e stepParseArgs) Exec(req *ExecutionRequest) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
type stepExec struct{}
|
||||
func stepLogStart(req *ExecutionRequest) bool {
|
||||
log.WithFields(log.Fields{
|
||||
"title": req.action.Title,
|
||||
"timeout": req.action.Timeout,
|
||||
}).Infof("Action starting")
|
||||
|
||||
func (e stepExec) Exec(req *ExecutionRequest) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func stepLogFinish(req *ExecutionRequest) bool {
|
||||
log.WithFields(log.Fields{
|
||||
"title": req.action.Title,
|
||||
"stdout": req.logEntry.Stdout,
|
||||
"stderr": req.logEntry.Stderr,
|
||||
"timedOut": req.logEntry.TimedOut,
|
||||
"exit": req.logEntry.ExitCode,
|
||||
}).Infof("Action finished")
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func wrapCommandInShell(ctx context.Context, finalParsedCommand string) *exec.Cmd {
|
||||
if runtime.GOOS == "windows" {
|
||||
return exec.CommandContext(ctx, "cmd", "/C", finalParsedCommand)
|
||||
}
|
||||
|
||||
return exec.CommandContext(ctx, "sh", "-c", finalParsedCommand)
|
||||
}
|
||||
|
||||
func stepExec(req *ExecutionRequest) bool {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(req.action.Timeout)*time.Second)
|
||||
defer cancel()
|
||||
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
|
||||
cmd := exec.CommandContext(ctx, "sh", "-c", req.finalParsedCommand)
|
||||
cmd := wrapCommandInShell(ctx, req.finalParsedCommand)
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
runerr := cmd.Run()
|
||||
|
||||
|
||||
req.logEntry.ExitCode = int32(cmd.ProcessState.ExitCode())
|
||||
req.logEntry.Stdout = stdout.String()
|
||||
req.logEntry.Stderr = stderr.String()
|
||||
@@ -212,91 +196,7 @@ func (e stepExec) Exec(req *ExecutionRequest) bool {
|
||||
req.logEntry.TimedOut = true
|
||||
}
|
||||
|
||||
req.logEntry.Tags = req.Tags
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func parseActionArguments(rawShellCommand string, values map[string]string, action *config.Action) (string, error) {
|
||||
log.WithFields(log.Fields{
|
||||
"cmd": rawShellCommand,
|
||||
}).Infof("Before Parse Args")
|
||||
|
||||
r := regexp.MustCompile("{{ *?([a-z]+?) *?}}")
|
||||
matches := r.FindAllStringSubmatch(rawShellCommand, -1)
|
||||
|
||||
for _, match := range matches {
|
||||
argValue, argProvided := values[match[1]]
|
||||
|
||||
if !argProvided {
|
||||
log.Infof("%v", values)
|
||||
return "", errors.New("Required arg not provided: " + match[1])
|
||||
}
|
||||
|
||||
err := typecheckActionArgument(match[1], argValue, action)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"name": match[1],
|
||||
"value": argValue,
|
||||
}).Debugf("Arg assigned")
|
||||
|
||||
rawShellCommand = strings.ReplaceAll(rawShellCommand, match[0], argValue)
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"cmd": rawShellCommand,
|
||||
}).Infof("After Parse Args")
|
||||
|
||||
return rawShellCommand, nil
|
||||
}
|
||||
|
||||
func typecheckActionArgument(name string, value string, action *config.Action) error {
|
||||
arg := action.FindArg(name)
|
||||
|
||||
if arg == nil {
|
||||
return errors.New("Action arg not defined: " + name)
|
||||
}
|
||||
|
||||
if len(arg.Choices) > 0 {
|
||||
return typecheckChoice(value, arg)
|
||||
}
|
||||
|
||||
return TypeSafetyCheck(name, value, arg.Type)
|
||||
}
|
||||
|
||||
func typecheckChoice(value string, arg *config.ActionArgument) error {
|
||||
for _, choice := range arg.Choices {
|
||||
if value == choice.Value {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return errors.New("argument value is not one of the predefined choices")
|
||||
}
|
||||
|
||||
// TypeSafetyCheck checks argument values match a specific type. The types are
|
||||
// defined in typecheckRegex, and, you guessed it, uses regex to check for allowed
|
||||
// characters.
|
||||
func TypeSafetyCheck(name string, value string, typ string) error {
|
||||
pattern, found := typecheckRegex[typ]
|
||||
|
||||
if !found {
|
||||
return errors.New("argument type not implemented " + typ)
|
||||
}
|
||||
|
||||
matches, _ := regexp.MatchString(pattern, value)
|
||||
|
||||
if !matches {
|
||||
log.WithFields(log.Fields{
|
||||
"name": name,
|
||||
"type": typ,
|
||||
"value": value,
|
||||
}).Warn("Arg type check safety failure")
|
||||
|
||||
return errors.New("invalid argument, doesn't match " + typ)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -4,14 +4,10 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
|
||||
acl "github.com/jamesread/OliveTin/internal/acl"
|
||||
config "github.com/jamesread/OliveTin/internal/config"
|
||||
acl "github.com/OliveTin/OliveTin/internal/acl"
|
||||
config "github.com/OliveTin/OliveTin/internal/config"
|
||||
)
|
||||
|
||||
func TestSanitizeUnsafe(t *testing.T) {
|
||||
assert.Nil(t, TypeSafetyCheck("", "_zomg_ c:/ haxxor ' bobby tables && rm -rf ", "very_dangerous_raw_string"))
|
||||
}
|
||||
|
||||
func testingExecutor() (*Executor, *config.Config) {
|
||||
e := DefaultExecutor()
|
||||
|
||||
@@ -38,9 +34,9 @@ func TestCreateExecutorAndExec(t *testing.T) {
|
||||
e, cfg := testingExecutor()
|
||||
|
||||
req := ExecutionRequest{
|
||||
ActionName: "Do some tickles",
|
||||
User: &acl.User{Username: "Mr Tickle"},
|
||||
Cfg: cfg,
|
||||
ActionName: "Do some tickles",
|
||||
AuthenticatedUser: &acl.AuthenticatedUser{Username: "Mr Tickle"},
|
||||
Cfg: cfg,
|
||||
Arguments: map[string]string{
|
||||
"person": "yourself",
|
||||
},
|
||||
@@ -68,3 +64,47 @@ func TestExecNonExistant(t *testing.T) {
|
||||
assert.Equal(t, int32(-1337), req.logEntry.ExitCode, "Log entry is set to an internal error code")
|
||||
assert.Equal(t, "", req.logEntry.ActionIcon, "Log entry icon wasnt found")
|
||||
}
|
||||
|
||||
func TestArgumentNameCamelCase(t *testing.T) {
|
||||
a1 := config.Action{
|
||||
Title: "Do some tickles",
|
||||
Shell: "echo 'Tickling {{ personName }}'",
|
||||
Arguments: []config.ActionArgument{
|
||||
{
|
||||
Name: "personName",
|
||||
Type: "ascii",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
values := map[string]string{
|
||||
"personName": "Fred",
|
||||
}
|
||||
|
||||
out, err := parseActionArguments(a1.Shell, values, &a1)
|
||||
|
||||
assert.Equal(t, "echo 'Tickling Fred'", out)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestArgumentNameSnakeCase(t *testing.T) {
|
||||
a1 := config.Action{
|
||||
Title: "Do some tickles",
|
||||
Shell: "echo 'Tickling {{ person_name }}'",
|
||||
Arguments: []config.ActionArgument{
|
||||
{
|
||||
Name: "person_name",
|
||||
Type: "ascii",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
values := map[string]string{
|
||||
"person_name": "Fred",
|
||||
}
|
||||
|
||||
out, err := parseActionArguments(a1.Shell, values, &a1)
|
||||
|
||||
assert.Equal(t, "echo 'Tickling Fred'", out)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
@@ -2,23 +2,25 @@ package grpcapi
|
||||
|
||||
import (
|
||||
ctx "context"
|
||||
pb "github.com/jamesread/OliveTin/gen/grpc"
|
||||
pb "github.com/OliveTin/OliveTin/gen/grpc"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"net"
|
||||
|
||||
acl "github.com/jamesread/OliveTin/internal/acl"
|
||||
config "github.com/jamesread/OliveTin/internal/config"
|
||||
executor "github.com/jamesread/OliveTin/internal/executor"
|
||||
acl "github.com/OliveTin/OliveTin/internal/acl"
|
||||
config "github.com/OliveTin/OliveTin/internal/config"
|
||||
executor "github.com/OliveTin/OliveTin/internal/executor"
|
||||
)
|
||||
|
||||
var (
|
||||
cfg *config.Config
|
||||
ex = executor.DefaultExecutor()
|
||||
)
|
||||
|
||||
type oliveTinAPI struct {
|
||||
pb.UnimplementedOliveTinApiServer
|
||||
|
||||
executor *executor.Executor
|
||||
}
|
||||
|
||||
func (api *oliveTinAPI) StartAction(ctx ctx.Context, req *pb.StartActionRequest) (*pb.StartActionResponse, error) {
|
||||
@@ -31,17 +33,17 @@ func (api *oliveTinAPI) StartAction(ctx ctx.Context, req *pb.StartActionRequest)
|
||||
}
|
||||
|
||||
execReq := executor.ExecutionRequest{
|
||||
ActionName: req.ActionName,
|
||||
Arguments: args,
|
||||
User: acl.UserFromContext(ctx),
|
||||
Cfg: cfg,
|
||||
ActionName: req.ActionName,
|
||||
Arguments: args,
|
||||
AuthenticatedUser: acl.UserFromContext(ctx, cfg),
|
||||
Cfg: cfg,
|
||||
}
|
||||
|
||||
return ex.ExecRequest(&execReq), nil
|
||||
return api.executor.ExecRequest(&execReq), nil
|
||||
}
|
||||
|
||||
func (api *oliveTinAPI) GetDashboardComponents(ctx ctx.Context, req *pb.GetDashboardComponentsRequest) (*pb.GetDashboardComponentsResponse, error) {
|
||||
user := acl.UserFromContext(ctx)
|
||||
user := acl.UserFromContext(ctx, cfg)
|
||||
|
||||
res := actionsCfgToPb(cfg.Actions, user)
|
||||
|
||||
@@ -59,7 +61,7 @@ func (api *oliveTinAPI) GetLogs(ctx ctx.Context, req *pb.GetLogsRequest) (*pb.Ge
|
||||
|
||||
// TODO Limit to 10 entries or something to prevent browser lag.
|
||||
|
||||
for _, logEntry := range ex.Logs {
|
||||
for _, logEntry := range api.executor.Logs {
|
||||
ret.Logs = append(ret.Logs, &pb.LogEntry{
|
||||
ActionTitle: logEntry.ActionTitle,
|
||||
ActionIcon: logEntry.ActionIcon,
|
||||
@@ -68,6 +70,7 @@ func (api *oliveTinAPI) GetLogs(ctx ctx.Context, req *pb.GetLogsRequest) (*pb.Ge
|
||||
Stderr: logEntry.Stderr,
|
||||
TimedOut: logEntry.TimedOut,
|
||||
ExitCode: logEntry.ExitCode,
|
||||
Tags: logEntry.Tags,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -93,8 +96,20 @@ func (api *oliveTinAPI) ValidateArgumentType(ctx ctx.Context, req *pb.ValidateAr
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (api *oliveTinAPI) WhoAmI(ctx ctx.Context, req *pb.WhoAmIRequest) (*pb.WhoAmIResponse, error) {
|
||||
user := acl.UserFromContext(ctx, cfg)
|
||||
|
||||
res := &pb.WhoAmIResponse{
|
||||
AuthenticatedUser: user.Username,
|
||||
}
|
||||
|
||||
log.Warnf("usergroup: %v", user.Usergroup)
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Start will start the GRPC API.
|
||||
func Start(globalConfig *config.Config) {
|
||||
func Start(globalConfig *config.Config, ex *executor.Executor) {
|
||||
cfg = globalConfig
|
||||
|
||||
lis, err := net.Listen("tcp", cfg.ListenAddressGrpcActions)
|
||||
@@ -104,7 +119,7 @@ func Start(globalConfig *config.Config) {
|
||||
}
|
||||
|
||||
grpcServer := grpc.NewServer()
|
||||
pb.RegisterOliveTinApiServer(grpcServer, newServer())
|
||||
pb.RegisterOliveTinApiServer(grpcServer, newServer(ex))
|
||||
|
||||
err = grpcServer.Serve(lis)
|
||||
|
||||
@@ -113,7 +128,8 @@ func Start(globalConfig *config.Config) {
|
||||
}
|
||||
}
|
||||
|
||||
func newServer() *oliveTinAPI {
|
||||
func newServer(ex *executor.Executor) *oliveTinAPI {
|
||||
server := oliveTinAPI{}
|
||||
server.executor = ex
|
||||
return &server
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@ package grpcapi
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
pb "github.com/jamesread/OliveTin/gen/grpc"
|
||||
acl "github.com/jamesread/OliveTin/internal/acl"
|
||||
config "github.com/jamesread/OliveTin/internal/config"
|
||||
pb "github.com/OliveTin/OliveTin/gen/grpc"
|
||||
acl "github.com/OliveTin/OliveTin/internal/acl"
|
||||
config "github.com/OliveTin/OliveTin/internal/config"
|
||||
)
|
||||
|
||||
func actionsCfgToPb(cfgActions []config.Action, user *acl.User) *pb.GetDashboardComponentsResponse {
|
||||
func actionsCfgToPb(cfgActions []config.Action, user *acl.AuthenticatedUser) *pb.GetDashboardComponentsResponse {
|
||||
res := &pb.GetDashboardComponentsResponse{}
|
||||
|
||||
for _, action := range cfgActions {
|
||||
@@ -23,7 +23,7 @@ func actionsCfgToPb(cfgActions []config.Action, user *acl.User) *pb.GetDashboard
|
||||
return res
|
||||
}
|
||||
|
||||
func actionCfgToPb(action config.Action, user *acl.User) *pb.Action {
|
||||
func actionCfgToPb(action config.Action, user *acl.AuthenticatedUser) *pb.Action {
|
||||
btn := pb.Action{
|
||||
Id: fmt.Sprintf("%x", md5.Sum([]byte(action.Title))),
|
||||
Title: action.Title,
|
||||
@@ -36,6 +36,7 @@ func actionCfgToPb(action config.Action, user *acl.User) *pb.Action {
|
||||
Name: cfgArg.Name,
|
||||
Title: cfgArg.Title,
|
||||
Type: cfgArg.Type,
|
||||
Description: cfgArg.Description,
|
||||
DefaultValue: cfgArg.Default,
|
||||
Choices: buildChoices(cfgArg.Choices),
|
||||
}
|
||||
|
||||
@@ -12,8 +12,9 @@ import (
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
pb "github.com/jamesread/OliveTin/gen/grpc"
|
||||
config "github.com/jamesread/OliveTin/internal/config"
|
||||
pb "github.com/OliveTin/OliveTin/gen/grpc"
|
||||
config "github.com/OliveTin/OliveTin/internal/config"
|
||||
"github.com/OliveTin/OliveTin/internal/executor"
|
||||
)
|
||||
|
||||
const bufSize = 1024 * 1024
|
||||
@@ -21,9 +22,11 @@ const bufSize = 1024 * 1024
|
||||
var lis *bufconn.Listener
|
||||
|
||||
func init() {
|
||||
ex := executor.DefaultExecutor()
|
||||
|
||||
lis = bufconn.Listen(bufSize)
|
||||
s := grpc.NewServer()
|
||||
pb.RegisterOliveTinApiServer(s, newServer())
|
||||
pb.RegisterOliveTinApiServer(s, newServer(ex))
|
||||
|
||||
go func() {
|
||||
if err := s.Serve(lis); err != nil {
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
package httpservers
|
||||
|
||||
import (
|
||||
config "github.com/jamesread/OliveTin/internal/config"
|
||||
config "github.com/OliveTin/OliveTin/internal/config"
|
||||
)
|
||||
|
||||
// StartServers will start 3 HTTP servers. The WebUI, the Rest API, and a proxy
|
||||
// for both of them.
|
||||
func StartServers(cfg *config.Config) {
|
||||
go startWebUIServer(cfg)
|
||||
go startRestAPIServer(cfg)
|
||||
|
||||
if cfg.UseSingleHTTPFrontend {
|
||||
StartSingleHTTPFrontend(cfg)
|
||||
go StartSingleHTTPFrontend(cfg)
|
||||
}
|
||||
|
||||
startRestAPIServer(cfg)
|
||||
}
|
||||
|
||||
@@ -5,20 +5,60 @@ import (
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"net/http"
|
||||
|
||||
gw "github.com/jamesread/OliveTin/gen/grpc"
|
||||
gw "github.com/OliveTin/OliveTin/gen/grpc"
|
||||
|
||||
cors "github.com/jamesread/OliveTin/internal/cors"
|
||||
|
||||
config "github.com/jamesread/OliveTin/internal/config"
|
||||
config "github.com/OliveTin/OliveTin/internal/config"
|
||||
cors "github.com/OliveTin/OliveTin/internal/cors"
|
||||
)
|
||||
|
||||
var (
|
||||
cfg *config.Config
|
||||
)
|
||||
|
||||
func parseHttpHeaderForAuth(req *http.Request) (string, string) {
|
||||
username, ok := req.Header[cfg.AuthHttpHeaderUsername]
|
||||
|
||||
if !ok {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
if cfg.AuthHttpHeaderUserGroup != "" {
|
||||
usergroup, ok := req.Header[cfg.AuthHttpHeaderUserGroup]
|
||||
|
||||
if ok {
|
||||
return username[0], usergroup[0]
|
||||
}
|
||||
}
|
||||
|
||||
return username[0], ""
|
||||
}
|
||||
|
||||
func parseRequestMetadata(ctx context.Context, req *http.Request) metadata.MD {
|
||||
username := ""
|
||||
usergroup := ""
|
||||
|
||||
if cfg.AuthJwtCookieName != "" {
|
||||
username, usergroup = parseJwtCookie(req)
|
||||
}
|
||||
|
||||
if cfg.AuthHttpHeaderUsername != "" {
|
||||
username, usergroup = parseHttpHeaderForAuth(req)
|
||||
}
|
||||
|
||||
md := metadata.Pairs(
|
||||
"username", username,
|
||||
"usergroup", usergroup,
|
||||
)
|
||||
|
||||
log.Debugf("jwt usable claims: %+v", md)
|
||||
|
||||
return md
|
||||
}
|
||||
|
||||
func startRestAPIServer(globalConfig *config.Config) error {
|
||||
cfg = globalConfig
|
||||
|
||||
@@ -32,6 +72,7 @@ func startRestAPIServer(globalConfig *config.Config) error {
|
||||
|
||||
// The JSONPb.EmitDefaults is necssary, so "empty" fields are returned in JSON.
|
||||
mux := runtime.NewServeMux(
|
||||
runtime.WithMetadata(parseRequestMetadata),
|
||||
runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.HTTPBodyMarshaler{
|
||||
Marshaler: &runtime.JSONPb{
|
||||
MarshalOptions: protojson.MarshalOptions{
|
||||
|
||||
67
internal/httpservers/restapi_auth_jwt.go
Normal file
67
internal/httpservers/restapi_auth_jwt.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package httpservers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func parseJwtToken(cookieValue string) (*jwt.Token, error) {
|
||||
return jwt.Parse(cookieValue, func(token *jwt.Token) (interface{}, error) {
|
||||
// Don't forget to validate the alg is what you expect:
|
||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
||||
}
|
||||
|
||||
// hmacSampleSecret is a []byte containing your secret, e.g. []byte("my_secret_key")
|
||||
return []byte(cfg.AuthJwtSecret), nil
|
||||
})
|
||||
}
|
||||
|
||||
func getClaimsFromJwtToken(cookieValue string) (jwt.MapClaims, error) {
|
||||
token, err := parseJwtToken(cookieValue)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("jwt parse failure: %v", err)
|
||||
return nil, errors.New("jwt parse failure")
|
||||
}
|
||||
|
||||
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
|
||||
return claims, nil
|
||||
} else {
|
||||
return nil, errors.New("jwt token isn't valid")
|
||||
}
|
||||
}
|
||||
|
||||
func lookupClaimValueOrDefault(claims jwt.MapClaims, key string, def string) string {
|
||||
if val, ok := claims[key]; ok {
|
||||
return fmt.Sprintf("%s", val)
|
||||
} else {
|
||||
return def
|
||||
}
|
||||
}
|
||||
|
||||
func parseJwtCookie(request *http.Request) (string, string) {
|
||||
cookie, err := request.Cookie(cfg.AuthJwtCookieName)
|
||||
|
||||
if err != nil {
|
||||
log.Debugf("jwt cookie check %v name: %v", err, cfg.AuthJwtCookieName)
|
||||
return "", ""
|
||||
}
|
||||
|
||||
claims, err := getClaimsFromJwtToken(cookie.Value)
|
||||
|
||||
log.Debugf("jwt claims data: %+v", claims)
|
||||
|
||||
if err != nil {
|
||||
log.Warnf("jwt claim error: %+v", err)
|
||||
return "", ""
|
||||
}
|
||||
|
||||
username := lookupClaimValueOrDefault(claims, cfg.AuthJwtClaimUsername, "")
|
||||
usergroup := lookupClaimValueOrDefault(claims, cfg.AuthJwtClaimUserGroup, "")
|
||||
|
||||
return username, usergroup
|
||||
}
|
||||
@@ -9,7 +9,7 @@ away, and several other issues.
|
||||
*/
|
||||
|
||||
import (
|
||||
config "github.com/jamesread/OliveTin/internal/config"
|
||||
config "github.com/OliveTin/OliveTin/internal/config"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
@@ -32,12 +32,12 @@ func StartSingleHTTPFrontend(cfg *config.Config) {
|
||||
mux := http.NewServeMux()
|
||||
|
||||
mux.HandleFunc("/api/", func(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debugf("api req: %v", r.URL)
|
||||
log.Debugf("api req: %q", r.URL)
|
||||
apiProxy.ServeHTTP(w, r)
|
||||
})
|
||||
|
||||
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debugf("ui req: %v", r.URL)
|
||||
log.Debugf("ui req: %q", r.URL)
|
||||
webuiProxy.ServeHTTP(w, r)
|
||||
})
|
||||
|
||||
|
||||
@@ -2,27 +2,31 @@ package httpservers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
// cors "github.com/jamesread/OliveTin/internal/cors"
|
||||
// cors "github.com/OliveTin/OliveTin/internal/cors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
config "github.com/jamesread/OliveTin/internal/config"
|
||||
updatecheck "github.com/jamesread/OliveTin/internal/updatecheck"
|
||||
config "github.com/OliveTin/OliveTin/internal/config"
|
||||
updatecheck "github.com/OliveTin/OliveTin/internal/updatecheck"
|
||||
)
|
||||
|
||||
type webUISettings struct {
|
||||
Rest string
|
||||
ThemeName string
|
||||
HideNavigation bool
|
||||
ShowFooter bool
|
||||
ShowNavigation bool
|
||||
ShowNewVersions bool
|
||||
AvailableVersion string
|
||||
CurrentVersion string
|
||||
ShowNewVersions bool
|
||||
PageTitle string
|
||||
}
|
||||
|
||||
func findWebuiDir() string {
|
||||
directoriesToSearch := []string{
|
||||
"./webui",
|
||||
"/usr/share/OliveTin/webui/",
|
||||
"/var/www/OliveTin/",
|
||||
"/var/www/olivetin/",
|
||||
"/etc/OliveTin/webui/",
|
||||
}
|
||||
@@ -43,19 +47,15 @@ func findWebuiDir() string {
|
||||
}
|
||||
|
||||
func generateWebUISettings(w http.ResponseWriter, r *http.Request) {
|
||||
restAddress := ""
|
||||
|
||||
if !cfg.UseSingleHTTPFrontend {
|
||||
restAddress = cfg.ExternalRestAddress
|
||||
}
|
||||
|
||||
jsonRet, _ := json.Marshal(webUISettings{
|
||||
Rest: restAddress + "/api/",
|
||||
Rest: cfg.ExternalRestAddress + "/api/",
|
||||
ThemeName: cfg.ThemeName,
|
||||
HideNavigation: cfg.HideNavigation,
|
||||
ShowFooter: cfg.ShowFooter,
|
||||
ShowNavigation: cfg.ShowNavigation,
|
||||
ShowNewVersions: cfg.ShowNewVersions,
|
||||
AvailableVersion: updatecheck.AvailableVersion,
|
||||
CurrentVersion: updatecheck.CurrentVersion,
|
||||
ShowNewVersions: cfg.ShowNewVersions,
|
||||
PageTitle: cfg.PageTitle,
|
||||
})
|
||||
|
||||
_, err := w.Write([]byte(jsonRet))
|
||||
|
||||
50
internal/oncron/cron.go
Normal file
50
internal/oncron/cron.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package oncron
|
||||
|
||||
import (
|
||||
"github.com/OliveTin/OliveTin/internal/acl"
|
||||
"github.com/OliveTin/OliveTin/internal/config"
|
||||
"github.com/OliveTin/OliveTin/internal/executor"
|
||||
"github.com/robfig/cron/v3"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func Schedule(cfg *config.Config, ex *executor.Executor) {
|
||||
scheduler := cron.New(cron.WithSeconds())
|
||||
|
||||
for _, action := range cfg.Actions {
|
||||
for _, cronline := range action.ExecOnCron {
|
||||
scheduleAction(cfg, scheduler, cronline, ex, action)
|
||||
}
|
||||
}
|
||||
|
||||
scheduler.Start()
|
||||
}
|
||||
|
||||
func scheduleAction(cfg *config.Config, scheduler *cron.Cron, cronline string, ex *executor.Executor, action config.Action) {
|
||||
log.WithFields(log.Fields{
|
||||
"action": action.Title,
|
||||
"cronline": cronline,
|
||||
}).Infof("Scheduling Action for cron")
|
||||
|
||||
_, err := scheduler.AddFunc(cronline, func() {
|
||||
req := &executor.ExecutionRequest{
|
||||
ActionName: action.Title,
|
||||
Cfg: cfg,
|
||||
Tags: []string{"cron"},
|
||||
AuthenticatedUser: &acl.AuthenticatedUser{
|
||||
Username: "cron",
|
||||
},
|
||||
}
|
||||
|
||||
ex.ExecRequest(req)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"action": action.Title,
|
||||
"cronError": err,
|
||||
}).Errorf("CRON schedule error")
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
32
internal/onstartup/startup.go
Normal file
32
internal/onstartup/startup.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package onstartup
|
||||
|
||||
import (
|
||||
"github.com/OliveTin/OliveTin/internal/acl"
|
||||
config "github.com/OliveTin/OliveTin/internal/config"
|
||||
"github.com/OliveTin/OliveTin/internal/executor"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func Execute(cfg *config.Config, ex *executor.Executor) {
|
||||
user := &acl.AuthenticatedUser{
|
||||
Username: "startup-user",
|
||||
}
|
||||
|
||||
for _, action := range cfg.Actions {
|
||||
if action.ExecOnStartup {
|
||||
log.WithFields(log.Fields{
|
||||
"action": action.Title,
|
||||
}).Infof("Startup action")
|
||||
|
||||
req := &executor.ExecutionRequest{
|
||||
ActionName: action.Title,
|
||||
Arguments: nil,
|
||||
Cfg: cfg,
|
||||
Tags: []string{"startup"},
|
||||
AuthenticatedUser: user,
|
||||
}
|
||||
|
||||
ex.ExecRequest(req)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,14 +3,15 @@ package updatecheck
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"github.com/denisbrodbeck/machineid"
|
||||
"github.com/go-co-op/gocron"
|
||||
config "github.com/jamesread/OliveTin/internal/config"
|
||||
"errors"
|
||||
config "github.com/OliveTin/OliveTin/internal/config"
|
||||
"github.com/google/uuid"
|
||||
"github.com/robfig/cron/v3"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
type updateRequest struct {
|
||||
@@ -18,7 +19,8 @@ type updateRequest struct {
|
||||
CurrentCommit string
|
||||
OS string
|
||||
Arch string
|
||||
MachineID string
|
||||
InstallationID string
|
||||
InContainer bool
|
||||
}
|
||||
|
||||
// AvailableVersion is updated when checking with the update service.
|
||||
@@ -27,20 +29,51 @@ var AvailableVersion = "none"
|
||||
// CurrentVersion is set by the main cmd (which is in tern set as a compile constant)
|
||||
var CurrentVersion = "?"
|
||||
|
||||
func machineID() string {
|
||||
v, err := machineid.ProtectedID("OliveTin")
|
||||
func installationID(filename string) string {
|
||||
var content string
|
||||
contentBytes, err := ioutil.ReadFile(filename)
|
||||
|
||||
if err != nil {
|
||||
log.Warnf("Error getting machine ID: %v", err)
|
||||
return "?"
|
||||
fileHandle, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
|
||||
|
||||
if err != nil {
|
||||
log.Warnf("Could not read + create installation ID file: %v", err)
|
||||
return "cant-create"
|
||||
}
|
||||
|
||||
content = uuid.NewString()
|
||||
fileHandle.WriteString(content)
|
||||
fileHandle.Close()
|
||||
} else {
|
||||
content = string(contentBytes)
|
||||
|
||||
_, err := uuid.Parse(content)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("Invalid installation ID, %v", err)
|
||||
content = "invalid-installation-id"
|
||||
}
|
||||
}
|
||||
|
||||
return v
|
||||
log.WithFields(log.Fields{
|
||||
"content": content,
|
||||
"from": filename,
|
||||
}).Infof("Installation ID")
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
func isInContainer() bool {
|
||||
if _, err := os.Stat("/.dockerenv"); errors.Is(err, os.ErrNotExist) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// StartUpdateChecker will start a job that runs periodically, checking
|
||||
// for updates.
|
||||
func StartUpdateChecker(currentVersion string, currentCommit string, cfg *config.Config) {
|
||||
func StartUpdateChecker(currentVersion string, currentCommit string, cfg *config.Config, configDir string) {
|
||||
CurrentVersion = currentVersion
|
||||
|
||||
if !cfg.CheckForUpdates {
|
||||
@@ -53,16 +86,23 @@ func StartUpdateChecker(currentVersion string, currentCommit string, cfg *config
|
||||
CurrentCommit: currentCommit,
|
||||
OS: runtime.GOOS,
|
||||
Arch: runtime.GOARCH,
|
||||
MachineID: machineID(),
|
||||
InstallationID: installationID(configDir + "/installation-id.txt"),
|
||||
InContainer: isInContainer(),
|
||||
}
|
||||
|
||||
s := gocron.NewScheduler(time.UTC)
|
||||
s := cron.New(cron.WithSeconds())
|
||||
|
||||
s.Every(7).Days().Do(func() {
|
||||
// Several values have been tried here.
|
||||
// 1st: Every 24h - very spammy.
|
||||
// 2nd: Every 7d - (168 hours - much more reasonable, but it checks in at the same time/day each week.
|
||||
// Current: Every 100h is not so spammy, and has the advantage that the checkin time "shifts" hours.
|
||||
s.AddFunc("@every 100h", func() {
|
||||
actualCheckForUpdate(payload)
|
||||
})
|
||||
|
||||
s.StartAsync()
|
||||
go actualCheckForUpdate(payload) // On startup
|
||||
|
||||
go s.Start()
|
||||
}
|
||||
|
||||
func doRequest(jsonUpdateRequest []byte) string {
|
||||
@@ -92,6 +132,8 @@ func doRequest(jsonUpdateRequest []byte) string {
|
||||
func actualCheckForUpdate(payload updateRequest) {
|
||||
jsonUpdateRequest, err := json.Marshal(payload)
|
||||
|
||||
log.Debugf("Update request payload: %+v", payload)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("Update check failed %v", err)
|
||||
return
|
||||
|
||||
BIN
var/manpage/OliveTin.1.gz
Normal file
BIN
var/manpage/OliveTin.1.gz
Normal file
Binary file not shown.
7
var/openrc/OliveTin
Executable file
7
var/openrc/OliveTin
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/sbin/openrc-run
|
||||
|
||||
name=$RC_SVCNAME
|
||||
description="OliveTin"
|
||||
command="/usr/local/bin/OliveTin"
|
||||
pidfile="/run/${RC_SVCNAME}.pid"
|
||||
command_background=true
|
||||
14
var/tekton/gobuilder/Dockerfile
Normal file
14
var/tekton/gobuilder/Dockerfile
Normal file
@@ -0,0 +1,14 @@
|
||||
FROM fedora
|
||||
RUN dnf install -v go -y --exclude=iputils
|
||||
RUN pwd
|
||||
RUN ls -l
|
||||
COPY go.mod /workspace/
|
||||
COPY go.sum /workspace/
|
||||
WORKDIR /workspace
|
||||
RUN go install -v "github.com/bufbuild/buf/cmd/buf"
|
||||
RUN go install -v "github.com/fzipp/gocyclo/cmd/gocyclo"
|
||||
RUN go install -v "github.com/go-critic/go-critic/cmd/gocritic"
|
||||
RUN go install -v "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway"
|
||||
RUN go install -v "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2"
|
||||
RUN go install -v "google.golang.org/grpc/cmd/protoc-gen-go-grpc"
|
||||
RUN go install -v "google.golang.org/protobuf/cmd/protoc-gen-go"
|
||||
@@ -16,7 +16,24 @@
|
||||
|
||||
<body>
|
||||
<main title = "main content">
|
||||
<fieldset id = "sectionSwitcher" title = "Sections">
|
||||
<div id = "perma-widget" hidden>
|
||||
<div id = "sidebar-toggle-wrapper">
|
||||
<label for = "sidebar-toggler" id = "sidebar-toggler-button" title = "Toggle sidebar" tabindex = "0">☰</label>
|
||||
</div>
|
||||
<h1 id = "page-title">OliveTin</h1>
|
||||
</div>
|
||||
|
||||
|
||||
<div id = "content-sidebar">
|
||||
<input type = "checkbox" id = "sidebar-toggler" hidden checked />
|
||||
<aside>
|
||||
<ul>
|
||||
<li>Foo</li>
|
||||
<li>Bar</li>
|
||||
</ul>
|
||||
</aside>
|
||||
</div>
|
||||
<fieldset id = "section-switcher" title = "Sections">
|
||||
<button id = "showActions">Actions</button>
|
||||
<button id = "showLogs">Logs</button>
|
||||
</fieldset>
|
||||
@@ -35,7 +52,7 @@
|
||||
</section>
|
||||
|
||||
<section id = "contentActions" title = "Actions" hidden >
|
||||
<fieldset id = "rootGroup" title = "Dashboard of buttons">
|
||||
<fieldset id = "root-group" title = "Dashboard of buttons">
|
||||
</fieldset>
|
||||
</section>
|
||||
|
||||
@@ -50,12 +67,12 @@
|
||||
<a href = "https://docs.olivetin.app" target = "_new">Documentation</a> |
|
||||
<a href = "https://github.com/OliveTin/OliveTin/issues/new/choose" target = "_new">Raise an issue on GitHub</a> |
|
||||
<span id = "currentVersion">Version: ?</p>
|
||||
<a id = "availableVersion" href = "http://olivetin.app" target = "_blank" hidden>?</a>
|
||||
<a id = "available-version" href = "http://olivetin.app" target = "_blank" hidden>?</a>
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<template id = "tplArgumentForm">
|
||||
<form class = "actionArguments">
|
||||
<form class = "action-arguments">
|
||||
<div class = "wrapper">
|
||||
<div>
|
||||
<span class = "icon" role = "icon"></span>
|
||||
@@ -80,12 +97,12 @@
|
||||
</template>
|
||||
|
||||
<template id = "tplLogRow">
|
||||
<tr class = "logRow">
|
||||
<tr class = "log-row">
|
||||
<td class = "timestamp">?</td>
|
||||
<td>
|
||||
<span class = "icon" role = "icon"></span>
|
||||
<span class = "content">?</span>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>stdout</summary>
|
||||
<pre class = "stdout">
|
||||
@@ -100,8 +117,9 @@
|
||||
</pre>
|
||||
</details>
|
||||
|
||||
<div class = "tags"></div>
|
||||
</td>
|
||||
<td class = "exitCode">?</td>
|
||||
<td class = "exit-code">?</td>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
@@ -117,9 +135,9 @@
|
||||
|
||||
const domErr = document.createElement('div')
|
||||
domErr.classList.add('error')
|
||||
domErr.innerHTML = '<h1>Error ' + friendlyType + '</h1><p>' + message + "</p><p><a href = 'http://docs.olivetin.app/troubleshooting.html' target = 'blank'/>OliveTin Documentation</a></p>"
|
||||
domErr.innerHTML = '<h1>Error ' + friendlyType + '</h1><p>' + message + "</p><p><a href = 'http://docs.olivetin.app/err-" + type + ".html' target = 'blank'/>" + type + " error in OliveTin Documentation</a></p>"
|
||||
|
||||
document.getElementById('rootGroup').appendChild(domErr)
|
||||
document.getElementById('root-group').appendChild(domErr)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -84,13 +84,13 @@ class ActionButton extends window.HTMLElement {
|
||||
marshalLogsJsonToHtml({ logs: [json.logEntry] })
|
||||
|
||||
if (json.logEntry.timedOut) {
|
||||
this.onActionResult('actionTimeout', 'Timed out')
|
||||
this.onActionResult('action-timeout', 'Timed out')
|
||||
} else if (json.logEntry.exitCode === -1337) {
|
||||
this.onActionError('Error')
|
||||
} else if (json.logEntry.exitCode !== 0) {
|
||||
this.onActionResult('actionNonZeroExit', 'Exit code ' + json.logEntry.exitCode)
|
||||
this.onActionResult('action-nonzero-exit', 'Exit code ' + json.logEntry.exitCode)
|
||||
} else {
|
||||
this.onActionResult('actionSuccess', 'Success!')
|
||||
this.onActionResult('action-success', 'Success!')
|
||||
}
|
||||
}).catch(err => {
|
||||
this.onActionError(err)
|
||||
@@ -113,10 +113,10 @@ class ActionButton extends window.HTMLElement {
|
||||
this.btn.disabled = false
|
||||
this.isWaiting = false
|
||||
this.updateDom()
|
||||
this.btn.classList.add('actionFailed')
|
||||
this.btn.classList.add('action-failed')
|
||||
|
||||
setTimeout(() => {
|
||||
this.btn.classList.remove('actionFailed')
|
||||
this.btn.classList.remove('action-failed')
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
@@ -139,13 +139,13 @@ class ActionButton extends window.HTMLElement {
|
||||
updateDom () {
|
||||
if (this.temporaryStatusMessage != null) {
|
||||
this.domTitle.innerText = this.temporaryStatusMessage
|
||||
this.domTitle.classList.add('temporaryStatusMessage')
|
||||
this.domTitle.classList.add('temporary-status-message')
|
||||
this.isWaiting = false
|
||||
this.disabled = false
|
||||
|
||||
setTimeout(() => {
|
||||
this.temporaryStatusMessage = null
|
||||
this.domTitle.classList.remove('temporaryStatusMessage')
|
||||
this.domTitle.classList.remove('temporary-status-message')
|
||||
this.updateDom()
|
||||
}, 2000)
|
||||
} else if (this.isWaiting) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
class ArgumentForm extends window.HTMLElement {
|
||||
setup (json, callback) {
|
||||
this.setAttribute('class', 'actionArguments')
|
||||
this.setAttribute('class', 'action-arguments')
|
||||
|
||||
this.constructTemplate()
|
||||
this.domTitle.innerText = json.title
|
||||
@@ -64,6 +64,7 @@ class ArgumentForm extends window.HTMLElement {
|
||||
|
||||
domFieldWrapper.appendChild(this.createDomLabel(arg))
|
||||
domFieldWrapper.appendChild(this.createDomInput(arg))
|
||||
domFieldWrapper.appendChild(this.createDomDescription(arg))
|
||||
|
||||
this.domArgs.appendChild(domFieldWrapper)
|
||||
}
|
||||
@@ -130,6 +131,14 @@ class ArgumentForm extends window.HTMLElement {
|
||||
return domEl
|
||||
}
|
||||
|
||||
createDomDescription (arg) {
|
||||
const domArgumentDescription = document.createElement('span')
|
||||
domArgumentDescription.classList.add('argument-description')
|
||||
domArgumentDescription.innerText = arg.description
|
||||
|
||||
return domArgumentDescription
|
||||
}
|
||||
|
||||
createSelectOption (choice) {
|
||||
const domEl = document.createElement('option')
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ export function marshalActionButtonsJsonToHtml (json) {
|
||||
htmlButton = document.createElement('action-button')
|
||||
htmlButton.constructFromJson(jsonButton)
|
||||
|
||||
document.getElementById('rootGroup').appendChild(htmlButton)
|
||||
document.getElementById('root-group').appendChild(htmlButton)
|
||||
} else {
|
||||
htmlButton.updateFromJson(jsonButton)
|
||||
htmlButton.updateDom()
|
||||
@@ -55,7 +55,15 @@ export function marshalLogsJsonToHtml (json) {
|
||||
row.querySelector('.icon').innerHTML = logEntry.actionIcon
|
||||
row.querySelector('pre.stdout').innerText = logEntry.stdout
|
||||
row.querySelector('pre.stderr').innerText = logEntry.stderr
|
||||
row.querySelector('.exitCode').innerText = logTableExitCode
|
||||
row.querySelector('.exit-code').innerText = logTableExitCode
|
||||
|
||||
for (const tag of logEntry.tags) {
|
||||
const domTag = document.createElement('span')
|
||||
domTag.classList.add('tag')
|
||||
domTag.innerText = tag
|
||||
|
||||
row.querySelector('.tags').append(domTag)
|
||||
}
|
||||
|
||||
document.querySelector('#logTableBody').prepend(row)
|
||||
}
|
||||
|
||||
@@ -58,11 +58,18 @@ function processWebuiSettingsJson (settings) {
|
||||
document.querySelector('#currentVersion').innerText = 'Version: ' + settings.CurrentVersion
|
||||
|
||||
if (settings.ShowNewVersions && settings.AvailableVersion !== 'none') {
|
||||
document.querySelector('#availableVersion').innerText = 'New Version Available: ' + settings.AvailableVersion
|
||||
document.querySelector('#availableVersion').hidden = false
|
||||
document.querySelector('#available-version').innerText = 'New Version Available: ' + settings.AvailableVersion
|
||||
document.querySelector('#available-version').hidden = false
|
||||
}
|
||||
|
||||
document.querySelector('#sectionSwitcher').hidden = settings.HideNavigation
|
||||
document.querySelector('#section-switcher').hidden = !settings.ShowNavigation
|
||||
document.querySelector('footer[title="footer"]').hidden = !settings.ShowFooter
|
||||
|
||||
if (settings.PageTitle) {
|
||||
document.title = settings.PageTitle
|
||||
const titleElem = document.querySelector('#page-title')
|
||||
if (titleElem) titleElem.innerText = settings.PageTitle
|
||||
}
|
||||
}
|
||||
|
||||
function main () {
|
||||
|
||||
5743
webui/package-lock.json
generated
Normal file
5743
webui/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -5,13 +5,13 @@
|
||||
"repository": "http://github.com/OliveTin/OliveTin",
|
||||
"main": "main.js",
|
||||
"devDependencies": {
|
||||
"stylelint": "^13.13.0",
|
||||
"stylelint-config-standard": "^22.0.0",
|
||||
"eslint": "^7.25.0",
|
||||
"eslint-config-standard": "^16.0.2",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^4.3.1"
|
||||
"eslint-plugin-promise": "^4.3.1",
|
||||
"stylelint": "^14.5.3",
|
||||
"stylelint-config-standard": "^25.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
|
||||
143
webui/style.css
143
webui/style.css
@@ -11,7 +11,7 @@ fieldset {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
fieldset#rootGroup {
|
||||
fieldset#root-group {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||
grid-template-rows: auto auto auto auto;
|
||||
@@ -20,11 +20,79 @@ fieldset#rootGroup {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
#sidebar-toggle-wrapper {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
h1 {
|
||||
display: inline;
|
||||
padding-left: 1em;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
label#sidebar-toggler-button {
|
||||
top: 1em;
|
||||
left: 0.5em;
|
||||
height: 2em;
|
||||
width: 2em;
|
||||
border-radius: 50%;
|
||||
background-color: white;
|
||||
text-align: center;
|
||||
display: inline-grid;
|
||||
place-items: center;
|
||||
padding: 0;
|
||||
box-shadow: 0 0 5px 0 #444;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
label#sidebar-toggler-button:hover,
|
||||
label#sidebar-toggler-button:focus {
|
||||
color: black;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
aside {
|
||||
position: absolute;
|
||||
width: 180px;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
padding-top: 4em;
|
||||
transition: 0.5s ease;
|
||||
background-color: white;
|
||||
border: 0 0 10px 0;
|
||||
box-shadow: 0 0 10px 0 #444;
|
||||
}
|
||||
|
||||
input:checked ~ aside {
|
||||
left: -250px;
|
||||
}
|
||||
|
||||
aside ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
aside ul li {
|
||||
list-style: none;
|
||||
text-align: left;
|
||||
padding-left: 1em;
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.5em;
|
||||
border-bottom: 1px inset black;
|
||||
}
|
||||
|
||||
aside ul li:hover {
|
||||
color: black;
|
||||
background-color: #efefef;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
table {
|
||||
background-color: white;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
box-shadow: 0 0 10px 0 #444;
|
||||
box-shadow: 0 0 5px 0 #444;
|
||||
}
|
||||
|
||||
th,
|
||||
@@ -53,7 +121,7 @@ span[role="icon"] {
|
||||
}
|
||||
|
||||
form span[role="icon"],
|
||||
tr.logRow span[role="icon"] {
|
||||
tr.log-row span[role="icon"] {
|
||||
display: inline-block;
|
||||
padding-right: 0.2em;
|
||||
}
|
||||
@@ -63,7 +131,7 @@ tr.logRow span[role="icon"] {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.title.temporaryStatusMessage {
|
||||
.title.temporary-status-message {
|
||||
color: gray;
|
||||
}
|
||||
|
||||
@@ -117,13 +185,13 @@ input[type="submit"]:disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
fieldset#sectionSwitcher {
|
||||
fieldset#section-switcher {
|
||||
border: 0;
|
||||
text-align: right;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
fieldset#sectionSwitcher button {
|
||||
fieldset#section-switcher button {
|
||||
padding: 1em;
|
||||
color: black;
|
||||
display: table-cell;
|
||||
@@ -135,60 +203,60 @@ fieldset#sectionSwitcher button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
fieldset#rootGroup action-button button {
|
||||
fieldset#root-group action-button button {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
fieldset#sectionSwitcher button:first-child {
|
||||
fieldset#section-switcher button:first-child {
|
||||
border-radius: 1em 0 0 1em;
|
||||
}
|
||||
|
||||
fieldset#sectionSwitcher button:last-child {
|
||||
fieldset#section-switcher button:last-child {
|
||||
border-radius: 0 1em 1em 0;
|
||||
}
|
||||
|
||||
button.activeSection {
|
||||
button.active-section {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Button animations */
|
||||
|
||||
.actionFailed {
|
||||
animation: kfActionFailed 1s;
|
||||
.action-failed {
|
||||
animation: kf-action-failed 1s;
|
||||
}
|
||||
|
||||
@keyframes kfActionFailed {
|
||||
@keyframes kf-action-failed {
|
||||
0% { background-color: black; }
|
||||
20% { background-color: red; }
|
||||
0% { background-color: inherit; }
|
||||
}
|
||||
|
||||
.actionSuccess {
|
||||
animation: kfActionSuccess 1s;
|
||||
.action-success {
|
||||
animation: kf-action-success 1s;
|
||||
}
|
||||
|
||||
@keyframes kfActionSuccess {
|
||||
@keyframes kf-action-success {
|
||||
0% { background-color: black; }
|
||||
20% { background-color: limegreen; }
|
||||
0% { background-color: inherit; }
|
||||
}
|
||||
|
||||
.actionNonZeroExit {
|
||||
animation: kfActionNonZeroExit 1s;
|
||||
.action-nonzero-exit {
|
||||
animation: kf-action-nonzero-exit 1s;
|
||||
}
|
||||
|
||||
@keyframes kfActionNonZeroExit {
|
||||
@keyframes kf-action-nonzero-exit {
|
||||
0% { background-color: black; }
|
||||
20% { background-color: orange; }
|
||||
0% { background-color: inherit; }
|
||||
}
|
||||
|
||||
.actionTimeout {
|
||||
animation: kfActionTimeout 1s;
|
||||
.action-timeout {
|
||||
animation: kf-action-timeout 1s;
|
||||
}
|
||||
|
||||
@keyframes kfActionTimeout {
|
||||
@keyframes kf-action-timeout {
|
||||
0% { background-color: black; }
|
||||
20% { background-color: cyan; }
|
||||
0% { background-color: inherit; }
|
||||
@@ -230,7 +298,7 @@ details[open] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
form.actionArguments {
|
||||
form.action-arguments {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
@@ -257,6 +325,15 @@ label {
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
#perma-widget {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#perma-widget label {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
input {
|
||||
padding: 0.6em;
|
||||
}
|
||||
@@ -274,14 +351,18 @@ form input[type="submit"]:first-child {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
button[name=cancel]:hover {
|
||||
button[name="cancel"]:hover {
|
||||
background-color: salmon;
|
||||
}
|
||||
|
||||
input[name=start]:hover {
|
||||
input[name="start"]:hover {
|
||||
background-color: #aceaac;
|
||||
}
|
||||
|
||||
span.argument-description {
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
form div.buttons {
|
||||
text-align: right;
|
||||
}
|
||||
@@ -292,7 +373,7 @@ pre {
|
||||
min-height: 1em;
|
||||
}
|
||||
|
||||
td.exitCode {
|
||||
td.exit-code {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -300,19 +381,25 @@ input.invalid {
|
||||
background-color: salmon;
|
||||
}
|
||||
|
||||
#availableVersion {
|
||||
#available-version {
|
||||
background-color: #aceaac;
|
||||
padding: 0.2em;
|
||||
border-radius: 1em;
|
||||
}
|
||||
|
||||
span.tag {
|
||||
background-color: lightgray;
|
||||
border-radius: 0.6em;
|
||||
padding: 0.2em;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: #333;
|
||||
color: white;
|
||||
}
|
||||
|
||||
form.actionArguments {
|
||||
form.action-arguments {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user