Compare commits

..

8 Commits

Author SHA1 Message Date
Jacob Weinstock
b3726acedf Move all glue scripts to bash:
By using `/usr/bin/env sh` I needed to ignore some
shell checks. By moving to bash, those shell checks can
be re-enabled.

Signed-off-by: Jacob Weinstock <jakobweinstock@gmail.com>
2021-08-19 11:03:31 -06:00
Jacob Weinstock
0ff1d633cd Make Hook the default OSIE:
With the recent update in Hook to publish the kernel and initrd
we can make make hook the default in the sandbox. Original OSIE
can still be used by updating deploy/compose/.env and setting
OSIE_DOWNLOAD_URL to an OSIE URL and TINKERBELL_USE_HOOK to false.
Currently only an x86_64 Hook is published so only x86_64 machines
can be provisioned with the sandbox using Hook.

Signed-off-by: Jacob Weinstock <jakobweinstock@gmail.com>
2021-08-19 10:46:24 -06:00
Manuel Mendez
6ea787f947 Add in repo DCO file
Signed-off-by: Manuel Mendez <mmendez@equinix.com>
2021-08-19 10:46:24 -06:00
Manuel Mendez
0b716b4720 Add CONTRIBUTING.md
Signed-off-by: Manuel Mendez <mmendez@equinix.com>
2021-08-19 10:46:24 -06:00
Jacob Weinstock
afc878ad88 Add Terraform with Equinix Metal:
This gets the Tinkerbell Sandbox up and running with
Terraform on Equinix Metal.

Signed-off-by: Jacob Weinstock <jakobweinstock@gmail.com>
2021-08-19 10:46:16 -06:00
Jacob Weinstock
d6af9a49af Reorg directory structure:
This makes the deploy directory cleaner by moving all
compose related file/directories into the compose directory.

Signed-off-by: Jacob Weinstock <jakobweinstock@gmail.com>
2021-08-09 08:04:21 -06:00
Jacob Weinstock
9b1cf3b509 Add vagrant-libvirt:
This gets the refactored sandbox back on par with
the existing sandbox for vagrant-libvirt functionality.

Signed-off-by: Jacob Weinstock <jakobweinstock@gmail.com>
2021-08-09 08:04:21 -06:00
Jacob Weinstock
6b841fee7c This simplifies the stand-up of a sandbox:
Only 2 main Vagrant calls are now needed (`vagrant up` and `vagrant up machine1`).
This PR only updates the Vagrant Virtualbox setup. The Vagrant Libvirt and Terraform
still need to be updated.

This uses docker-compose as the entry point for standing up the stack and makes the stand-up
of the sandbox more portal. Vagrant and Terraform are only responsible for standing up infrastructure
and then running docker-compose, not for running any glue scripts.

The docker-compose calls out to single-shot services to do all the glue required to get the fully
functional Tinkerbell stack up and running. All the single-shot services are idempotent.
This increases portability and the development iteration loop. This also simplifies the required
steps needed to get a fully functioning sandbox up and running.

This is intended to help people looking to get started by getting them to a provisioned
machine quicker and more easily.

Signed-off-by: Jacob Weinstock <jakobweinstock@gmail.com>
2021-08-09 08:04:06 -06:00
73 changed files with 2903 additions and 1387 deletions

View File

@ -13,7 +13,7 @@ jobs:
- uses: actions/setup-go@v2
with:
go-version: "1.15.5"
- run: ./script/release-binaries.sh
- run: ./releases/script/release-binaries.sh
name: get binaries
- name: Create Release
id: create_release
@ -30,4 +30,4 @@ jobs:
env:
GITHUB_TOKEN: ${{ github.token }}
with:
asset_paths: '["./out/release/*"]'
asset_paths: '["./releases/out/release/*"]'

View File

@ -19,4 +19,5 @@ jobs:
- name: Vagrant Test
run: |
export VAGRANT_DEFAULT_PROVIDER="virtualbox"
go test --timeout 1h -v ./test/vagrant
cd ./test/vagrant
go test --timeout 1h -v ./

10
.gitignore vendored
View File

@ -1,3 +1,11 @@
envrc
out
.env
!deploy/.env
.vagrant
deploy/compose/state/webroot/misc/osie/current/*
deploy/compose/state/webroot/workflow/*
!deploy/compose/state/webroot/misc/osie/current/.keep
!deploy/compose/state/webroot/workflow/.keep
deploy/compose/state/webroot/*.gz
workflow_id.txt
compose.tar.gz

View File

@ -1,59 +1,47 @@
This repository is a quick way to get the Tinkerbell stack up and running.
# Quick-Starts
Currently it supports:
The following quick-start guides will walk you through standing up the Tinkerbell stack.
There are a few options for this.
Pick the one that works best for you.
1. Vagrant with libvirt and VirtualBox
2. Terraform on Packet
## Options
Tinkerbell is made of different components: osie, boots, tink-server,
tink-worker and so on. Currently they are under heavy development and we are
working around the release process for all the components.
- [Vagrant and VirtualBox](docs/quickstarts/VAGRANTVBOX.md)
- [Vagrant and Libvirt](docs/quickstarts/VAGRANTLVIRT.md)
- [Docker Compose](docs/quickstarts/COMPOSE.md)
- [Terraform and Equinix Metal](docs/quickstarts/TERRAFORMEM.md)
- [Kubernetes](docs/quickstarts/KUBERNETES.md)
- [Multipass](docs/quickstarts/MULTIPASS.md)
We need a way to serve a version of Tinkerbell that you can use and we know what
is running the hood. Sandbox runs a pinned version for all the components via
commit sha. In this way as a user you won't be effected (ideally) from new code
that will may change a bit how Tinkerbell works.
## Next Steps
We are keeping the number of breaking changes as low as possible but in the current
state they are expected.
Now that you have a Tinkerbell stack up and running, you can start provisioning machines.
Tinkerbell.org has a [list of guides](https://docs.tinkerbell.org/deploying-operating-systems/the-deployment/) for provisioning machines.
You can also create your own.
The following docs will help you get started.
## Binary release
1. [Create Hardware Data](https://docs.tinkerbell.org/setup/local-vagrant/#creating-the-workers-hardware-data)
2. [Create a Template](https://docs.tinkerbell.org/setup/local-vagrant/#creating-a-template)
3. [Create a Workflow](https://docs.tinkerbell.org/setup/local-vagrant/#creating-the-workflow)
As part of a new release for sandbox we want to push binaries to GitHub Release
in this way the community will be able to use them if needed.
### In the Sandbox
We build Docker images across many architectures, each of them in its own
repository: boots, hegel, tink and so on.
1. Create your own templates
Sandbox is just a collection of those services and we follow the same pattern
for getting binaries as well.
```bash
docker exec -i compose_tink-cli_1 tink template create < ./custom-template.yaml
```
There is a go program available in `./cmd/getbinariesfromquay/main.go`. You can
run it with `go run` or build it with `go build`:
2. Upload any container images you want to use in the templates to the internal registry
```terminal
$ go run cmd/getbinariesfromquay/main.go -h
-binary-to-copy string
The location of the binary you want to copy from inside the image. (default "/usr/bin/hegel")
-image string
The image you want to download binaries from. It has to be a multi stage image. (default "docker://quay.io/tinkerbell/hegel")
-out string
The directory that will be used to store the release binaries (default "./out")
-program string
The name of the program you are extracing binaries for. (eg tink-worker, hegel, tink-server, tink, boots) (default "hegel")
```
```bash
docker run -it --rm quay.io/containers/skopeo copy --all --dest-tls-verify=false --dest-creds="admin":"Admin1234" docker://hello-world docker://192.168.50.4/hello-world
```
By default it uses the image running on Quay for Hegel and it gets the binary
`/usr/bin/hegel` from there. The directory `./out` is used to store images and
binaries inside `./out/releases`.
3. Create a workflow
To get the binaries for example for boots you can run:
```bash
docker exec -i compose_tink-cli_1 tink workflow create -t <TEMPLATE ID> -r '{"device_1":"08:00:27:00:00:01"}')
```
```terminal
$ go run cmd/getbinariesfromquay/main.go \
-binary-to-copy /usr/bin/boots \
-image docker://quay.io/tinkerbell/boots:sha-9625559b \
-program boots
```
You will find them in `./out/release`
4. Restart the machine to provision (if using the vagrant sandbox test machine this is done by running `vagrant destroy -f machine1 && vagrant up machine1`)

1
deploy/.gitignore vendored
View File

@ -1 +0,0 @@
state

12
deploy/compose/.env Normal file
View File

@ -0,0 +1,12 @@
#OSIE_DOWNLOAD_URL="https://tinkerbell-oss.s3.amazonaws.com/osie-uploads/osie-1790-23d78ea47f794d0e5c934b604579c26e5fce97f5.tar.gz"
OSIE_DOWNLOAD_URL="https://github.com/tinkerbell/hook/releases/download/5.10.57/hook-x86_64.tar.gz"
TINKERBELL_USE_HOOK="true"
TINK_CLI_IMAGE="quay.io/tinkerbell/tink-cli:sha-8ea8a0e5"
TINK_SERVER_IMAGE="quay.io/tinkerbell/tink:sha-8ea8a0e5"
BOOTS_SERVER_IMAGE="quay.io/tinkerbell/boots:sha-94f43947"
HEGEL_SERVER_IMAGE="quay.io/tinkerbell/hegel:sha-9f5da0a8"
TINKERBELL_HARDWARE_MANIFEST="/manifests/hardware/hardware.json"
TINKERBELL_TEMPLATE_MANIFEST="/manifests/template/ubuntu.yaml"
TINKERBELL_HOST_IP=192.168.50.4
TINKERBELL_CLIENT_IP=192.168.50.43
TINKERBELL_CLIENT_MAC=08:00:27:9e:f5:3a

View File

@ -0,0 +1,301 @@
services:
# TLS cert for tink-server and docker registry
tls-gen:
image: cfssl/cfssl
entrypoint: /code/tls/generate.sh
command: ["$TINKERBELL_HOST_IP"]
environment:
FACILITY: ${FACILITY:-onprem}
volumes:
- ${REPO_TOP_LEVEL:-.}:/code
- certs:/certs/${FACILITY:-onprem}:rw
# User creds for the registry
registry-auth:
image: httpd:2
entrypoint: htpasswd
working_dir: /auth
command:
[
"-Bbc",
".htpasswd",
"${TINKERBELL_REGISTRY_USERNAME:-admin}",
"${TINKERBELL_REGISTRY_PASSWORD:-Admin1234}",
]
volumes:
- auth:/auth:rw
# OSIE work
osie-work:
image: bash:4.4
entrypoint: /scripts/lastmile.sh
command:
[
"${OSIE_DOWNLOAD_URL}",
"/source",
"/source",
"/destination",
"${TINKERBELL_USE_HOOK}",
]
volumes:
- ${REPO_TOP_LEVEL:-.}/osie:/scripts
- ${REPO_TOP_LEVEL:-.}/state/webroot/misc/osie/current:/source
- ${REPO_TOP_LEVEL:-.}/state/webroot/workflow:/destination
# Uploads images in /registry/registry_images.txt to the local registry
images-to-local-registry:
image: quay.io/containers/skopeo:latest
entrypoint: /registry/upload.sh
command:
[
"${TINKERBELL_REGISTRY_USERNAME:-admin}",
"${TINKERBELL_REGISTRY_PASSWORD:-Admin1234}",
"${TINKERBELL_HOST_IP}",
"/registry/registry_images.txt",
]
volumes:
- ${REPO_TOP_LEVEL:-.}/registry:/registry
depends_on:
registry:
condition: service_healthy
# registry ca.crt download
registry-ca-crt-download:
image: alpine
entrypoint: wget
working_dir: /code
command: ["http://$TINKERBELL_HOST_IP:42114/cert", "-O", "ca.pem"]
volumes:
- ${REPO_TOP_LEVEL:-.}/state/webroot/workflow:/code
depends_on:
tink-server:
condition: service_healthy
db:
condition: service_healthy
# Create hardware, template, and workflow records in tink-server
create-tink-records:
image: ${TINK_CLI_IMAGE}
entrypoint: /manifests/exec_in_bash.sh
command:
[
"$TINKERBELL_HARDWARE_MANIFEST",
"$TINKERBELL_TEMPLATE_MANIFEST",
"/manifests/workflow",
"$TINKERBELL_HOST_IP",
"$TINKERBELL_CLIENT_IP",
"$TINKERBELL_CLIENT_MAC",
]
environment:
GLUE_SCRIPT_NAME: "/manifests/apply_manifests.sh"
TINKERBELL_GRPC_AUTHORITY: tink-server:42113
TINKERBELL_CERT_URL: http://tink-server:42114/cert
volumes:
- ${REPO_TOP_LEVEL:-.}/manifests:/manifests
depends_on:
tink-server:
condition: service_healthy
db:
condition: service_healthy
# Setup ubuntu image
ubuntu-image-setup:
image: ubuntu
entrypoint: /scripts/setup_ubuntu.sh
command:
[
"https://cloud-images.ubuntu.com/daily/server/focal/current/focal-server-cloudimg-amd64.img",
"focal-server-cloudimg-amd64.img",
"/destination/focal-server-cloudimg-amd64.raw",
]
volumes:
- ${REPO_TOP_LEVEL:-.}/ubuntu:/scripts
- ${REPO_TOP_LEVEL:-.}/state/webroot:/destination
tink-server:
image: ${TINK_SERVER_IMAGE}
restart: unless-stopped
environment:
FACILITY: ${FACILITY:-onprem}
PACKET_ENV: ${PACKET_ENV:-testing}
PACKET_VERSION: ${PACKET_VERSION:-ignored}
ROLLBAR_TOKEN: ${ROLLBAR_TOKEN:-ignored}
ROLLBAR_DISABLE: ${ROLLBAR_DISABLE:-1}
PGDATABASE: tinkerbell
PGHOST: db
PGPASSWORD: tinkerbell
PGPORT: 5432
PGSSLMODE: disable
PGUSER: tinkerbell
TINKERBELL_GRPC_AUTHORITY: :42113
TINKERBELL_HTTP_AUTHORITY: :42114
TINK_AUTH_USERNAME: ${TINKERBELL_TINK_USERNAME:-admin}
TINK_AUTH_PASSWORD: ${TINKERBELL_TINK_PASSWORD:-admin}
depends_on:
tink-server-migration:
condition: service_started
db:
condition: service_healthy
tls-gen:
condition: service_completed_successfully
healthcheck:
test: ["CMD-SHELL", "wget -qO- 127.0.0.1:42114/cert"] # port needs to match TINKERBELL_HTTP_AUTHORITY
interval: 5s
timeout: 2s
retries: 30
volumes:
- certs:/certs/${FACILITY:-onprem}:rw
ports:
- 42113:42113/tcp
- 42114:42114/tcp
tink-server-migration:
image: ${TINK_SERVER_IMAGE}
restart: on-failure
environment:
ONLY_MIGRATION: "true"
FACILITY: ${FACILITY:-onprem}
PGDATABASE: tinkerbell
PGHOST: db
PGPASSWORD: tinkerbell
PGPORT: 5432
PGSSLMODE: disable
PGUSER: tinkerbell
TINKERBELL_GRPC_AUTHORITY: :42113
TINKERBELL_HTTP_AUTHORITY: :42114
TINK_AUTH_USERNAME: ${TINKERBELL_TINK_USERNAME:-admin}
TINK_AUTH_PASSWORD: ${TINKERBELL_TINK_PASSWORD:-admin}
depends_on:
db:
condition: service_healthy
volumes:
- certs:/certs/${FACILITY:-onprem}:rw
db:
image: postgres:10-alpine
restart: unless-stopped
environment:
POSTGRES_DB: tinkerbell
POSTGRES_PASSWORD: tinkerbell
POSTGRES_USER: tinkerbell
volumes:
- postgres_data:/var/lib/postgresql/data:rw
ports:
- 5432:5432
healthcheck:
test: ["CMD-SHELL", "pg_isready -U tinkerbell"]
interval: 1s
timeout: 1s
retries: 30
tink-cli:
image: ${TINK_CLI_IMAGE}
restart: unless-stopped
environment:
TINKERBELL_GRPC_AUTHORITY: tink-server:42113
TINKERBELL_CERT_URL: http://tink-server:42114/cert
depends_on:
tink-server:
condition: service_healthy
db:
condition: service_healthy
registry:
image: registry:2.7.1
restart: unless-stopped
network_mode: host
healthcheck:
test:
[
"CMD-SHELL",
"wget --no-check-certificate https://$TINKERBELL_HOST_IP -O -",
]
interval: 5s
timeout: 1s
retries: 5
environment:
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
REGISTRY_AUTH_HTPASSWD_PATH: /auth/.htpasswd
REGISTRY_HTTP_TLS_CERTIFICATE: /certs/${FACILITY:-onprem}/bundle.pem
REGISTRY_HTTP_TLS_KEY: /certs/${FACILITY:-onprem}/server-key.pem
REGISTRY_HTTP_ADDR: $TINKERBELL_HOST_IP:443
volumes:
- certs:/certs/${FACILITY:-onprem}:ro
- auth:/auth:rw
depends_on:
tls-gen:
condition: service_completed_successfully
registry-auth:
condition: service_completed_successfully
boots:
image: ${BOOTS_SERVER_IMAGE}
restart: unless-stopped
command: -dhcp-addr 0.0.0.0:67 -tftp-addr $TINKERBELL_HOST_IP:69 -http-addr $TINKERBELL_HOST_IP:80 -log-level DEBUG
network_mode: host
environment:
API_AUTH_TOKEN: ${PACKET_API_AUTH_TOKEN:-ignored}
API_CONSUMER_TOKEN: ${PACKET_CONSUMER_TOKEN:-ignored}
FACILITY_CODE: ${FACILITY:-onprem}
PACKET_ENV: ${PACKET_ENV:-testing}
PACKET_VERSION: ${PACKET_VERSION:-ignored}
ROLLBAR_TOKEN: ${ROLLBAR_TOKEN:-ignored}
ROLLBAR_DISABLE: ${ROLLBAR_DISABLE:-1}
MIRROR_HOST: ${TINKERBELL_HOST_IP:-127.0.0.1}:8080
DNS_SERVERS: 8.8.8.8
PUBLIC_IP: $TINKERBELL_HOST_IP
BOOTP_BIND: $TINKERBELL_HOST_IP:67
HTTP_BIND: $TINKERBELL_HOST_IP:80
SYSLOG_BIND: $TINKERBELL_HOST_IP:514
TFTP_BIND: $TINKERBELL_HOST_IP:69
DOCKER_REGISTRY: $TINKERBELL_HOST_IP
REGISTRY_USERNAME: ${TINKERBELL_REGISTRY_USERNAME:-admin}
REGISTRY_PASSWORD: ${TINKERBELL_REGISTRY_PASSWORD:-Admin1234}
TINKERBELL_GRPC_AUTHORITY: $TINKERBELL_HOST_IP:42113
TINKERBELL_CERT_URL: http://$TINKERBELL_HOST_IP:42114/cert
DATA_MODEL_VERSION: 1
extra_hosts:
- "tink-server:$TINKERBELL_HOST_IP"
depends_on:
tink-server:
condition: service_healthy
osie-bootloader:
image: nginx:alpine
restart: unless-stopped
tty: true
user: root
ports:
- 8080:80/tcp
volumes:
- ${REPO_TOP_LEVEL:-.}/state/webroot:/usr/share/nginx/html/
depends_on:
osie-work:
condition: service_completed_successfully
ubuntu-image-setup:
condition: service_completed_successfully
hegel:
image: ${HEGEL_SERVER_IMAGE}
restart: unless-stopped
environment:
ROLLBAR_TOKEN: ${ROLLBAR_TOKEN-ignored}
ROLLBAR_DISABLE: 1
PACKET_ENV: testing
PACKET_VERSION: ${PACKET_VERSION:-ignored}
GRPC_PORT: 42115
HEGEL_FACILITY: ${FACILITY:-onprem}
HEGEL_USE_TLS: 0
TINKERBELL_GRPC_AUTHORITY: tink-server:42113
TINKERBELL_CERT_URL: http://tink-server:42114/cert
DATA_MODEL_VERSION: 1
CUSTOM_ENDPOINTS: '{"/metadata":""}'
depends_on:
tink-server:
condition: service_healthy
volumes:
postgres_data:
certs:
auth:

View File

@ -0,0 +1,91 @@
#!/usr/bin/env bash
set -xo pipefail
# update_hw_ip_addr the hardware json with a specified IP address
update_hw_ip_addr() {
local ip_address="$1"
local hw_file="$2"
sed -i "s/\"address\":.*,/\"address\": \"${ip_address}\",/" "${hw_file}"
}
# update_hw_mac_addr the hardware json with a specified MAC address
update_hw_mac_addr() {
local mac_address="$1"
local hw_file="$2"
sed -i "s/\"mac\":.*,/\"mac\": \"${mac_address}\",/" "${hw_file}"
}
# hardware creates a hardware record in tink from the file_loc provided
hardware() {
local file_loc="$1"
tink hardware push --file "${file_loc}"
}
# update_template_img_ip the template yaml with a specified IP address
update_template_img_ip() {
local ip_address="$1"
local template_file="$2"
sed -i "s,IMG_URL: \"http://.*,IMG_URL: \"http://${ip_address}:8080/focal-server-cloudimg-amd64.raw.gz\"," "${template_file}"
}
# template create a template record in tink from the file_loc provided
template() {
local file_loc="$1"
tink template create --file "${file_loc}"
}
# workflow creates a workflow record in tink from the hardware and template records
workflow() {
local workflow_dir="$1"
local mac_address="$2"
local mac
mac=$(echo "${mac_address}" | tr '[:upper:]' '[:lower:]')
local template_id
template_id=$(tink template get --no-headers 2>/dev/null | grep -v "+" | cut -d" " -f2 | xargs)
tink workflow create --template "${template_id}" --hardware "{\"device_1\":\"${mac}\"}" | tee "${workflow_dir}/workflow_id.txt"
# write just the workflow id to a file. `|| true` is a failsafe in case the workflow creation fails
sed -i 's/Created Workflow: //g' "${workflow_dir}/workflow_id.txt" || true
}
# workflow_exists checks if a workflow record exists in tink before creating a new one
workflow_exists() {
local workflow_dir="$1"
local mac_address="$2"
if [ ! -f "${workflow_dir}"/workflow_id.txt ]; then
workflow "${workflow_dir}" "${mac_address}"
return 0
fi
local workflow_id
workflow_id=$(cat "${workflow_dir}"/workflow_id.txt)
if [ -z "${workflow_id}" ]; then
workflow "${workflow_dir}" "${mac_address}"
return 0
fi
tink workflow get | grep -q "${workflow_id}"
local result=$?
if [ "${result}" -ne 0 ]; then
workflow "${workflow_dir}" "${mac_address}"
else
echo "Workflow [$(cat "${workflow_dir}"/workflow_id.txt)] already exists"
fi
}
# main runs the creation functions in order
main() {
local hw_file="$1"
local template_file="$2"
local workflow_dir="$3"
local ip_address="$4"
local client_ip_address="$5"
local client_mac_address="$6"
update_hw_ip_addr "${client_ip_address}" "${hw_file}"
update_hw_mac_addr "${client_mac_address}" "${hw_file}"
hardware "${hw_file}"
update_template_img_ip "${ip_address}" "${template_file}"
template "${template_file}"
workflow_exists "${workflow_dir}" "${client_mac_address}"
}
main "$1" "$2" "$3" "$4" "$5" "$6"

View File

@ -0,0 +1,20 @@
#!/usr/bin/env sh
# This script is needed because we prefer bash scripts but
# the pre-built tink-worker container image is alpine and does not
# have bash naively installed.
set -x
# install_bash install bash, needed when running this script in an Alpine container, like tink-worker image
install_bash() {
apk update
apk add bash
}
# main runs the functions
main() {
install_bash
bash "${GLUE_SCRIPT_NAME}" "$@"
}
main "$@"

View File

@ -0,0 +1,32 @@
{
"id": "0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94",
"metadata": {
"facility": {
"facility_code": "onprem",
"plan_slug": "c2.medium.x86",
"plan_version_slug": ""
},
"instance": {},
"state": "provisioning"
},
"network": {
"interfaces": [
{
"dhcp": {
"arch": "x86_64",
"ip": {
"address": "192.168.50.43",
"gateway": "192.168.50.4",
"netmask": "255.255.255.0"
},
"mac": "08:00:27:9e:f5:3a",
"uefi": false
},
"netboot": {
"allow_pxe": true,
"allow_workflow": true
}
}
]
}
}

View File

@ -0,0 +1,32 @@
{
"id": "0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94",
"metadata": {
"facility": {
"facility_code": "onprem",
"plan_slug": "c2.medium.x86",
"plan_version_slug": ""
},
"instance": {},
"state": "provisioning"
},
"network": {
"interfaces": [
{
"dhcp": {
"arch": "x86_64",
"ip": {
"address": "192.168.50.43",
"gateway": "192.168.50.1",
"netmask": "255.255.255.0"
},
"mac": "08:00:27:9e:f5:3a",
"uefi": false
},
"netboot": {
"allow_pxe": true,
"allow_workflow": true
}
}
]
}
}

View File

@ -1,13 +1,13 @@
{
"id": "${id}",
"id": "0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94",
"metadata": {
"facility": {
"facility_code": "${facility_code}",
"plan_slug": "${plan_slug}",
"facility_code": "onprem",
"plan_slug": "c2.medium.x86",
"plan_version_slug": ""
},
"instance": {},
"state": ""
"state": "provisioning"
},
"network": {
"interfaces": [
@ -15,11 +15,10 @@
"dhcp": {
"arch": "x86_64",
"ip": {
"address": "${address}",
"gateway": "192.168.1.1",
"netmask": "255.255.255.248"
"address": "192.168.50.43",
"netmask": "255.255.255.0"
},
"mac": "${mac}",
"mac": "08:00:27:9e:f5:3a",
"uefi": false
},
"netboot": {

View File

@ -0,0 +1,91 @@
version: "0.1"
name: debian_Focal
global_timeout: 1800
tasks:
- name: "os-installation"
worker: "{{.device_1}}"
volumes:
- /dev:/dev
- /dev/console:/dev/console
- /lib/firmware:/lib/firmware:ro
actions:
- name: "stream-ubuntu-image"
image: image2disk:v1.0.0
timeout: 600
environment:
DEST_DISK: /dev/sda
IMG_URL: "http://192.168.50.4:8080/focal-server-cloudimg-amd64.raw.gz"
COMPRESSED: true
- name: "grow-partition"
image: cexec:v1.0.0
timeout: 90
environment:
BLOCK_DEVICE: /dev/sda1
FS_TYPE: ext4
CHROOT: y
DEFAULT_INTERPRETER: "/bin/sh -c"
CMD_LINE: "growpart /dev/sda 1 && resize2fs /dev/sda1"
- name: "fix-serial"
image: cexec:v1.0.0
timeout: 90
pid: host
environment:
BLOCK_DEVICE: /dev/sda1
FS_TYPE: ext4
CHROOT: y
DEFAULT_INTERPRETER: "/bin/sh -c"
CMD_LINE: "sed -e 's|ttyS0|ttyS1,115200|g' -i /etc/default/grub.d/50-cloudimg-settings.cfg ; update-grub"
- name: "install-openssl"
image: cexec:v1.0.0
timeout: 90
environment:
BLOCK_DEVICE: /dev/sda1
FS_TYPE: ext4
CHROOT: y
DEFAULT_INTERPRETER: "/bin/sh -c"
CMD_LINE: "apt -y update && apt -y install openssl"
- name: "create-user"
image: cexec:v1.0.0
timeout: 90
environment:
BLOCK_DEVICE: /dev/sda1
FS_TYPE: ext4
CHROOT: y
DEFAULT_INTERPRETER: "/bin/sh -c"
CMD_LINE: "useradd -p $(openssl passwd -1 tink) -s /bin/bash -d /home/tink/ -m -G sudo tink"
- name: "enable-ssh"
image: cexec:v1.0.0
timeout: 90
environment:
BLOCK_DEVICE: /dev/sda1
FS_TYPE: ext4
CHROOT: y
DEFAULT_INTERPRETER: "/bin/sh -c"
CMD_LINE: "ssh-keygen -A; systemctl enable ssh.service; sed -i 's/^PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config"
- name: "disable-apparmor"
image: cexec:v1.0.0
timeout: 90
environment:
BLOCK_DEVICE: /dev/sda1
FS_TYPE: ext4
CHROOT: y
DEFAULT_INTERPRETER: "/bin/sh -c"
CMD_LINE: "systemctl disable apparmor; systemctl disable snapd"
- name: "write-netplan"
image: writefile:v1.0.0
timeout: 90
environment:
DEST_DISK: /dev/sda1
FS_TYPE: ext4
DEST_PATH: /etc/netplan/config.yaml
CONTENTS: |
network:
version: 2
renderer: networkd
ethernets:
enp1s0f0:
dhcp4: true
UID: 0
GID: 0
MODE: 0644
DIRMODE: 0755

View File

@ -0,0 +1,74 @@
version: "0.1"
name: debian_Focal
global_timeout: 1800
tasks:
- name: "os-installation"
worker: "{{.device_1}}"
volumes:
- /dev:/dev
- /dev/console:/dev/console
- /lib/firmware:/lib/firmware:ro
actions:
- name: "stream-ubuntu-image"
image: image2disk:v1.0.0
timeout: 600
environment:
DEST_DISK: /dev/vda
IMG_URL: "http://192.168.50.4:8080/focal-server-cloudimg-amd64.raw.gz"
COMPRESSED: true
- name: "install-openssl"
image: cexec:v1.0.0
timeout: 90
environment:
BLOCK_DEVICE: /dev/vda1
FS_TYPE: ext4
CHROOT: y
DEFAULT_INTERPRETER: "/bin/sh -c"
CMD_LINE: "apt -y update && apt -y install openssl"
- name: "create-user"
image: cexec:v1.0.0
timeout: 90
environment:
BLOCK_DEVICE: /dev/vda1
FS_TYPE: ext4
CHROOT: y
DEFAULT_INTERPRETER: "/bin/sh -c"
CMD_LINE: "useradd -p $(openssl passwd -1 tink) -s /bin/bash -d /home/tink/ -m -G sudo tink"
- name: "enable-ssh"
image: cexec:v1.0.0
timeout: 90
environment:
BLOCK_DEVICE: /dev/vda1
FS_TYPE: ext4
CHROOT: y
DEFAULT_INTERPRETER: "/bin/sh -c"
CMD_LINE: "ssh-keygen -A; systemctl enable ssh.service; sed -i 's/^PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config"
- name: "disable-apparmor"
image: cexec:v1.0.0
timeout: 90
environment:
BLOCK_DEVICE: /dev/vda1
FS_TYPE: ext4
CHROOT: y
DEFAULT_INTERPRETER: "/bin/sh -c"
CMD_LINE: "systemctl disable apparmor; systemctl disable snapd"
- name: "write-netplan"
image: writefile:v1.0.0
timeout: 90
environment:
DEST_DISK: /dev/vda1
FS_TYPE: ext4
DEST_PATH: /etc/netplan/config.yaml
CONTENTS: |
network:
version: 2
renderer: networkd
ethernets:
ens5:
dhcp4: true
ens6:
dhcp4: true
UID: 0
GID: 0
MODE: 0644
DIRMODE: 0755

View File

@ -0,0 +1,76 @@
version: "0.1"
name: debian_Focal
global_timeout: 1800
tasks:
- name: "os-installation"
worker: "{{.device_1}}"
volumes:
- /dev:/dev
- /dev/console:/dev/console
- /lib/firmware:/lib/firmware:ro
actions:
- name: "stream-ubuntu-image"
image: image2disk:v1.0.0
timeout: 600
environment:
DEST_DISK: /dev/sda
IMG_URL: "http://192.168.50.4:8080/focal-server-cloudimg-amd64.raw.gz"
COMPRESSED: true
- name: "install-openssl"
image: cexec:v1.0.0
timeout: 90
environment:
BLOCK_DEVICE: /dev/sda1
FS_TYPE: ext4
CHROOT: y
DEFAULT_INTERPRETER: "/bin/sh -c"
CMD_LINE: "apt -y update && apt -y install openssl"
- name: "create-user"
image: cexec:v1.0.0
timeout: 90
environment:
BLOCK_DEVICE: /dev/sda1
FS_TYPE: ext4
CHROOT: y
DEFAULT_INTERPRETER: "/bin/sh -c"
CMD_LINE: "useradd -p $(openssl passwd -1 tink) -s /bin/bash -d /home/tink/ -m -G sudo tink"
- name: "enable-ssh"
image: cexec:v1.0.0
timeout: 90
environment:
BLOCK_DEVICE: /dev/sda1
FS_TYPE: ext4
CHROOT: y
DEFAULT_INTERPRETER: "/bin/sh -c"
CMD_LINE: "ssh-keygen -A; systemctl enable ssh.service; sed -i 's/^PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config"
- name: "disable-apparmor"
image: cexec:v1.0.0
timeout: 90
environment:
BLOCK_DEVICE: /dev/sda1
FS_TYPE: ext4
CHROOT: y
DEFAULT_INTERPRETER: "/bin/sh -c"
CMD_LINE: "systemctl disable apparmor; systemctl disable snapd"
- name: "write-netplan"
image: writefile:v1.0.0
timeout: 90
environment:
DEST_DISK: /dev/sda1
FS_TYPE: ext4
DEST_PATH: /etc/netplan/config.yaml
CONTENTS: |
network:
version: 2
renderer: networkd
ethernets:
enp0s3:
dhcp4: true
enp0s8:
dhcp4: true
ens33:
dhcp4: true
UID: 0
GID: 0
MODE: 0644
DIRMODE: 0755

View File

72
deploy/compose/osie/lastmile.sh Executable file
View File

@ -0,0 +1,72 @@
#!/usr/bin/env bash
set -xo pipefail
# osie_download from url and save it to directory
osie_download() {
local url="$1"
local directory="$2"
wget "${url}" -O "${directory}"/osie.tar.gz
}
# osie_extract from tarball and save it to directory
osie_extract() {
local source_dir="$1"
local dest_dir="$2"
tar -zxvf "${source_dir}"/osie.tar.gz -C "${dest_dir}" --strip-components 1
}
# osie_move_helper_scripts moves workflow helper scripts to the workflow directory
osie_move_helper_scripts() {
local source_dir="$1"
local dest_dir="$2"
cp "${source_dir}"/workflow-helper.sh "${source_dir}"/workflow-helper-rc "${dest_dir}"/
}
# hook_rename_files renames the kernel and initrd files from the github downloaded tar
# to the default names that the OSIE installer in Boots is expecting.
# See https://github.com/tinkerbell/boots/blob/78d4f74e6944ae3bd04e1297dc8e354fc93d9320/installers/osie/main.go#L160 and
# https://github.com/tinkerbell/boots/blob/78d4f74e6944ae3bd04e1297dc8e354fc93d9320/installers/osie/main.go#L168
hook_rename_files() {
local src_kernel="$1"
local src_initrd="$2"
local dest_dir="$3"
mv "${src_kernel}" "${dest_dir}/vmlinuz-x86_64"
mv "${src_initrd}" "${dest_dir}/initramfs-x86_64"
}
# main runs the functions in order to download, extract, and move helper scripts
main() {
local url="$1"
local extract_dir="$2"
local source_dir="$3"
local dest_dir="$4"
local use_hook="$5"
if [ ! -f "${extract_dir}"/osie.tar.gz ]; then
echo "downloading osie..."
osie_download "${url}" "${extract_dir}"
else
echo "osie already downloaded"
fi
if [ "${use_hook}" == "true" ]; then
if [ ! -f "${source_dir}"/hook-x86_64-kernel ] && [ ! -f "${source_dir}"/hook-x86_64-initrd.img ]; then
echo "extracting hook..."
osie_extract "${extract_dir}" "${source_dir}"
else
echo "hook files already exist, not extracting"
fi
hook_rename_files "${source_dir}"/hook-x86_64-kernel "${source_dir}"/hook-x86_64-initrd.img "${source_dir}"
else
if [ ! -f "${source_dir}"/workflow-helper.sh ] && [ ! -f "${source_dir}"/workflow-helper-rc ]; then
echo "extracting osie..."
osie_extract "${extract_dir}" "${source_dir}"
else
echo "osie files already exist, not extracting"
fi
osie_move_helper_scripts "${source_dir}" "${dest_dir}"
fi
}
main "$1" "$2" "$3" "$4" "$5"

View File

@ -0,0 +1,6 @@
quay.io/tinkerbell/tink-worker:latest tinkerbell/tink-worker:latest
quay.io/tinkerbell/tink-worker:latest tink-worker:latest
quay.io/tinkerbell/tink-worker:latest tinkerbell/tink-worker:sha-5e1f0fd8
quay.io/tinkerbell-actions/image2disk:v1.0.0 image2disk:v1.0.0
quay.io/tinkerbell-actions/cexec:v1.0.0 cexec:v1.0.0
quay.io/tinkerbell-actions/writefile:v1.0.0 writefile:v1.0.0

View File

@ -0,0 +1,20 @@
#!/usr/bin/env bash
# shellcheck disable=SC2001,SC2155,SC2046
set -xo pipefail
main() {
local reg_user="$1"
local reg_pw="$2"
local reg_url="$3"
local images_file="$4"
# this confusing IFS= and the || is to capture the last line of the file if there is no newline at the end
while IFS= read -r img || [ -n "${img}" ]; do
# file is expected to have src and dst images delimited by a space
local src_img="$(echo "${img}" | cut -d' ' -f1)"
local dst_img="$(echo "${img}" | cut -d' ' -f2)"
skopeo copy --all --dest-tls-verify=false --dest-creds="${reg_user}":"${reg_pw}" docker://"${src_img}" docker://"${reg_url}"/"${dst_img}"
done <"${images_file}"
}
main "$1" "$2" "$3" "$4"

View File

@ -4,8 +4,10 @@
"tinkerbell.registry",
"tinkerbell.tinkerbell",
"tinkerbell",
"localhost",
"127.0.0.1"
"tink-server",
"192.168.50.4",
"127.0.0.1",
"localhost"
],
"key": {
"algo": "rsa",

47
deploy/compose/tls/generate.sh Executable file
View File

@ -0,0 +1,47 @@
#!/usr/bin/env bash
set -xo pipefail
# update_csr will add the sans_ip to the csr
update_csr() {
local sans_ip="$1"
local csr_file="$2"
sed -i "/\"hosts\".*/a \ \"${sans_ip}\"," "${csr_file}"
}
# cleanup will remove unneeded files
cleanup() {
rm -rf ca-key.pem ca.csr ca.pem server.csr server.pem
}
# gen will generate the key and bundle
gen() {
local bundle_destination="$1"
local key_destination="$2"
cfssl gencert -initca /code/tls/csr.json | cfssljson -bare ca -
cfssl gencert -config /code/tls/ca-config.json -ca ca.pem -ca-key ca-key.pem -profile server /code/tls/csr.json | cfssljson -bare server
cat server.pem ca.pem >"${bundle_destination}"
mv server-key.pem "${key_destination}"
}
# main orchestrates the process
main() {
local sans_ip="$1"
local csr_file="/code/tls/csr.json"
local bundle_file="/certs/${FACILITY:-onprem}/bundle.pem"
local server_key_file="/certs/${FACILITY:-onprem}/server-key.pem"
if ! grep -q "${sans_ip}" "${csr_file}"; then
update_csr "${sans_ip}" "${csr_file}"
else
echo "IP ${sans_ip} already in ${csr_file}"
fi
if [ ! -f "${bundle_file}" ] && [ ! -f "${server_key_file}" ]; then
gen "${bundle_file}" "${server_key_file}"
else
echo "Files [${bundle_file}, ${server_key_file}] already exist"
fi
cleanup
}
main "$1"

View File

@ -0,0 +1,45 @@
#!/usr/bin/env bash
set -xo pipefail
install_deps() {
apt -y update
DEBIAN_FRONTEND=noninteractive apt -y install qemu-utils wget gzip
}
download_image() {
local url="$1"
wget "${url}"
}
img_to_raw() {
local img_file="$1"
local raw_file="$2"
qemu-img convert "${img_file}" -O raw "${raw_file}"
}
compress_raw() {
local raw_file="$1"
gzip "${raw_file}"
}
cleanup() {
local img_file="$1"
rm -rf "${img_file}"
}
main() {
local image_url="$1"
local img_file="$2"
local raw_file="$3"
if [ ! -f "${raw_file}.gz" ]; then
install_deps
download_image "${image_url}"
img_to_raw "${img_file}" "${raw_file}"
compress_raw "${raw_file}"
cleanup "${img_file}"
fi
}
main "$1" "$2" "$3"

View File

@ -1,179 +0,0 @@
version: "2.1"
services:
tink-server:
image: ${TINKERBELL_TINK_SERVER_IMAGE}
restart: unless-stopped
environment:
FACILITY: ${FACILITY:-onprem}
PACKET_ENV: ${PACKET_ENV:-testing}
PACKET_VERSION: ${PACKET_VERSION:-ignored}
ROLLBAR_TOKEN: ${ROLLBAR_TOKEN:-ignored}
ROLLBAR_DISABLE: ${ROLLBAR_DISABLE:-1}
PGDATABASE: tinkerbell
PGHOST: db
PGPASSWORD: tinkerbell
PGPORT: 5432
PGSSLMODE: disable
PGUSER: tinkerbell
TINKERBELL_GRPC_AUTHORITY: :42113
TINKERBELL_HTTP_AUTHORITY: :42114
TINK_AUTH_USERNAME: ${TINKERBELL_TINK_USERNAME}
TINK_AUTH_PASSWORD: ${TINKERBELL_TINK_PASSWORD}
depends_on:
tink-server-migration:
condition: service_started
db:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "wget -qO- 127.0.0.1:42114/cert"] # port needs to match TINKERBELL_HTTP_AUTHORITY
interval: 5s
timeout: 2s
retries: 30
volumes:
- ./state/certs:/certs/${FACILITY:-onprem}
ports:
- 42113:42113/tcp
- 42114:42114/tcp
tink-server-migration:
image: ${TINKERBELL_TINK_SERVER_IMAGE}
restart: on-failure
environment:
ONLY_MIGRATION: "true"
FACILITY: ${FACILITY:-onprem}
PGDATABASE: tinkerbell
PGHOST: db
PGPASSWORD: tinkerbell
PGPORT: 5432
PGSSLMODE: disable
PGUSER: tinkerbell
TINKERBELL_GRPC_AUTHORITY: :42113
TINKERBELL_HTTP_AUTHORITY: :42114
TINK_AUTH_USERNAME: ${TINKERBELL_TINK_USERNAME}
TINK_AUTH_PASSWORD: ${TINKERBELL_TINK_PASSWORD}
depends_on:
db:
condition: service_healthy
volumes:
- ./state/certs:/certs/${FACILITY:-onprem}
db:
image: postgres:10-alpine
restart: unless-stopped
environment:
POSTGRES_DB: tinkerbell
POSTGRES_PASSWORD: tinkerbell
POSTGRES_USER: tinkerbell
volumes:
- postgres_data:/var/lib/postgresql/data:rw
ports:
- 5432:5432
healthcheck:
test: ["CMD-SHELL", "pg_isready -U tinkerbell"]
interval: 1s
timeout: 1s
retries: 30
tink-cli:
image: ${TINKERBELL_TINK_CLI_IMAGE}
restart: unless-stopped
environment:
TINKERBELL_GRPC_AUTHORITY: 127.0.0.1:42113
TINKERBELL_CERT_URL: http://127.0.0.1:42114/cert
depends_on:
tink-server:
condition: service_healthy
db:
condition: service_healthy
network_mode: host
registry:
build:
context: registry
args:
REGISTRY_USERNAME: $TINKERBELL_REGISTRY_USERNAME
REGISTRY_PASSWORD: $TINKERBELL_REGISTRY_PASSWORD
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "curl --cacert /certs/ca.pem https://127.0.0.1"]
interval: 5s
timeout: 1s
retries: 5
environment:
REGISTRY_HTTP_ADDR: 0.0.0.0:443
REGISTRY_HTTP_TLS_CERTIFICATE: /certs/server.pem
REGISTRY_HTTP_TLS_KEY: /certs/server-key.pem
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: "Registry Realm"
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
volumes:
- ./state/certs:/certs
- ./state/registry:/var/lib/registry
network_mode: host
boots:
image: ${TINKERBELL_TINK_BOOTS_IMAGE}
restart: unless-stopped
network_mode: host
command: -dhcp-addr 0.0.0.0:67 -tftp-addr $TINKERBELL_HOST_IP:69 -http-addr $TINKERBELL_HOST_IP:80 -log-level DEBUG
environment:
API_AUTH_TOKEN: ${PACKET_API_AUTH_TOKEN:-ignored}
API_CONSUMER_TOKEN: ${PACKET_CONSUMER_TOKEN:-ignored}
FACILITY_CODE: ${FACILITY:-onprem}
PACKET_ENV: ${PACKET_ENV:-testing}
PACKET_VERSION: ${PACKET_VERSION:-ignored}
ROLLBAR_TOKEN: ${ROLLBAR_TOKEN:-ignored}
ROLLBAR_DISABLE: ${ROLLBAR_DISABLE:-1}
MIRROR_HOST: ${TINKERBELL_HOST_IP:-127.0.0.1}:8080
DNS_SERVERS: 8.8.8.8
PUBLIC_IP: $TINKERBELL_HOST_IP
BOOTP_BIND: $TINKERBELL_HOST_IP:67
HTTP_BIND: $TINKERBELL_HOST_IP:80
SYSLOG_BIND: $TINKERBELL_HOST_IP:514
TFTP_BIND: $TINKERBELL_HOST_IP:69
DOCKER_REGISTRY: $TINKERBELL_HOST_IP
REGISTRY_USERNAME: $TINKERBELL_REGISTRY_USERNAME
REGISTRY_PASSWORD: $TINKERBELL_REGISTRY_PASSWORD
TINKERBELL_GRPC_AUTHORITY: $TINKERBELL_HOST_IP:42113
TINKERBELL_CERT_URL: http://$TINKERBELL_HOST_IP:42114/cert
ELASTIC_SEARCH_URL: $TINKERBELL_HOST_IP:9200
DATA_MODEL_VERSION: 1
depends_on:
db:
condition: service_healthy
ports:
- $TINKERBELL_HOST_IP:80:80/tcp
- 67:67/udp
- 69:69/udp
nginx:
image: nginx:alpine
restart: unless-stopped
tty: true
ports:
- 8080:80/tcp
volumes:
- ./state/webroot:/usr/share/nginx/html/
hegel:
image: ${TINKERBELL_TINK_HEGEL_IMAGE}
restart: unless-stopped
network_mode: host
environment:
ROLLBAR_TOKEN: ${ROLLBAR_TOKEN-ignored}
ROLLBAR_DISABLE: 1
PACKET_ENV: testing
PACKET_VERSION: ${PACKET_VERSION:-ignored}
GRPC_PORT: 42115
HEGEL_FACILITY: ${FACILITY:-onprem}
HEGEL_USE_TLS: 0
TINKERBELL_GRPC_AUTHORITY: 127.0.0.1:42113
TINKERBELL_CERT_URL: http://127.0.0.1:42114/cert
DATA_MODEL_VERSION: 1
CUSTOM_ENDPOINTS: '{"/metadata":""}'
depends_on:
db:
condition: service_healthy
volumes:
postgres_data:

View File

@ -1,7 +0,0 @@
FROM registry:2.7.1
RUN apk add --no-cache --update curl apache2-utils
ARG REGISTRY_USERNAME
ARG REGISTRY_PASSWORD
RUN mkdir -p /certs /auth
RUN htpasswd -Bbn ${REGISTRY_USERNAME} ${REGISTRY_PASSWORD} > /auth/htpasswd
EXPOSE 443

View File

@ -2,3 +2,4 @@
terraform.tfstate
terraform.tfstate.backup
terraform.tfvars
.terraform.lock.hcl

View File

@ -1,66 +0,0 @@
#!/usr/bin/env bash
YUM="yum"
APT="apt"
PIP3="pip3"
YUM_CONFIG_MGR="yum-config-manager"
WHICH_YUM=$(command -v $YUM)
WHICH_APT=$(command -v $APT)
YUM_INSTALL="$YUM install"
APT_INSTALL="$APT install"
PIP3_INSTALL="$PIP3 install"
declare -a YUM_LIST=("https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.6-3.3.el7.x86_64.rpm"
"docker-ce"
"docker-ce-cli"
"epel-release"
"pass"
"python3")
declare -a APT_LIST=("docker"
"docker-compose" "pass")
add_yum_repo() (
$YUM_CONFIG_MGR --add-repo https://download.docker.com/linux/centos/docker-ce.repo
)
update_yum() (
$YUM_INSTALL -y yum-utils
add_yum_repo
)
update_apt() (
$APT update
DEBIAN_FRONTEND=noninteractive $APT --yes --force-yes -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" upgrade
)
restart_docker_service() (
service docker restart
)
install_yum_packages() (
$YUM_INSTALL "${YUM_LIST[@]}" -y
)
install_pip3_packages() (
$PIP3_INSTALL docker-compose
)
install_apt_packages() (
$APT_INSTALL "${APT_LIST[@]}" -y
)
main() (
if [[ -n $WHICH_YUM ]]; then
update_yum
install_yum_packages
install_pip3_packages
restart_docker_service
elif [[ -n $WHICH_APT ]]; then
update_apt
install_apt_packages
restart_docker_service
else
echo "Unknown platform. Error while installing the required packages"
exit 1
fi
)
main

View File

@ -3,7 +3,7 @@ terraform {
required_providers {
metal = {
source = "equinix/metal"
version = "1.0.0"
version = "3.1.0"
}
null = {
source = "hashicorp/null"
@ -27,72 +27,9 @@ resource "metal_vlan" "provisioning_vlan" {
project_id = var.project_id
}
# Create a device and add it to tf_project_1
resource "metal_device" "tink_provisioner" {
hostname = "tink-provisioner"
plan = var.device_type
facilities = [var.facility]
operating_system = "ubuntu_18_04"
billing_cycle = "hourly"
project_id = var.project_id
user_data = file("install_package.sh")
}
resource "null_resource" "tink_directory" {
connection {
type = "ssh"
user = var.ssh_user
host = metal_device.tink_provisioner.network[0].address
}
provisioner "remote-exec" {
inline = [
"mkdir -p /root/tink/deploy"
]
}
provisioner "file" {
source = "../../setup.sh"
destination = "/root/tink/setup.sh"
}
provisioner "file" {
source = "../../generate-env.sh"
destination = "/root/tink/generate-env.sh"
}
provisioner "file" {
source = "../../current_versions.sh"
destination = "/root/tink/current_versions.sh"
}
provisioner "file" {
source = "../../deploy"
destination = "/root/tink"
}
provisioner "file" {
source = "nat_interface"
destination = "/root/tink/.nat_interface"
}
provisioner "remote-exec" {
inline = [
"chmod +x /root/tink/*.sh /root/tink/deploy/tls/*.sh"
]
}
}
resource "metal_device_network_type" "tink_provisioner_network_type" {
device_id = metal_device.tink_provisioner.id
type = "hybrid"
}
# Create a device and add it to tf_project_1
resource "metal_device" "tink_worker" {
count = var.worker_count
hostname = "tink-worker-${count.index}"
hostname = "tink-worker"
plan = var.device_type
facilities = [var.facility]
operating_system = "custom_ipxe"
@ -103,12 +40,36 @@ resource "metal_device" "tink_worker" {
}
resource "metal_device_network_type" "tink_worker_network_type" {
count = var.worker_count
device_id = metal_device.tink_worker[count.index].id
device_id = metal_device.tink_worker.id
type = "layer2-individual"
}
# Attach VLAN to worker
resource "metal_port_vlan_attachment" "worker" {
depends_on = [metal_device_network_type.tink_worker_network_type]
device_id = metal_device.tink_worker.id
port_name = "eth0"
vlan_vnid = metal_vlan.provisioning_vlan.vxlan
}
# Create a device and add it to tf_project_1
resource "metal_device" "tink_provisioner" {
hostname = "tink-provisioner"
plan = var.device_type
facilities = [var.facility]
operating_system = "ubuntu_20_04"
billing_cycle = "hourly"
project_id = var.project_id
user_data = file("setup.sh")
}
resource "metal_device_network_type" "tink_provisioner_network_type" {
device_id = metal_device.tink_provisioner.id
type = "hybrid"
}
# Attach VLAN to provisioner
resource "metal_port_vlan_attachment" "provisioner" {
depends_on = [metal_device_network_type.tink_provisioner_network_type]
@ -117,40 +78,30 @@ resource "metal_port_vlan_attachment" "provisioner" {
vlan_vnid = metal_vlan.provisioning_vlan.vxlan
}
# Attach VLAN to worker
resource "metal_port_vlan_attachment" "worker" {
count = var.worker_count
depends_on = [metal_device_network_type.tink_worker_network_type]
device_id = metal_device.tink_worker[count.index].id
port_name = "eth0"
vlan_vnid = metal_vlan.provisioning_vlan.vxlan
}
data "template_file" "worker_hardware_data" {
count = var.worker_count
template = file("${path.module}/hardware_data.tpl")
vars = {
id = metal_device.tink_worker[count.index].id
facility_code = metal_device.tink_worker[count.index].deployed_facility
plan_slug = metal_device.tink_worker[count.index].plan
address = "192.168.1.${count.index + 5}"
mac = metal_device.tink_worker[count.index].ports[1].mac
}
}
resource "null_resource" "hardware_data" {
count = var.worker_count
depends_on = [null_resource.tink_directory]
resource "null_resource" "setup" {
connection {
type = "ssh"
user = var.ssh_user
user = "root"
host = metal_device.tink_provisioner.network[0].address
private_key = file("~/.ssh/id_rsa")
}
# need to tar the compose directory because the 'provisioner "file"' does not preserve file permissions
provisioner "local-exec" {
command = "cd ../ && tar zcvf compose.tar.gz compose"
}
provisioner "file" {
content = data.template_file.worker_hardware_data[count.index].rendered
destination = "/root/tink/deploy/hardware-data-${count.index}.json"
source = "../compose.tar.gz"
destination = "/root/compose.tar.gz"
}
provisioner "remote-exec" {
inline = [
"cd /root && tar zxvf /root/compose.tar.gz -C /root/sandbox",
"cd /root/sandbox/compose && TINKERBELL_CLIENT_MAC=${metal_device.tink_worker.ports[1].mac} TINKERBELL_TEMPLATE_MANIFEST=/manifests/template/ubuntu-equinix-metal.yaml TINKERBELL_HARDWARE_MANIFEST=/manifests/hardware/hardware-equinix-metal.json docker-compose up -d"
]
}
}

View File

@ -1 +0,0 @@
bond0

View File

@ -1,15 +1,7 @@
output "provisioner_dns_name" {
value = "${split("-", metal_device.tink_provisioner.id)[0]}.packethost.net"
}
output "provisioner_ip" {
value = metal_device.tink_provisioner.network[0].address
}
output "worker_mac_addr" {
value = formatlist("%s", metal_device.tink_worker[*].ports[1].mac)
}
output "worker_sos" {
value = formatlist("%s@sos.%s.platformequinix.com", metal_device.tink_worker[*].id, metal_device.tink_worker[*].deployed_facility)
value = formatlist("%s@sos.%s.platformequinix.com", metal_device.tink_worker[*].id, metal_device.tink_worker.deployed_facility)
}

66
deploy/terraform/setup.sh Executable file
View File

@ -0,0 +1,66 @@
#!/usr/bin/env bash
set -xo pipefail
install_docker() {
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
update_apt
DEBIAN_FRONTEND=noninteractive apt install -y apt-transport-https ca-certificates curl gnupg-agent gnupg2 software-properties-common docker-ce docker-ce-cli containerd.io
}
install_docker_compose() {
curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
}
update_apt() (
$APT update
DEBIAN_FRONTEND=noninteractive $APT --yes --force-yes -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" upgrade
)
restart_docker_service() (
service docker restart
)
# get_second_interface_from_bond0 returns the second interface of the bond0 interface
get_second_interface_from_bond0() {
local return_value
return_value=$(cut -d' ' -f2 /sys/class/net/bond0/bonding/slaves | xargs)
echo "${return_value}"
}
# setup_layer2_network removes the second interface from bond0 and uses it for the layer2 network
# https://metal.equinix.com/developers/docs/layer2-networking/hybrid-unbonded-mode/
setup_layer2_network() {
local layer2_interface="$1"
#local ip_addr="$2"
ifenslave -d bond0 "${layer2_interface}"
#ip addr add ${ip_addr}/24 dev "${layer2_interface}"
ip addr add 192.168.50.4/24 dev "${layer2_interface}"
ip link set dev "${layer2_interface}" up
}
# make_host_gw_server makes the host a gateway server
make_host_gw_server() {
local incoming_interface="$1"
local outgoing_interface="$2"
iptables -t nat -A POSTROUTING -o "${outgoing_interface}" -j MASQUERADE
iptables -A FORWARD -i "${outgoing_interface}" -o "${incoming_interface}" -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i "${incoming_interface}" -o "${outgoing_interface}" -j ACCEPT
}
main() (
#local provisioner_ip="$1"
install_docker
install_docker_compose
restart_docker_service
mkdir -p /root/sandbox/compose
local layer2_interface
layer2_interface="$(get_second_interface_from_bond0)"
setup_layer2_network "${layer2_interface}" #"${provisioner_ip}"
make_host_gw_server "${layer2_interface}" "bond0"
)
main #"$1"

View File

@ -8,11 +8,6 @@ variable "project_id" {
type = string
}
variable "worker_count" {
description = "Number of Workers"
type = number
default = 1
}
variable "facility" {
description = "Packet facility to provision in"
type = string
@ -24,9 +19,3 @@ variable "device_type" {
description = "Type of device to provision"
default = "c3.small.x86"
}
variable "ssh_user" {
description = "Username that will be used to transfer file from your local environment to the provisioner"
type = string
default = "root"
}

View File

@ -1 +0,0 @@
*/

View File

@ -1,7 +0,0 @@
FROM alpine:3.11
ENTRYPOINT [ "/entrypoint.sh" ]
RUN apk add --no-cache --update --upgrade ca-certificates postgresql-client
RUN apk add --no-cache --update --upgrade --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing cfssl
COPY . .

View File

@ -1,12 +0,0 @@
{
"CN": "Autogenerated CA",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"L": "@FACILITY@"
}
]
}

View File

@ -1,13 +0,0 @@
#!/usr/bin/env sh
# set -o errexit -o nounset -o pipefail
if [ -z "${TINKERBELL_TLS_CERT:-}" ]; then
(
echo "creating directory"
mkdir -p "certs"
./gencerts.sh
)
fi
"$@"

View File

@ -1,30 +0,0 @@
#!/usr/bin/env sh
set -eux
cd /certs
if [ ! -f ca-key.pem ]; then
cfssl gencert \
-initca ca.json | cfssljson -bare ca
fi
if [ ! -f server.pem ]; then
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=/ca-config.json \
-profile=server \
server-csr.json |
cfssljson -bare server
fi
cat server.pem ca.pem >bundle.pem.tmp
# only "modify" the file if truly necessary since workflow will serve it with
# modtime info for client caching purposes
if ! cmp -s bundle.pem.tmp bundle.pem; then
mv bundle.pem.tmp bundle.pem
else
rm bundle.pem.tmp
fi

View File

@ -1 +0,0 @@
.vagrant

View File

@ -1 +0,0 @@
https://tinkerbell.org/docs/setup/local-with-vagrant/

View File

@ -1,109 +1,98 @@
ENV['VAGRANT_NO_PARALLEL'] = 'yes'
# -*- mode: ruby -*-
# vi: set ft=ruby :
num_workers = ENV['TINKERBELL_NUM_WORKERS'] || '1'
PROVISIONER_IP = "192.168.50.4"
MACHINE1_IP = "192.168.50.43"
# Returns true if `GUI` environment variable exists, value does not matter.
# Defaults to false
def worker_gui_enabled?
ENV.include?('VAGRANT_WORKER_GUI')
$script = <<-SCRIPT
ip addr add 192.168.50.4/24 dev eth1
ip link set dev eth1 up
SCRIPT
unless Vagrant.has_plugin?("vagrant-docker-compose")
system("vagrant plugin install vagrant-docker-compose")
puts "Dependencies installed, please try the command again."
exit
end
# Returns true if `SCALE` environment variable exists, value does not matter.
# Defaults to false
def worker_display_scale_enabled?
ENV.include?('VAGRANT_WORKER_SCALE')
end
Vagrant.configure("2") do |config|
config.vm.define "provisioner" do |provisioner|
provisioner.vm.box = "generic/ubuntu2004"
provisioner.vm.synced_folder '../', '/vagrant'
provisioner.vm.provision :docker
provisioner.vm.provision "shell", inline: $script
provisioner.vm.network "private_network", ip: PROVISIONER_IP,
libvirt__network_name: "tink_network",
libvirt__host_ip: '192.168.50.1',
libvirt__netmask: "255.255.255.0",
libvirt__dhcp_enabled: false,
auto_config: false
def configure_nat
return ENV.has_key?('TINKERBELL_CONFIGURE_NAT') ? ENV['TINKERBELL_CONFIGURE_NAT'] : 'true'
end
def libvirt_forward_mode
return configure_nat == 'false' ? 'nat' : 'none'
end
Vagrant.configure('2') do |config|
config.vm.define :provisioner do |provisioner|
provisioner.vm.box = "tinkerbelloss/sandbox-ubuntu1804"
provisioner.vm.box_version = "0.2.0"
provisioner.vm.hostname = 'provisioner'
provisioner.vm.synced_folder './../../', '/vagrant'
provisioner.vm.provision :shell,
path: './scripts/tinkerbell.sh',
provisioner.vm.provider "virtualbox" do |v, override|
v.memory = 2048
v.cpus = 2
override.vm.synced_folder '../', '/vagrant'
# vagrant plugin install vagrant-docker-compose
override.vm.provision :docker_compose,
compose_version: "1.29.1",
yml: "/vagrant/compose/docker-compose.yml",
run:"always",
env: {
'TINKERBELL_CONFIGURE_NAT': configure_nat,
"TINKERBELL_HOST_IP": PROVISIONER_IP,
"TINKERBELL_CLIENT_IP": MACHINE1_IP,
"REPO_TOP_LEVEL": "/vagrant/compose",
"TINKERBELL_HARDWARE_MANIFEST": "/manifests/hardware/hardware.json",
"TINKERBELL_TEMPLATE_MANIFEST": "/manifests/template/ubuntu.yaml"
}
provisioner.vm.network :private_network,
virtualbox__intnet: "tink_network",
libvirt__network_name: "tink_network",
libvirt__host_ip: "192.168.1.6",
libvirt__netmask: "255.255.255.248",
libvirt__dhcp_enabled: false,
libvirt__forward_mode: libvirt_forward_mode,
libvirt__adapter: 1,
auto_config: false
provisioner.vm.network "forwarded_port", guest: 42113, host: 42113
provisioner.vm.network "forwarded_port", guest: 42114, host: 42114
provisioner.vm.provider :libvirt do |lv, override|
lv.memory = 2*1024
lv.cpus = 2
lv.cpu_mode = 'host-passthrough'
end
provisioner.vm.provider :virtualbox do |vb, override|
vb.memory = 2*1024
vb.cpus = 2
provisioner.vm.provider "libvirt" do |l, override|
override.vm.synced_folder '../', '/vagrant', type: "nfs", nfs_version: 4, "nfs_udp": false, mount_options: ["rw", "vers=4", "tcp"]
# vagrant plugin install vagrant-docker-compose
override.vm.provision :docker_compose,
compose_version: "1.29.1",
yml: "/vagrant/compose/docker-compose.yml",
run:"always",
env: {
"TINKERBELL_HOST_IP": PROVISIONER_IP,
"TINKERBELL_CLIENT_IP": MACHINE1_IP,
"REPO_TOP_LEVEL": "/vagrant/compose",
"TINKERBELL_HARDWARE_MANIFEST": "/manifests/hardware/hardware-libvirt.json",
"TINKERBELL_TEMPLATE_MANIFEST": "/manifests/template/ubuntu-libvirt.yaml"
}
end
end
config.vm.define :machine1, autostart: false do |machine1|
(1..num_workers.to_i).each do |i|
mac_suffix = "%02x" % i
worker_suffix = i==1 ? "" : "i"
config.vm.define "worker#{worker_suffix}" do |worker|
worker.vm.box = nil
worker.vm.network :private_network,
mac: "0800270000#{mac_suffix}",
virtualbox__intnet: "tink_network",
machine1.ssh.insert_key = false
machine1.vm.boot_timeout = 10
machine1.vm.synced_folder '.', '/vagrant', disabled: true
machine1.vm.network :private_network, ip: MACHINE1_IP,
mac: "0800279EF53A",
adapter: 1,
libvirt__network_name: "tink_network",
libvirt__dhcp_enabled: false,
libvirt__forward_mode: libvirt_forward_mode,
auto_config: false
libvirt__forward_mode: 'nat'
worker.vm.provider :libvirt do |lv|
lv.memory = 4*1024
lv.cpus = 1
lv.boot 'network'
lv.mgmt_attach = false
lv.storage :file, :size => '40G'
lv.random :model => 'random'
machine1.vm.provider "libvirt" do |v|
v.storage :file, :size => '20G'
v.memory = 4096
v.cpus = 2
v.boot 'hd'
v.boot 'network'
v.graphics_ip = '0.0.0.0'
v.machine_arch = 'x86_64'
end
worker.vm.provider :virtualbox do |vb, worker|
worker.vm.box = 'generic/alpine38'
vb.memory = 4*1024
vb.cpus = 1
vb.gui = worker_gui_enabled?
vb.customize [
'setextradata', :id,
'GUI/ScaleFactor', '3.0'
] if worker_display_scale_enabled?
vb.customize [
'modifyvm', :id,
'--nic1', 'none',
'--boot1', 'net',
'--boot2', 'none',
'--boot3', 'none',
'--boot4', 'none',
'--macaddress1', "0800270000#{mac_suffix}"
]
end
machine1.vm.provider "virtualbox" do |v, override|
override.vm.box = 'jtyr/pxe'
v.memory = 2048
v.cpus = 2
v.gui = true
v.customize ['modifyvm', :id, '--nic1', 'hostonly', '--nic2', 'nat', '--boot1', 'disk', '--boot2', 'net']
v.customize ['setextradata', :id, 'GUI/ScaleFactor', '3.0']
v.check_guest_additions = false
end
end
end

View File

@ -1 +0,0 @@
output*

View File

@ -1,30 +0,0 @@
This directory contains a provisioning mechanism for the Vagrant boxes we ship
as part of Sandbox.
In order to self contain and distribute the required dependencies for Tinkerbell
and Sandbox without having to download all of them at runtime we decided to use
[Packer.io](https://packer.io) to build boxes that you can use when provisioning
Tinkerbell on Vagrant.
Currently the generated boxes are available via [Vagrant
Cloud](https://app.vagrantup.com/tinkerbelloss).
---
## Build
To build the boxes checkout the right directory and run
```terminal
$ packer build --parallel-builds=1 ./template.json
```
`-parallel-builds=1` is required because the template builds images for multiple
providers using the [Vagrant
builder](https://www.packer.io/docs/builders/vagrant) and I didn't manage to get
it to work in parallel yet.
## Deploy to Vagrant Cloud
I didn't find a way to make the Vagrant Cloud post processor to work. But I use
the vagrant cli `vagrant cloud publish` command.

View File

@ -1,57 +0,0 @@
#!/bin/bash
# abort this script on errors
set -euxo pipefail
setup_docker() (
# steps from https://docs.docker.com/engine/install/ubuntu/
sudo apt-get install -y \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common \
;
curl -fsSL https://download.docker.com/linux/ubuntu/gpg |
sudo apt-key add -
local repo
repo=$(
printf "deb [arch=amd64] https://download.docker.com/linux/ubuntu %s stable" \
"$(lsb_release -cs)"
)
sudo add-apt-repository "$repo"
sudo apt-get update
sudo apt-get install -y \
containerd.io \
docker-ce \
docker-ce-cli \
;
)
# from https://docs.docker.com/compose/install/
setup_docker_compose() (
local name url
name=docker-compose-$(uname -s)-$(uname -m)
url=https://github.com/docker/compose/releases/download/1.26.0/$name
curl -fsSLO "$url"
curl -fsSLO "$url.sha256"
sha256sum -c <"$name.sha256"
rm -f "$name.sha256"
chmod +x "$name"
sudo mv "$name" /usr/local/bin/docker-compose
)
main() (
export DEBIAN_FRONTEND=noninteractive
sudo apt-get update
setup_docker
setup_docker_compose
sudo apt-get install -y jq
sudo usermod -aG docker vagrant
)
main
sync # do not remove!

View File

@ -1,27 +0,0 @@
{
"builders": [
{
"communicator": "ssh",
"name": "vagrant-virtualbox",
"provider": "virtualbox",
"source_path": "generic/ubuntu1804",
"type": "vagrant"
},
{
"communicator": "ssh",
"name": "vagrant-libvirt",
"provider": "libvirt",
"source_path": "generic/ubuntu1804",
"type": "vagrant"
}
],
"provisioners": [
{
"script": "provision.sh",
"type": "shell"
}
],
"variables": {
"cloud_token": "{{ env `VAGRANT_CLOUD_TOKEN` }}"
}
}

View File

@ -1,59 +0,0 @@
#!/bin/bash
# abort this script on errors
set -euxo pipefail
whoami
cd /vagrant
make_certs_writable() (
local certdir="/etc/docker/certs.d/$TINKERBELL_HOST_IP"
sudo mkdir -p "$certdir"
sudo chown -R "$USER" "$certdir"
)
secure_certs() (
local certdir="/etc/docker/certs.d/$TINKERBELL_HOST_IP"
sudo chown "root" "$certdir"
)
configure_vagrant_user() (
echo -n "$TINKERBELL_REGISTRY_PASSWORD" |
sudo -iu vagrant docker login \
--username="$TINKERBELL_REGISTRY_USERNAME" \
--password-stdin "$TINKERBELL_HOST_IP"
)
setup_nat() (
iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
iptables -A FORWARD -i eth0 -o eth1 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
)
main() (
export DEBIAN_FRONTEND=noninteractive
if ! [[ -f ./.env ]]; then
./generate-env.sh eth1 >.env
fi
# shellcheck disable=SC1091
source ./.env
make_certs_writable
./setup.sh
if [[ ${TINKERBELL_CONFIGURE_NAT:=true} != "false" ]]; then
setup_nat
fi
secure_certs
configure_vagrant_user
set +x # don't want the stderr output from xtrace messing with the post-setup-message
[[ -f /tmp/post-setup-message ]] && cat /tmp/post-setup-message
)
main

231
docs/quickstarts/COMPOSE.md Normal file
View File

@ -0,0 +1,231 @@
# Quick start guide for Docker Compose
This option will stand up the provisioner using Docker Compose.
You will need to bring your own machines to provision.
## Prerequisites
- [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) is installed
- [Docker](https://docs.docker.com/get-docker/) is installed (version >= 19.03)
- [Docker Compose](https://docs.docker.com/compose/install/) is installed (version >= 1.29.0)
## Steps
1. Clone this repository
```bash
git clone https://github.com/tinkerbell/sandbox.git
cd sandbox
```
2. Set the public IP address for the provisioner
```bash
# This should be an IP that's on an interface where you will be provisioning machines
export TINKERBELL_HOST_IP=192.168.2.111
```
3. Set the IP and MAC address of the machine you want to provision (if you want Tink hardware, template, and workflow records auto-generated)
```bash
# This IP and MAC of the machine to be provisioned
# The IP should normally be in the same network as the IP used for the provisioner
export TINKERBELL_CLIENT_IP=192.168.2.211
export TINKERBELL_CLIENT_MAC=08:00:27:9E:F5:3A
```
4. Start the provisioner
```bash
cd deploy/compose
docker-compose up -d
# This process will take about 5-10 minutes depending on your internet connection.
# OSIE is about 2GB in size and the Ubuntu Focal image is about 500MB
```
<details>
<summary>expected output</summary>
```bash
Creating network "deploy_default" with the default driver
Creating volume "deploy_postgres_data" with default driver
Creating volume "deploy_certs" with default driver
Creating volume "deploy_auth" with default driver
Pulling tls-gen (cfssl/cfssl:)...
latest: Pulling from cfssl/cfssl
50e431f79093: Pull complete
dd8c6d374ea5: Pull complete
c85513200d84: Pull complete
55769680e827: Pull complete
15357f5e50c4: Pull complete
5dcdacb923a0: Pull complete
3b6795100674: Pull complete
572d1ec44610: Pull complete
b3de5480e786: Pull complete
03ed00a20dd4: Pull complete
Digest: sha256:c21e852f3904e2ba77960e9cba23c69d9231467795a8a160ce1d848e621381ea
Status: Downloaded newer image for cfssl/cfssl:latest
Pulling registry-auth (httpd:2)...
2: Pulling from library/httpd
b4d181a07f80: Pull complete
4b72f5187e6e: Pull complete
12b2c44d04b2: Pull complete
35c238b46d30: Pull complete
1adcec05f52b: Pull complete
Digest: sha256:1fd07d599a519b594b756d2e4e43a72edf7e30542ce646f5eb3328cf3b12341a
Status: Downloaded newer image for httpd:2
Pulling osie-work (alpine:)...
latest: Pulling from library/alpine
5843afab3874: Pull complete
Digest: sha256:234cb88d3020898631af0ccbbcca9a66ae7306ecd30c9720690858c1b007d2a0
Status: Downloaded newer image for alpine:latest
Pulling ubuntu-image-setup (ubuntu:)...
latest: Pulling from library/ubuntu
a31c7b29f4ad: Pull complete
Digest: sha256:b3e2e47d016c08b3396b5ebe06ab0b711c34e7f37b98c9d37abe794b71cea0a2
Status: Downloaded newer image for ubuntu:latest
Pulling db (postgres:10-alpine)...
10-alpine: Pulling from library/postgres
5843afab3874: Already exists
525703b16f79: Pull complete
86f8340bd3d9: Pull complete
79044baaabb2: Pull complete
36cf25109e96: Pull complete
bc752cda1992: Pull complete
17905079c3e2: Pull complete
04d52afe0744: Pull complete
325e49088bb1: Pull complete
Digest: sha256:0eef1c94e0c4b0c4b84437785d0c5926f62b7f537627d97cf9ebcd7b205bc9aa
Status: Downloaded newer image for postgres:10-alpine
Pulling tink-server-migration (quay.io/tinkerbell/tink:sha-8ea8a0e5)...
sha-8ea8a0e5: Pulling from tinkerbell/tink
ddad3d7c1e96: Pull complete
721d7c3819bb: Pull complete
bb168258b5ea: Pull complete
Digest: sha256:84fc83f8562901d0b27e7ebb453a7f27e5797d17fb0b6899f92002df840fbf21
Status: Downloaded newer image for quay.io/tinkerbell/tink:sha-8ea8a0e5
Pulling create-tink-records (quay.io/tinkerbell/tink-cli:sha-8ea8a0e5)...
sha-8ea8a0e5: Pulling from tinkerbell/tink-cli
ddad3d7c1e96: Already exists
30e0616e2b41: Pull complete
5066d7cb6405: Pull complete
Digest: sha256:0fc5441e9ef6e94eff7bf1ae9cf9a15a98581c742890d2d7130fd9542b12802d
Status: Downloaded newer image for quay.io/tinkerbell/tink-cli:sha-8ea8a0e5
Pulling registry (registry:2.7.1)...
2.7.1: Pulling from library/registry
ddad3d7c1e96: Already exists
6eda6749503f: Pull complete
363ab70c2143: Pull complete
5b94580856e6: Pull complete
12008541203a: Pull complete
Digest: sha256:aba2bfe9f0cff1ac0618ec4a54bfefb2e685bbac67c8ebaf3b6405929b3e616f
Status: Downloaded newer image for registry:2.7.1
Pulling images-to-local-registry (quay.io/containers/skopeo:latest)...
latest: Pulling from containers/skopeo
7d63354ae1f4: Pull complete
75b596804be5: Pull complete
51cba67b7076: Pull complete
18e224798580: Pull complete
2b087916826e: Pull complete
695aa9f61886: Pull complete
Digest: sha256:ab8d8b9e7f61b78a7f24ec4076e0ef895e596cf31dd32d9ee6e718c571f02cde
Status: Downloaded newer image for quay.io/containers/skopeo:latest
Pulling boots (quay.io/tinkerbell/boots:sha-cb0290f8)...
sha-cb0290f8: Pulling from tinkerbell/boots
339de151aab4: Pull complete
edc0420940c8: Pull complete
85dd670aacee: Pull complete
Digest: sha256:8e106bf73122d08ce9ef75f5cae4be77ecff38c2b55cb44541caabf94d325de9
Status: Downloaded newer image for quay.io/tinkerbell/boots:sha-cb0290f8
Pulling osie-bootloader (nginx:alpine)...
alpine: Pulling from library/nginx
5843afab3874: Already exists
0dc18a5274f2: Pull complete
48a0ee941dcd: Pull complete
2446243a1a3f: Pull complete
cbf0756b41fb: Pull complete
c72750a979b9: Pull complete
Digest: sha256:91528597e842ab1b3b25567191fa7d4e211cb3cc332071fa031cfed2b5892f9e
Status: Downloaded newer image for nginx:alpine
Pulling hegel (quay.io/tinkerbell/hegel:sha-9f5da0a8)...
sha-9f5da0a8: Pulling from tinkerbell/hegel
5d20c808ce19: Pull complete
c9b8cebd2f86: Pull complete
a3e87bc13599: Pull complete
ac61d4bd540b: Pull complete
Digest: sha256:9d3c6d5e4bc957cedafbeec22da4f59d94c78b65d84adbd0c8f947c51cf3668b
Status: Downloaded newer image for quay.io/tinkerbell/hegel:sha-9f5da0a8
Creating deploy_registry-auth_1 ... done
Creating deploy_tls-gen_1 ... done
Creating deploy_db_1 ... done
Creating deploy_osie-work_1 ... done
Creating deploy_ubuntu-image-setup_1 ... done
Creating deploy_osie-bootloader_1 ... done
Creating deploy_registry_1 ... done
Creating deploy_tink-server-migration_1 ... done
Creating deploy_tink-server_1 ... done
Creating deploy_images-to-local-registry_1 ... done
Creating deploy_create-tink-records_1 ... done
Creating deploy_hegel_1 ... done
Creating deploy_registry-ca-crt-download_1 ... done
Creating deploy_boots_1 ... done
Creating deploy_tink-cli_1 ... done
```
</details>
5. Power up the machine to be provisioned
6. Watch for the provisioner to complete
```bash
# watch the workflow events and status for workflow completion
# once the workflow is complete (see the expected output below for completion), move on to the next step
wid=$(cat manifests/workflow/workflow_id.txt); docker exec -it compose_tink-cli_1 watch "tink workflow events ${wid}; tink workflow state ${wid}"
```
<details>
<summary>expected output</summary>
```bash
+--------------------------------------+-----------------+---------------------+----------------+---------------------------------+---------------+
| WORKER ID | TASK NAME | ACTION NAME | EXECUTION TIME | MESSAGE | ACTION STATUS |
+--------------------------------------+-----------------+---------------------+----------------+---------------------------------+---------------+
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | stream-ubuntu-image | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | stream-ubuntu-image | 15 | finished execution successfully | STATE_SUCCESS |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | install-openssl | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | install-openssl | 1 | finished execution successfully | STATE_SUCCESS |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | create-user | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | create-user | 0 | finished execution successfully | STATE_SUCCESS |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | enable-ssh | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | enable-ssh | 0 | finished execution successfully | STATE_SUCCESS |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | disable-apparmor | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | disable-apparmor | 0 | finished execution successfully | STATE_SUCCESS |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | write-netplan | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | write-netplan | 0 | finished execution successfully | STATE_SUCCESS |
+--------------------------------------+-----------------+---------------------+----------------+---------------------------------+---------------+
+----------------------+--------------------------------------+
| FIELD NAME | VALUES |
+----------------------+--------------------------------------+
| Workflow ID | 3107919b-e59d-11eb-bf99-0242ac120005 |
| Workflow Progress | 100% |
| Current Task | os-installation |
| Current Action | write-netplan |
| Current Worker | 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 |
| Current Action State | STATE_SUCCESS |
+----------------------+--------------------------------------+
```
</details>
7. Reboot the machine
8. Login to the machine
The machine has been provisioned with Ubuntu Focal.
You can now SSH into the machine.
```bash
# crtl-c to exit the watch
ssh tink@${TINKERBELL_CLIENT_IP} # user/pass => tink/tink
```

View File

@ -0,0 +1,3 @@
# Quick start guide for Kubernetes
> coming soon...

View File

@ -0,0 +1,3 @@
# Quick start guide for Multipass
> coming soon...

View File

@ -0,0 +1,108 @@
# Quick start guide for Terraform on Equinix Metal
This option will stand up the provisioner on a Bare Metal machine using Terraform with Equinix Metal.
This option will also show you how to create a machine to provision.
## Prerequisites
- [Terraform](https://www.vagrantup.com/downloads) is installed
## Steps
1. Clone this repository
```bash
git clone https://github.com/tinkerbell/sandbox.git
cd sandbox
```
2. Set your Equinix Metal project id and access token
```bash
cd deploy/terraform
cat << EOF > terraform.tfvars
metal_api_token = "awegaga4gs4g"
project_id = "235-23452-245-345"
EOF
```
3. Start the provisioner
```bash
terraform init
terraform apply
# This process will take about 5-10 minutes.
# Most of the time will be to download OSIE.
# OSIE is about 2GB in size and the Ubuntu Focal image is about 500MB
```
4. Reboot the machine
In the [Equinix Metal Web UI](https://console.equinix.com), find the `tink_worker` and reboot it.
Or if you have the [Equinix Metal CLI](https://github.com/equinix/metal-cli) installed run the following:
```bash
metal device reboot -i $(terraform show -json | jq -r '.values.root_module.resources[1].values.id')
```
5. Watch the provision complete
```bash
# log in to the provisioner
ssh root@139.178.69.231
# watch the workflow events and status for workflow completion
# once the workflow is complete (see the expected output below for completion), move on to the next step
wid=$(cat sandbox/compose/manifests/workflow/workflow_id.txt); docker exec -it compose_tink-cli_1 watch "tink workflow events ${wid}; tink workflow state ${wid}"
```
<details>
<summary>expected output</summary>
```bash
+--------------------------------------+-----------------+---------------------+----------------+---------------------------------+---------------+
| WORKER ID | TASK NAME | ACTION NAME | EXECUTION TIME | MESSAGE | ACTION STATUS |
+--------------------------------------+-----------------+---------------------+----------------+---------------------------------+---------------+
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | stream-ubuntu-image | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | stream-ubuntu-image | 15 | finished execution successfully | STATE_SUCCESS |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | install-openssl | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | install-openssl | 1 | finished execution successfully | STATE_SUCCESS |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | create-user | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | create-user | 0 | finished execution successfully | STATE_SUCCESS |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | enable-ssh | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | enable-ssh | 0 | finished execution successfully | STATE_SUCCESS |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | disable-apparmor | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | disable-apparmor | 0 | finished execution successfully | STATE_SUCCESS |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | write-netplan | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | write-netplan | 0 | finished execution successfully | STATE_SUCCESS |
+--------------------------------------+-----------------+---------------------+----------------+---------------------------------+---------------+
+----------------------+--------------------------------------+
| FIELD NAME | VALUES |
+----------------------+--------------------------------------+
| Workflow ID | 3107919b-e59d-11eb-bf99-0242ac120005 |
| Workflow Progress | 100% |
| Current Task | os-installation |
| Current Action | write-netplan |
| Current Worker | 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 |
| Current Action State | STATE_SUCCESS |
+----------------------+--------------------------------------+
```
</details>
6. Reboot the machine
Now reboot the `tink-worker` via the [Equinix Metal Web UI](https://console.equinix.com), or if you have the [Equinix Metal CLI](https://github.com/equinix/metal-cli) installed run the following:
```bash
metal device reboot -i $(terraform show -json | jq -r '.values.root_module.resources[1].values.id')
```
7. Login to the machine
The machine has been provisioned with Ubuntu Focal.
Wait for the reboot to complete and then you can SSH into it.
```bash
# crtl-c to exit the watch
ssh tink@192.168.50.43 # user/pass => tink/tink
```

View File

@ -0,0 +1,290 @@
# Quick start guide for Vagrant and Libvirt
This option will stand up the provisioner in Libvirt using Vagrant.
This option will also show you how to create a machine to provision.
## Prerequisites
- [Vagrant](https://www.vagrantup.com/downloads) is installed
- [Libvirt](https://ubuntu.com/server/docs/virtualization-libvirt) is installed
## Steps
1. Clone this repository
```bash
git clone https://github.com/tinkerbell/sandbox.git
cd sandbox
```
2. Start the provisioner
```bash
cd deploy/vagrant
vagrant up
# This process will take about 5-10 minutes depending on your internet connection.
# OSIE is about 2GB in size and the Ubuntu Focal image is about 500MB
```
<details>
<summary>expected output</summary>
```bash
Bringing machine 'provisioner' up with 'libvirt' provider...
==> provisioner: Checking if box 'generic/ubuntu2004' version '3.3.4' is up to date...
==> provisioner: Creating image (snapshot of base box volume).
==> provisioner: Creating domain with the following settings...
==> provisioner: -- Name: vagrant_provisioner
==> provisioner: -- Domain type: kvm
==> provisioner: -- Cpus: 2
==> provisioner: -- Feature: acpi
==> provisioner: -- Feature: apic
==> provisioner: -- Feature: pae
==> provisioner: -- Memory: 2048M
==> provisioner: -- Management MAC:
==> provisioner: -- Loader:
==> provisioner: -- Nvram:
==> provisioner: -- Base box: generic/ubuntu2004
==> provisioner: -- Storage pool: default
==> provisioner: -- Image: /var/lib/libvirt/images/vagrant_provisioner.img (128G)
==> provisioner: -- Volume Cache: default
==> provisioner: -- Kernel:
==> provisioner: -- Initrd:
==> provisioner: -- Graphics Type: vnc
==> provisioner: -- Graphics Port: -1
==> provisioner: -- Graphics IP: 127.0.0.1
==> provisioner: -- Graphics Password: Not defined
==> provisioner: -- Video Type: cirrus
==> provisioner: -- Video VRAM: 256
==> provisioner: -- Sound Type:
==> provisioner: -- Keymap: en-us
==> provisioner: -- TPM Path:
==> provisioner: -- INPUT: type=mouse, bus=ps2
==> provisioner: Pruning invalid NFS exports. Administrator privileges will be required...
[sudo] password for tink:
==> provisioner: Creating shared folders metadata...
==> provisioner: Starting domain.
==> provisioner: Waiting for domain to get an IP address...
==> provisioner: Waiting for SSH to become available...
provisioner:
provisioner: Vagrant insecure key detected. Vagrant will automatically replace
provisioner: this with a newly generated keypair for better security.
provisioner:
provisioner: Inserting generated public key within guest...
provisioner: Removing insecure key from the guest if it's present...
provisioner: Key inserted! Disconnecting and reconnecting using new SSH key...
==> provisioner: Configuring and enabling network interfaces...
==> provisioner: Installing NFS client...
==> provisioner: Exporting NFS shared folders...
==> provisioner: Preparing to edit /etc/exports. Administrator privileges will be required...
==> provisioner: Mounting NFS shared folders...
==> provisioner: Running provisioner: docker...
provisioner: Installing Docker onto machine...
==> provisioner: Running provisioner: shell...
provisioner: Running: inline script
==> provisioner: Running provisioner: docker_compose...
provisioner: Checking for Docker Compose installation...
provisioner: Getting machine and kernel name from guest machine...
provisioner: Downloading Docker Compose 1.29.1 for Linux x86_64
provisioner: Downloaded Docker Compose 1.29.1 has SHA256 signature 8097769d32e34314125847333593c8edb0dfc4a5b350e4839bef8c2fe8d09de7
provisioner: Uploading Docker Compose 1.29.1 to guest machine...
provisioner: Installing Docker Compose 1.29.1 in guest machine...
provisioner: Symlinking Docker Compose 1.29.1 in guest machine...
provisioner: Running docker-compose up...
==> provisioner: Creating network "vagrant_default" with the default driver
==> provisioner: Creating volume "vagrant_postgres_data" with default driver
==> provisioner: Creating volume "vagrant_certs" with default driver
==> provisioner: Creating volume "vagrant_auth" with default driver
==> provisioner: Pulling tls-gen (cfssl/cfssl:)...
provisioner: latest: Pulling from cfssl/cfssl
provisioner: Digest: sha256:c21e852f3904e2ba77960e9cba23c69d9231467795a8a160ce1d848e621381ea
provisioner: Status: Downloaded newer image for cfssl/cfssl:latest
==> provisioner: Pulling registry-auth (httpd:2)...
provisioner: 2: Pulling from library/httpd
provisioner: Digest: sha256:eacdd6c7419ab95b43a258321fc6b38cf56004de4f6a952fc0d96a12730e04de
provisioner: Status: Downloaded newer image for httpd:2
==> provisioner: Pulling osie-work (alpine:)...
provisioner: latest: Pulling from library/alpine
provisioner: Digest: sha256:eb3e4e175ba6d212ba1d6e04fc0782916c08e1c9d7b45892e9796141b1d379ae
provisioner: Status: Downloaded newer image for alpine:latest
==> provisioner: Pulling ubuntu-image-setup (ubuntu:)...
provisioner: latest: Pulling from library/ubuntu
provisioner: Digest: sha256:82becede498899ec668628e7cb0ad87b6e1c371cb8a1e597d83a47fac21d6af3
provisioner: Status: Downloaded newer image for ubuntu:latest
==> provisioner: Pulling db (postgres:10-alpine)...
provisioner: 10-alpine: Pulling from library/postgres
provisioner: Digest: sha256:07bb8292fa57fbe87f5426841105a19db7229e8e684299642e9c2046203abb10
provisioner: Status: Downloaded newer image for postgres:10-alpine
==> provisioner: Pulling tink-server-migration (quay.io/tinkerbell/tink:sha-8ea8a0e5)...
provisioner: sha-8ea8a0e5: Pulling from tinkerbell/tink
provisioner: Digest: sha256:84fc83f8562901d0b27e7ebb453a7f27e5797d17fb0b6899f92002df840fbf21
provisioner: Status: Downloaded newer image for quay.io/tinkerbell/tink:sha-8ea8a0e5
==> provisioner: Pulling create-tink-records (quay.io/tinkerbell/tink-cli:sha-8ea8a0e5)...
provisioner: sha-8ea8a0e5: Pulling from tinkerbell/tink-cli
provisioner: Digest: sha256:0fc5441e9ef6e94eff7bf1ae9cf9a15a98581c742890d2d7130fd9542b12802d
provisioner: Status: Downloaded newer image for quay.io/tinkerbell/tink-cli:sha-8ea8a0e5
==> provisioner: Pulling registry (registry:2.7.1)...
provisioner: 2.7.1: Pulling from library/registry
provisioner: Digest: sha256:121baf25069a56749f249819e36b386d655ba67116d9c1c6c8594061852de4da
provisioner: Status: Downloaded newer image for registry:2.7.1
==> provisioner: Pulling images-to-local-registry (quay.io/containers/skopeo:latest)...
provisioner: latest: Pulling from containers/skopeo
provisioner: Digest: sha256:7ae70111960190f0f638191a707a57301e6b71c2571be2d188c692ead47e9a23
provisioner: Status: Downloaded newer image for quay.io/containers/skopeo:latest
==> provisioner: Pulling boots (quay.io/tinkerbell/boots:sha-94f43947)...
provisioner: sha-94f43947: Pulling from tinkerbell/boots
provisioner: Digest: sha256:def67c645dc0517a166bb3ef7eba955e2112a28583ac908a8f84d1382b6046e8
provisioner: Status: Downloaded newer image for quay.io/tinkerbell/boots:sha-94f43947
==> provisioner: Pulling osie-bootloader (nginx:alpine)...
provisioner: alpine: Pulling from library/nginx
provisioner: Digest: sha256:bead42240255ae1485653a956ef41c9e458eb077fcb6dc664cbc3aa9701a05ce
provisioner: Status: Downloaded newer image for nginx:alpine
==> provisioner: Pulling hegel (quay.io/tinkerbell/hegel:sha-9f5da0a8)...
provisioner: sha-9f5da0a8: Pulling from tinkerbell/hegel
provisioner: Digest: sha256:9d3c6d5e4bc957cedafbeec22da4f59d94c78b65d84adbd0c8f947c51cf3668b
provisioner: Status: Downloaded newer image for quay.io/tinkerbell/hegel:sha-9f5da0a8
==> provisioner: Creating vagrant_registry-auth_1 ...
==> provisioner: Creating vagrant_osie-work_1 ...
==> provisioner: Creating vagrant_db_1 ...
==> provisioner: Creating vagrant_ubuntu-image-setup_1 ...
==> provisioner: Creating vagrant_tls-gen_1 ...
==> provisioner: Creating vagrant_osie-work_1 ... done
==> provisioner: Creating vagrant_ubuntu-image-setup_1 ... done
==> provisioner: Creating vagrant_db_1 ... done
==> provisioner: Creating vagrant_tls-gen_1 ... done
==> provisioner: Creating vagrant_registry-auth_1 ... done
==> provisioner: Creating vagrant_registry_1 ...
==> provisioner: Creating vagrant_registry_1 ... done
==> provisioner: Creating vagrant_tink-server-migration_1 ...
==> provisioner: Creating vagrant_tink-server-migration_1 ... done
==> provisioner: Creating vagrant_tink-server_1 ...
==> provisioner: Creating vagrant_images-to-local-registry_1 ...
==> provisioner: Creating vagrant_tink-server_1 ... done
==> provisioner: Creating vagrant_images-to-local-registry_1 ... done
==> provisioner: Creating vagrant_hegel_1 ...
==> provisioner: Creating vagrant_boots_1 ...
==> provisioner: Creating vagrant_create-tink-records_1 ...
==> provisioner: Creating vagrant_tink-cli_1 ...
==> provisioner: Creating vagrant_registry-ca-crt-download_1 ...
==> provisioner: Creating vagrant_boots_1 ... done
==> provisioner: Creating vagrant_tink-cli_1 ... done
==> provisioner: Creating vagrant_hegel_1 ... done
==> provisioner: Creating vagrant_create-tink-records_1 ... done
==> provisioner: Creating vagrant_registry-ca-crt-download_1 ... done
==> provisioner: Creating vagrant_osie-bootloader_1 ...
==> provisioner: Creating vagrant_osie-bootloader_1 ... done
```
</details>
3. Start the machine to be provisioned
```bash
vagrant up machine1
# This will start a VM to pxe boot.
```
<details>
<summary>expected output</summary>
```bash
Bringing machine 'machine1' up with 'libvirt' provider...
==> machine1: Creating domain with the following settings...
==> machine1: -- Name: vagrant_machine1
==> machine1: -- Domain type: kvm
==> machine1: -- Cpus: 2
==> machine1: -- Feature: acpi
==> machine1: -- Feature: apic
==> machine1: -- Feature: pae
==> machine1: -- Memory: 4096M
==> machine1: -- Management MAC:
==> machine1: -- Loader:
==> machine1: -- Nvram:
==> machine1: -- Storage pool: default
==> machine1: -- Image: (G)
==> machine1: -- Volume Cache: default
==> machine1: -- Kernel:
==> machine1: -- Initrd:
==> machine1: -- Graphics Type: vnc
==> machine1: -- Graphics Port: -1
==> machine1: -- Graphics IP: 0.0.0.0
==> machine1: -- Graphics Password: Not defined
==> machine1: -- Video Type: cirrus
==> machine1: -- Video VRAM: 9216
==> machine1: -- Sound Type:
==> machine1: -- Keymap: en-us
==> machine1: -- TPM Path:
==> machine1: -- Boot device: hd
==> machine1: -- Boot device: network
==> machine1: -- Disks: vdb(qcow2,20G)
==> machine1: -- Disk(vdb): /var/lib/libvirt/images/vagrant_machine1-vdb.qcow2 Not created - using existed.
==> machine1: -- INPUT: type=mouse, bus=ps2
==> machine1: Starting domain.
```
</details>
4. Watch the provision complete
```bash
# log in to the provisioner
vagrant ssh provisioner
# watch the workflow events and status for workflow completion
# once the workflow is complete (see the expected output below for completion), move on to the next step
wid=$(cat /vagrant/compose/manifests/workflow/workflow_id.txt); docker exec -it compose_tink-cli_1 watch "tink workflow events ${wid}; tink workflow state ${wid}"
```
<details>
<summary>expected output</summary>
```bash
+--------------------------------------+-----------------+---------------------+----------------+---------------------------------+---------------+
| WORKER ID | TASK NAME | ACTION NAME | EXECUTION TIME | MESSAGE | ACTION STATUS |
+--------------------------------------+-----------------+---------------------+----------------+---------------------------------+---------------+
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | stream-ubuntu-image | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | stream-ubuntu-image | 15 | finished execution successfully | STATE_SUCCESS |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | install-openssl | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | install-openssl | 1 | finished execution successfully | STATE_SUCCESS |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | create-user | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | create-user | 0 | finished execution successfully | STATE_SUCCESS |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | enable-ssh | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | enable-ssh | 0 | finished execution successfully | STATE_SUCCESS |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | disable-apparmor | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | disable-apparmor | 0 | finished execution successfully | STATE_SUCCESS |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | write-netplan | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | write-netplan | 0 | finished execution successfully | STATE_SUCCESS |
+--------------------------------------+-----------------+---------------------+----------------+---------------------------------+---------------+
+----------------------+--------------------------------------+
| FIELD NAME | VALUES |
+----------------------+--------------------------------------+
| Workflow ID | 3107919b-e59d-11eb-bf99-0242ac120005 |
| Workflow Progress | 100% |
| Current Task | os-installation |
| Current Action | write-netplan |
| Current Worker | 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 |
| Current Action State | STATE_SUCCESS |
+----------------------+--------------------------------------+
```
</details>
5. Reboot the machine
```bash
# crtl-c to exit the watch
# exit the provisioner
vagrant@ubuntu2004:~$ exit
# restart machine1
# the output will be the same as step 3, once the command line control is returned to you, you can move on to the next step.
vagrant reload machine1
```
6. Login to the machine
The machine has been provisioned with Ubuntu Focal.
You can now SSH into the machine.
```bash
vagrant ssh provisioner
ssh tink@192.168.50.43 # user/pass => tink/tink
```

View File

@ -0,0 +1,278 @@
# Quick start guide for Vagrant and VirtualBox
This option will stand up the provisioner in Virtualbox using Vagrant.
This option will also show you how to create a machine to provision.
## Prerequisites
- [Vagrant](https://www.vagrantup.com/downloads) is installed
- [VirtualBox](https://www.virtualbox.org/) is installed
## Steps
1. Clone this repository
```bash
git clone https://github.com/tinkerbell/sandbox.git
cd sandbox
```
2. Start the provisioner
```bash
cd deploy/vagrant
vagrant up
# This process will take about 5-10 minutes depending on your internet connection.
# OSIE is about 2GB in size and the Ubuntu Focal image is about 500MB
```
<details>
<summary>expected output</summary>
```bash
Bringing machine 'provisioner' up with 'virtualbox' provider...
==> provisioner: Importing base box 'generic/ubuntu2004'...
==> provisioner: Matching MAC address for NAT networking...
==> provisioner: Checking if box 'generic/ubuntu2004' version '3.2.24' is up to date...
==> provisioner: Setting the name of the VM: vagrant_provisioner_1626366679197_92753
==> provisioner: Clearing any previously set network interfaces...
==> provisioner: Preparing network interfaces based on configuration...
provisioner: Adapter 1: nat
provisioner: Adapter 2: hostonly
==> provisioner: Forwarding ports...
provisioner: 22 (guest) => 2222 (host) (adapter 1)
==> provisioner: Running 'pre-boot' VM customizations...
==> provisioner: Booting VM...
==> provisioner: Waiting for machine to boot. This may take a few minutes...
provisioner: SSH address: 127.0.0.1:2222
provisioner: SSH username: vagrant
provisioner: SSH auth method: private key
provisioner:
provisioner: Vagrant insecure key detected. Vagrant will automatically replace
provisioner: this with a newly generated keypair for better security.
provisioner:
provisioner: Inserting generated public key within guest...
provisioner: Removing insecure key from the guest if it's present...
provisioner: Key inserted! Disconnecting and reconnecting using new SSH key...
==> provisioner: Machine booted and ready!
==> provisioner: Checking for guest additions in VM...
==> provisioner: Configuring and enabling network interfaces...
==> provisioner: Mounting shared folders...
provisioner: /vagrant => /Users/jacobweinstock/tmp/sandbox/deploy
==> provisioner: Running provisioner: docker...
provisioner: Installing Docker onto machine...
==> provisioner: Running provisioner: docker_compose...
provisioner: Checking for Docker Compose installation...
provisioner: Getting machine and kernel name from guest machine...
provisioner: Downloading Docker Compose 1.29.1 for Linux x86_64
provisioner: Downloaded Docker Compose 1.29.1 has SHA256 signature 8097769d32e34314125847333593c8edb0dfc4a5b350e4839bef8c2fe8d09de7
provisioner: Uploading Docker Compose 1.29.1 to guest machine...
provisioner: Installing Docker Compose 1.29.1 in guest machine...
provisioner: Symlinking Docker Compose 1.29.1 in guest machine...
provisioner: Running docker-compose up...
==> provisioner: Creating network "vagrant_default" with the default driver
==> provisioner: Creating volume "vagrant_postgres_data" with default driver
==> provisioner: Creating volume "vagrant_certs" with default driver
==> provisioner: Creating volume "vagrant_auth" with default driver
==> provisioner: Pulling tls-gen (cfssl/cfssl:)...
provisioner: latest: Pulling from cfssl/cfssl
provisioner: Digest: sha256:c21e852f3904e2ba77960e9cba23c69d9231467795a8a160ce1d848e621381ea
provisioner: Status: Downloaded newer image for cfssl/cfssl:latest
==> provisioner: Pulling registry-auth (httpd:2)...
provisioner: 2: Pulling from library/httpd
provisioner: Digest: sha256:1fd07d599a519b594b756d2e4e43a72edf7e30542ce646f5eb3328cf3b12341a
provisioner: Status: Downloaded newer image for httpd:2
==> provisioner: Pulling osie-work (alpine:)...
provisioner: latest: Pulling from library/alpine
provisioner: Digest: sha256:234cb88d3020898631af0ccbbcca9a66ae7306ecd30c9720690858c1b007d2a0
provisioner: Status: Downloaded newer image for alpine:latest
==> provisioner: Pulling ubuntu-image-setup (ubuntu:)...
provisioner: latest: Pulling from library/ubuntu
provisioner: Digest: sha256:b3e2e47d016c08b3396b5ebe06ab0b711c34e7f37b98c9d37abe794b71cea0a2
provisioner: Status: Downloaded newer image for ubuntu:latest
==> provisioner: Pulling db (postgres:10-alpine)...
provisioner: 10-alpine: Pulling from library/postgres
provisioner: Digest: sha256:0eef1c94e0c4b0c4b84437785d0c5926f62b7f537627d97cf9ebcd7b205bc9aa
provisioner: Status: Downloaded newer image for postgres:10-alpine
==> provisioner: Pulling tink-server-migration (quay.io/tinkerbell/tink:sha-8ea8a0e5)...
provisioner: sha-8ea8a0e5: Pulling from tinkerbell/tink
provisioner: Digest: sha256:84fc83f8562901d0b27e7ebb453a7f27e5797d17fb0b6899f92002df840fbf21
provisioner: Status: Downloaded newer image for quay.io/tinkerbell/tink:sha-8ea8a0e5
==> provisioner: Pulling create-tink-records (quay.io/tinkerbell/tink-cli:sha-8ea8a0e5)...
provisioner: sha-8ea8a0e5: Pulling from tinkerbell/tink-cli
provisioner: Digest: sha256:0fc5441e9ef6e94eff7bf1ae9cf9a15a98581c742890d2d7130fd9542b12802d
provisioner: Status: Downloaded newer image for quay.io/tinkerbell/tink-cli:sha-8ea8a0e5
==> provisioner: Pulling registry (registry:2.7.1)...
provisioner: 2.7.1: Pulling from library/registry
provisioner: Digest: sha256:aba2bfe9f0cff1ac0618ec4a54bfefb2e685bbac67c8ebaf3b6405929b3e616f
provisioner: Status: Downloaded newer image for registry:2.7.1
==> provisioner: Pulling images-to-local-registry (quay.io/containers/skopeo:latest)...
provisioner: latest: Pulling from containers/skopeo
provisioner: Digest: sha256:f7bfc49ffc4331ce7ab6ff51b0883bc39115cd1028fe1606a6fc9d4351df3673
provisioner: Status: Downloaded newer image for quay.io/containers/skopeo:latest
==> provisioner: Pulling boots (quay.io/tinkerbell/boots:sha-cb0290f8)...
provisioner: sha-cb0290f8: Pulling from tinkerbell/boots
provisioner: Digest: sha256:8e106bf73122d08ce9ef75f5cae4be77ecff38c2b55cb44541caabf94d325de9
provisioner: Status: Downloaded newer image for quay.io/tinkerbell/boots:sha-cb0290f8
==> provisioner: Pulling osie-bootloader (nginx:alpine)...
provisioner: alpine: Pulling from library/nginx
provisioner: Digest: sha256:91528597e842ab1b3b25567191fa7d4e211cb3cc332071fa031cfed2b5892f9e
provisioner: Status: Downloaded newer image for nginx:alpine
==> provisioner: Pulling hegel (quay.io/tinkerbell/hegel:sha-9f5da0a8)...
provisioner: sha-9f5da0a8: Pulling from tinkerbell/hegel
provisioner: Digest: sha256:9d3c6d5e4bc957cedafbeec22da4f59d94c78b65d84adbd0c8f947c51cf3668b
provisioner: Status: Downloaded newer image for quay.io/tinkerbell/hegel:sha-9f5da0a8
==> provisioner: Creating vagrant_db_1 ...
==> provisioner: Creating vagrant_osie-bootloader_1 ...
==> provisioner: Creating vagrant_ubuntu-image-setup_1 ...
==> provisioner: Creating vagrant_tls-gen_1 ...
==> provisioner: Creating vagrant_registry-auth_1 ...
==> provisioner: Creating vagrant_osie-work_1 ...
==> provisioner: Creating vagrant_tls-gen_1 ... done
==> provisioner: Creating vagrant_ubuntu-image-setup_1 ... done
==> provisioner: Creating vagrant_osie-bootloader_1 ... done
==> provisioner: Creating vagrant_registry-auth_1 ... done
==> provisioner: Creating vagrant_db_1 ... done
==> provisioner: Creating vagrant_osie-work_1 ... done
==> provisioner: Creating vagrant_registry_1 ...
==> provisioner: Creating vagrant_registry_1 ... done
==> provisioner: Creating vagrant_tink-server-migration_1 ...
==> provisioner: Creating vagrant_tink-server-migration_1 ... done
==> provisioner: Creating vagrant_tink-server_1 ...
==> provisioner: Creating vagrant_tink-server_1 ... done
==> provisioner: Creating vagrant_images-to-local-registry_1 ...
==> provisioner: Creating vagrant_images-to-local-registry_1 ... done
==> provisioner: Creating vagrant_registry-ca-crt-download_1 ...
==> provisioner: Creating vagrant_create-tink-records_1 ...
==> provisioner: Creating vagrant_boots_1 ...
==> provisioner: Creating vagrant_tink-cli_1 ...
==> provisioner: Creating vagrant_hegel_1 ...
==> provisioner: Creating vagrant_boots_1 ... done
==> provisioner: Creating vagrant_create-tink-records_1 ... done
==> provisioner: Creating vagrant_tink-cli_1 ... done
==> provisioner: Creating vagrant_registry-ca-crt-download_1 ... done
==> provisioner: Creating vagrant_hegel_1 ... done
==> provisioner: Creating vagrant_wait-for-osie-and-ubuntu-downloads_1 ...
==> provisioner: Creating vagrant_wait-for-osie-and-ubuntu-downloads_1 ... done
```
</details>
3. Start the machine to be provisioned
```bash
vagrant up machine1
# This will start a VM to pxe boot. A GUI window of this machines console will be opened.
# The `vagrant up machine1` command will exit quickly and show the following error message. This is expected.
# Once the command line control is returned to you, you can move on to the next step.
```
<details>
<summary>expected output</summary>
```bash
Bringing machine 'machine1' up with 'virtualbox' provider...
==> machine1: Importing base box 'jtyr/pxe'...
==> machine1: Matching MAC address for NAT networking...
==> machine1: Checking if box 'jtyr/pxe' version '2' is up to date...
==> machine1: Setting the name of the VM: vagrant_machine1_1626365105119_9800
==> machine1: Fixed port collision for 22 => 2222. Now on port 2200.
==> machine1: Clearing any previously set network interfaces...
==> machine1: Preparing network interfaces based on configuration...
machine1: Adapter 1: hostonly
==> machine1: Forwarding ports...
machine1: 22 (guest) => 2200 (host) (adapter 1)
machine1: VirtualBox adapter #1 not configured as "NAT". Skipping port
machine1: forwards on this adapter.
==> machine1: Running 'pre-boot' VM customizations...
==> machine1: Booting VM...
==> machine1: Waiting for machine to boot. This may take a few minutes...
machine1: SSH address: 127.0.0.1:22
machine1: SSH username: vagrant
machine1: SSH auth method: private key
machine1: Warning: Authentication failure. Retrying...
Timed out while waiting for the machine to boot. This means that
Vagrant was unable to communicate with the guest machine within
the configured ("config.vm.boot_timeout" value) time period.
If you look above, you should be able to see the error(s) that
Vagrant had when attempting to connect to the machine. These errors
are usually good hints as to what may be wrong.
If you're using a custom box, make sure that networking is properly
working and you're able to connect to the machine. It is a common
problem that networking isn't setup properly in these boxes.
Verify that authentication configurations are also setup properly,
as well.
If the box appears to be booting properly, you may want to increase
the timeout ("config.vm.boot_timeout") value.
```
</details>
4. Watch the provision complete
```bash
# log in to the provisioner
vagrant ssh provisioner
# watch the workflow events and status for workflow completion
# once the workflow is complete (see the expected output below for completion), move on to the next step
wid=$(cat /vagrant/compose/manifests/workflow/workflow_id.txt); docker exec -it compose_tink-cli_1 watch "tink workflow events ${wid}; tink workflow state ${wid}"
```
<details>
<summary>expected output</summary>
```bash
+--------------------------------------+-----------------+---------------------+----------------+---------------------------------+---------------+
| WORKER ID | TASK NAME | ACTION NAME | EXECUTION TIME | MESSAGE | ACTION STATUS |
+--------------------------------------+-----------------+---------------------+----------------+---------------------------------+---------------+
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | stream-ubuntu-image | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | stream-ubuntu-image | 15 | finished execution successfully | STATE_SUCCESS |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | install-openssl | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | install-openssl | 1 | finished execution successfully | STATE_SUCCESS |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | create-user | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | create-user | 0 | finished execution successfully | STATE_SUCCESS |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | enable-ssh | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | enable-ssh | 0 | finished execution successfully | STATE_SUCCESS |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | disable-apparmor | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | disable-apparmor | 0 | finished execution successfully | STATE_SUCCESS |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | write-netplan | 0 | Started execution | STATE_RUNNING |
| 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 | os-installation | write-netplan | 0 | finished execution successfully | STATE_SUCCESS |
+--------------------------------------+-----------------+---------------------+----------------+---------------------------------+---------------+
+----------------------+--------------------------------------+
| FIELD NAME | VALUES |
+----------------------+--------------------------------------+
| Workflow ID | 3107919b-e59d-11eb-bf99-0242ac120005 |
| Workflow Progress | 100% |
| Current Task | os-installation |
| Current Action | write-netplan |
| Current Worker | 0eba0bf8-3772-4b4a-ab9f-6ebe93b90a94 |
| Current Action State | STATE_SUCCESS |
+----------------------+--------------------------------------+
```
</details>
5. Reboot the machine
```bash
# crtl-c to exit the watch
# exit the provisioner
vagrant@ubuntu2004:~$ exit
# restart machine1
# the output will be the same as step 3, once the command line control is returned to you, you can move on to the next step.
vagrant reload machine1
```
6. Login to the machine
The machine has been provisioned with Ubuntu Focal.
You can now SSH into the machine.
```bash
vagrant ssh provisioner
ssh tink@192.168.50.43 # user/pass => tink/tink
```

View File

@ -0,0 +1,42 @@
#cloud-config
package_update: true
package_reboot_if_required: true
apt:
sources:
docker.list:
source: deb [arch=amd64] https://download.docker.com/linux/ubuntu $RELEASE stable
keyid: 9DC858229FC7DD38854AE2D88D81803C0EBFCD88
packages:
- make
- apt-transport-https
- ca-certificates
- curl
- gnupg-agent
- gnupg2
- software-properties-common
- docker-ce
- docker-ce-cli
- containerd.io
write_files:
- path: /etc/netplan/60-cloud-init.yaml
content: |
network:
version: 2
renderer: networkd
ethernets:
enp0s8:
dhcp4: no
addresses:
- 192.168.2.111/24
nameservers:
addresses: [1.1.1.1, 8.8.8.8]
runcmd:
- usermod -aG docker ubuntu
- curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
- chmod +x /usr/local/bin/docker-compose
- netplan apply

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -1,110 +0,0 @@
#!/usr/bin/env bash
# stops the execution if a command or pipeline has an error
set -eu
if command -v tput >/dev/null && tput setaf 1 >/dev/null 2>&1; then
# color codes
RED="$(tput setaf 1)"
RESET="$(tput sgr0)"
fi
ERR="${RED:-}ERROR:${RESET:-}"
source ./current_versions.sh
err() (
if [[ -z ${1:-} ]]; then
cat >&2
else
echo "$ERR " "$@" >&2
fi
)
candidate_interfaces() (
ip -o link show |
awk -F': ' '{print $2}' |
sed 's/[ \t].*//;/^\(lo\|bond0\|\|\)$/d' |
sort
)
validate_tinkerbell_network_interface() (
local tink_interface=$1
if ! candidate_interfaces | grep -q "^$tink_interface$"; then
err "Invalid interface ($tink_interface) selected, must be one of:"
candidate_interfaces | err
return 1
else
return 0
fi
)
generate_password() (
head -c 12 /dev/urandom | sha256sum | cut -d' ' -f1
)
generate_env() (
local tink_interface=$1
validate_tinkerbell_network_interface "$tink_interface"
local tink_password
tink_password=$(generate_password)
local registry_password
registry_password=$(generate_password)
cat <<-EOF
# Tinkerbell Stack version
export OSIE_DOWNLOAD_LINK=${OSIE_DOWNLOAD_LINK}
export TINKERBELL_TINK_SERVER_IMAGE=${TINKERBELL_TINK_SERVER_IMAGE}
export TINKERBELL_TINK_CLI_IMAGE=${TINKERBELL_TINK_CLI_IMAGE}
export TINKERBELL_TINK_BOOTS_IMAGE=${TINKERBELL_TINK_BOOTS_IMAGE}
export TINKERBELL_TINK_HEGEL_IMAGE=${TINKERBELL_TINK_HEGEL_IMAGE}
export TINKERBELL_TINK_WORKER_IMAGE=${TINKERBELL_TINK_WORKER_IMAGE}
# Network interface for Tinkerbell's network
export TINKERBELL_NETWORK_INTERFACE="$tink_interface"
# Decide on a subnet for provisioning. Tinkerbell should "own" this
# network space. Its subnet should be just large enough to be able
# to provision your hardware.
export TINKERBELL_CIDR=${TINKERBELL_CIDR:-"29"}
# Host IP is used by provisioner to expose different services such as
# tink, boots, etc.
#
# The host IP should the first IP in the range, and the Nginx IP
# should be the second address.
export TINKERBELL_HOST_IP=${TINKERBELL_HOST_IP:-"192.168.1.1"}
# Tink server username and password
export TINKERBELL_TINK_USERNAME=admin
export TINKERBELL_TINK_PASSWORD="$tink_password"
# Docker Registry's username and password
export TINKERBELL_REGISTRY_USERNAME=admin
export TINKERBELL_REGISTRY_PASSWORD="$registry_password"
# Tink cli options
export TINKERBELL_GRPC_AUTHORITY=${TINKERBELL_HOST_IP:-"192.168.1.1"}:42113
export TINKERBELL_CERT_URL=http://${TINKERBELL_HOST_IP:-"192.168.1.1"}:42114/cert
# Legacy options, to be deleted:
export FACILITY=onprem
export ROLLBAR_TOKEN=ignored
export ROLLBAR_DISABLE=1
EOF
)
main() (
if [[ -z ${1:-} ]]; then
err "Usage: $0 network-interface-name > .env"
exit 1
fi
generate_env "$1"
)
main "$@"

31
notes.md Normal file
View File

@ -0,0 +1,31 @@
# TODO
- [x] automate getting osie download and decompressed/extracted
- create directories (`state/webroot/workflow` and `state/webroot/misc/osie/current`)
- automate moving files around (workflow-helper scripts)
- [x] automate getting tink-worker uploaded to internal registry
- on the provisioner machine need to enable pushing to [local registry](https://docs.docker.com/registry/insecure/), using one of the following:
1. ~~enable insecure registry in `/etc/docker/daemon.json`~~
2. ~~add crt to `/etc/docker/certs.d/192.168.50.4/ca.crt` && `sudo update-ca-certificates`~~
3. use `skopeo` to copy images to the local registry
- [x] automate ca.pem (bundle.pem) making it to `state/webroot/workflow/ca.pem` (used for docker registry)
- [x] automate hardware, template, and workflow creation
- [x] update Vagrantfile with a machine to provision (vagrant up machine1)
- [x] wait for osie and ubuntu download and/or notify user that it's ready
- [x] after `vagrant up machine1` notify user how to show progress `tink workflow events`
- [x] after machine1 is complete notify user how login to the machine
- [ ] reboot action for machine1
- [x] build idempotency in for downloads and extractions
- [x] add idempotency to cert generation (`tls/generate.sh`)
- [x] download focal cloud img and convert to raw and place it in correct location (`state/webroot/focal.img`)
- [x] make virtualbox networking more stable
- [x] create a getting started document that will replace the existing on on tinkerbell.org
- [ ] create a contributor guide to explain how the new sandbox works
- [ ] machine1 default creds: tink/tink
- [x] document on how to run docker-compose on its own `TINKERBELL_HOST_IP=192.168.65.3 TINKERBELL_CLIENT_IP=192.168.65.43 docker-compose up -d` or update `.env` file
- [x] test in multipass - works great!
- [x] document prerequisites
- [ ] docker-compose >= 1.29.2
- [ ] storage > ?
- [x] make the "TINKERBELL_IP" configurable. `csr.json`, `ubuntu.json`
- [x] make client machine ip configurable. `hardware.json`

59
releases/README.md Normal file
View File

@ -0,0 +1,59 @@
This repository is a quick way to get the Tinkerbell stack up and running.
Currently it supports:
1. Vagrant with libvirt and VirtualBox
2. Terraform on Packet
Tinkerbell is made of different components: osie, boots, tink-server,
tink-worker and so on. Currently they are under heavy development and we are
working around the release process for all the components.
We need a way to serve a version of Tinkerbell that you can use and we know what
is running the hood. Sandbox runs a pinned version for all the components via
commit sha. In this way as a user you won't be effected (ideally) from new code
that will may change a bit how Tinkerbell works.
We are keeping the number of breaking changes as low as possible but in the current
state they are expected.
## Binary release
As part of a new release for sandbox we want to push binaries to GitHub Release
in this way the community will be able to use them if needed.
We build Docker images across many architectures, each of them in its own
repository: boots, hegel, tink and so on.
Sandbox is just a collection of those services and we follow the same pattern
for getting binaries as well.
There is a go program available in `./cmd/getbinariesfromquay/main.go`. You can
run it with `go run` or build it with `go build`:
```terminal
$ go run cmd/getbinariesfromquay/main.go -h
-binary-to-copy string
The location of the binary you want to copy from inside the image. (default "/usr/bin/hegel")
-image string
The image you want to download binaries from. It has to be a multi stage image. (default "docker://quay.io/tinkerbell/hegel")
-out string
The directory that will be used to store the release binaries (default "./out")
-program string
The name of the program you are extracing binaries for. (eg tink-worker, hegel, tink-server, tink, boots) (default "hegel")
```
By default it uses the image running on Quay for Hegel and it gets the binary
`/usr/bin/hegel` from there. The directory `./out` is used to store images and
binaries inside `./out/releases`.
To get the binaries for example for boots you can run:
```terminal
$ go run cmd/getbinariesfromquay/main.go \
-binary-to-copy /usr/bin/boots \
-image docker://quay.io/tinkerbell/boots:sha-9625559b \
-program boots
```
You will find them in `./out/release`

View File

@ -1,4 +1,5 @@
#!/usr/bin/env bash
# shellcheck disable=SC1091,SC2086
source ./current_versions.sh

515
setup.sh
View File

@ -1,515 +0,0 @@
#!/usr/bin/env bash
# stops the execution if a command or pipeline has an error
set -euxo pipefail
# Tinkerbell stack Linux setup script
#
# See https://tinkerbell.org/setup for the installation steps.
# file to hold all environment variables
ENV_FILE=.env
SCRATCH=$(mktemp -d -t tmp.XXXXXXXXXX)
readonly SCRATCH
function finish() (
rm -rf "$SCRATCH"
)
trap finish EXIT
DEPLOYDIR=$(pwd)/deploy
readonly DEPLOYDIR
readonly STATEDIR=$DEPLOYDIR/state
if command -v tput >/dev/null && tput setaf 1 >/dev/null 2>&1; then
# color codes
RED="$(tput setaf 1)"
GREEN="$(tput setaf 2)"
YELLOW="$(tput setaf 3)"
RESET="$(tput sgr0)"
fi
INFO="${GREEN:-}INFO:${RESET:-}"
ERR="${RED:-}ERROR:${RESET:-}"
WARN="${YELLOW:-}WARNING:${RESET:-}"
BLANK=" "
NEXT="${GREEN:-}NEXT:${RESET:-}"
get_distribution() (
local lsb_dist=""
# Every system that we officially support has /etc/os-release
if [[ -r /etc/os-release ]]; then
# shellcheck disable=SC1091
lsb_dist="$(. /etc/os-release && echo "$ID")"
fi
# Returning an empty string here should be alright since the
# case statements don't act unless you provide an actual value
echo "$lsb_dist" | tr '[:upper:]' '[:lower:]'
)
get_distro_version() (
local lsb_version="0"
# Every system that we officially support has /etc/os-release
if [[ -r /etc/os-release ]]; then
# shellcheck disable=SC1091
lsb_version="$(. /etc/os-release && echo "$VERSION_ID")"
fi
echo "$lsb_version"
)
is_network_configured() (
# Require the provisioner interface have the host IP
if ! ip addr show "$TINKERBELL_NETWORK_INTERFACE" |
grep -q "$TINKERBELL_HOST_IP"; then
return 1
fi
return 0
)
identify_network_strategy() (
local distro=$1
local version=$2
case "$distro" in
ubuntu)
if jq -n --exit-status '$distro_version >= 17.10' --argjson distro_version "$version" >/dev/null 2>&1; then
echo "setup_networking_netplan"
else
echo "setup_networking_ubuntu_legacy"
fi
;;
centos)
echo "setup_networking_centos"
;;
*)
echo "setup_networking_manually"
;;
esac
)
setup_networking() (
local distro=$1
local version=$2
setup_network_forwarding
if is_network_configured; then
echo "$INFO tinkerbell network interface is already configured"
return 0
fi
local strategy
strategy=$(identify_network_strategy "$distro" "$version")
"${strategy}" "$distro" "$version" # execute the strategy
if is_network_configured; then
echo "$INFO tinkerbell network interface configured successfully"
else
echo "$ERR tinkerbell network interface configuration failed"
fi
NAT_INTERFACE=""
if [[ -r .nat_interface ]]; then
NAT_INTERFACE=$(cat .nat_interface)
fi
if [[ -n $NAT_INTERFACE ]] && ip addr show "$NAT_INTERFACE" &>/dev/null; then
# TODO(nshalman) the terraform code would just run these commands as-is once
# but it would be nice to make these more persistent based on OS
iptables -A FORWARD -i "$TINKERBELL_NETWORK_INTERFACE" -o "$NAT_INTERFACE" -j ACCEPT
iptables -A FORWARD -i "$NAT_INTERFACE" -o "$TINKERBELL_NETWORK_INTERFACE" -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE
fi
)
setup_networking_manually() (
local distro=$1
local version=$2
echo "$ERR this setup script cannot configure $distro ($version)"
echo "$BLANK please read this script's source and configure it manually."
exit 1
)
setup_network_forwarding() (
# enable IP forwarding for docker
if (($(sysctl -n net.ipv4.ip_forward) != 1)); then
if [[ -d /etc/sysctl.d ]]; then
echo "net.ipv4.ip_forward=1" >/etc/sysctl.d/99-tinkerbell.conf
elif [[ -f /etc/sysctl.conf ]]; then
echo "net.ipv4.ip_forward=1" >>/etc/sysctl.conf
fi
sysctl net.ipv4.ip_forward=1
fi
)
setup_networking_netplan() (
jq -n \
--arg interface "$TINKERBELL_NETWORK_INTERFACE" \
--arg cidr "$TINKERBELL_CIDR" \
--arg host_ip "$TINKERBELL_HOST_IP" \
'{
network: {
renderer: "networkd",
ethernets: {
($interface): {
addresses: [
"\($host_ip)/\($cidr)"
]
}
}
}
}' >"/etc/netplan/${TINKERBELL_NETWORK_INTERFACE}.yaml"
ip link set "$TINKERBELL_NETWORK_INTERFACE" nomaster
netplan apply
echo "$INFO waiting for the network configuration to be applied by systemd-networkd"
sleep 3
)
setup_networking_ubuntu_legacy() (
if ! [[ -f /etc/network/interfaces ]]; then
echo "$ERR file /etc/network/interfaces not found"
exit 1
fi
if grep -q "$TINKERBELL_NETWORK_INTERFACE" /etc/network/interfaces; then
echo "$ERR /etc/network/interfaces already has an entry for $TINKERBELL_NETWORK_INTERFACE."
echo "$BLANK To prevent breaking your network, please edit /etc/network/interfaces"
echo "$BLANK and configure $TINKERBELL_NETWORK_INTERFACE as follows:"
generate_iface_config
echo ""
echo "$BLANK Then run the following commands:"
echo "$BLANK ip link set $TINKERBELL_NETWORK_INTERFACE nomaster"
echo "$BLANK ifdown $TINKERBELL_NETWORK_INTERFACE"
echo "$BLANK ifup $TINKERBELL_NETWORK_INTERFACE"
exit 1
else
generate_iface_config >>/etc/network/interfaces
ip link set "$TINKERBELL_NETWORK_INTERFACE" nomaster
ifdown "$TINKERBELL_NETWORK_INTERFACE"
ifup "$TINKERBELL_NETWORK_INTERFACE"
fi
)
generate_iface_config() (
cat <<EOF
auto $TINKERBELL_NETWORK_INTERFACE
iface $TINKERBELL_NETWORK_INTERFACE inet static
address $TINKERBELL_HOST_IP/$TINKERBELL_CIDR
pre-up sleep 4
EOF
)
setup_networking_centos() (
local HWADDRESS
local content
HWADDRESS=$(ip addr show "$TINKERBELL_NETWORK_INTERFACE" | grep ether | awk -F 'ether' '{print $2}' | cut -d" " -f2)
content=$(
cat <<EOF
DEVICE=$TINKERBELL_NETWORK_INTERFACE
ONBOOT=yes
HWADDR=$HWADDRESS
BOOTPROTO=static
IPADDR=$TINKERBELL_HOST_IP
PREFIX=$TINKERBELL_CIDR
EOF
)
local cfgfile="/etc/sysconfig/network-scripts/ifcfg-$TINKERBELL_NETWORK_INTERFACE"
if [[ -f $cfgfile ]]; then
echo "$ERR network config already exists: $cfgfile"
echo "$BLANK Please update it to match this configuration:"
echo "$content"
echo ""
echo "$BLANK Then, run the following commands:"
echo "ip link set $TINKERBELL_NETWORK_INTERFACE nomaster"
echo "ifup $TINKERBELL_NETWORK_INTERFACE"
fi
echo "$content" >"$cfgfile"
ip link set "$TINKERBELL_NETWORK_INTERFACE" nomaster
ifup "$TINKERBELL_NETWORK_INTERFACE"
)
setup_osie() (
mkdir -p "$STATEDIR/webroot"
local osie_current=$STATEDIR/webroot/misc/osie/current
local tink_workflow=$STATEDIR/webroot/workflow/
if [[ ! -d $osie_current ]] || [[ ! -d $tink_workflow ]]; then
mkdir -p "$osie_current"
mkdir -p "$tink_workflow"
pushd "$SCRATCH"
if [[ -z ${TB_OSIE_TAR:-} ]]; then
curl "${OSIE_DOWNLOAD_LINK}" -o ./osie.tar.gz
tar -zxf osie.tar.gz
else
tar -zxf "$TB_OSIE_TAR"
fi
if pushd osie*/; then
if mv workflow-helper.sh workflow-helper-rc "$tink_workflow"; then
cp -r ./* "$osie_current"
else
echo "$ERR failed to move 'workflow-helper.sh' and 'workflow-helper-rc'"
exit 1
fi
popd
fi
else
echo "$INFO found existing osie files, skipping osie setup"
fi
)
check_container_status() (
local container_name="$1"
local container_id
container_id=$(docker-compose -f "$DEPLOYDIR/docker-compose.yml" ps -q "$container_name")
local start_moment
local current_status
start_moment=$(docker inspect "${container_id}" --format '{{ .State.StartedAt }}')
current_status=$(docker inspect "${container_id}" --format '{{ .State.Health.Status }}')
case "$current_status" in
starting)
: # move on to the events check
;;
healthy)
return 0
;;
unhealthy)
echo "$ERR $container_name is already running but not healthy. status: $current_status"
exit 1
;;
*)
echo "$ERR $container_name is already running but its state is a mystery. status: $current_status"
exit 1
;;
esac
local status
read -r status < <(docker events \
--since "$start_moment" \
--filter "container=$container_id" \
--filter "event=health_status" \
--format '{{.Status}}')
if [[ $status != "health_status: healthy" ]]; then
echo "$ERR $container_name is not healthy. status: $status"
exit 1
fi
)
generate_certificates() (
mkdir -p "$STATEDIR/certs"
if ! [[ -f "$STATEDIR/certs/ca.json" ]]; then
jq \
'.
| .names[0].L = $facility
' \
"$DEPLOYDIR/tls/ca.in.json" \
--arg ip "$TINKERBELL_HOST_IP" \
--arg facility "$FACILITY" \
>"$STATEDIR/certs/ca.json"
fi
if ! [[ -f "$STATEDIR/certs/server-csr.json" ]]; then
jq \
'.
| .hosts += [ $ip, "tinkerbell.\($facility).packet.net" ]
| .names[0].L = $facility
| .hosts = (.hosts | sort | unique)
' \
"$DEPLOYDIR/tls/server-csr.in.json" \
--arg ip "$TINKERBELL_HOST_IP" \
--arg facility "$FACILITY" \
>"$STATEDIR/certs/server-csr.json"
fi
docker build --tag "tinkerbell-certs" "$DEPLOYDIR/tls"
docker run --rm \
--volume "$STATEDIR/certs:/certs" \
--user "$UID:$(id -g)" \
tinkerbell-certs
local certs_dir="/etc/docker/certs.d/$TINKERBELL_HOST_IP"
# copy public key to NGINX for workers
if ! cmp --quiet "$STATEDIR/certs/ca.pem" "$STATEDIR/webroot/workflow/ca.pem"; then
cp "$STATEDIR/certs/ca.pem" "$STATEDIR/webroot/workflow/ca.pem"
fi
# update host to trust registry certificate
if ! cmp --quiet "$STATEDIR/certs/ca.pem" "$certs_dir/tinkerbell.crt"; then
if ! [[ -d "$certs_dir/" ]]; then
# The user will be told to create the directory
# in the next block, if copying the certs there
# fails.
mkdir -p "$certs_dir" || true >/dev/null 2>&1
fi
if ! cp "$STATEDIR/certs/ca.pem" "$certs_dir/tinkerbell.crt"; then
echo "$ERR please copy $STATEDIR/certs/ca.pem to $certs_dir/tinkerbell.crt"
echo "$BLANK and run $0 again:"
if ! [[ -d $certs_dir ]]; then
echo "sudo mkdir -p '$certs_dir'"
fi
echo "sudo cp '$STATEDIR/certs/ca.pem' '$certs_dir/tinkerbell.crt'"
exit 1
fi
fi
)
docker_login() (
echo -n "$TINKERBELL_REGISTRY_PASSWORD" | docker login -u="$TINKERBELL_REGISTRY_USERNAME" --password-stdin "$TINKERBELL_HOST_IP"
)
# This function takes an image specified as first parameter and it tags and
# push it using the second one. useful to proxy images from a repository to
# another.
docker_mirror_image() (
local from=$1
local to=$2
docker pull "$from"
docker tag "$from" "$to"
docker push "$to"
)
start_registry() (
docker-compose -f "$DEPLOYDIR/docker-compose.yml" up --build -d registry
check_container_status "registry"
)
# This function supposes that the registry is up and running.
# It configures with the required dependencies.
bootstrap_docker_registry() (
docker_login
# osie looks for tink-worker:latest, so we have to play with it a bit
# https://github.com/tinkerbell/osie/blob/master/apps/workflow-helper.sh#L66
docker_mirror_image "${TINKERBELL_TINK_WORKER_IMAGE}" "${TINKERBELL_HOST_IP}/tink-worker:latest"
)
setup_docker_registry() (
local registry_images="$STATEDIR/registry"
if ! [[ -d $registry_images ]]; then
mkdir -p "$registry_images"
fi
start_registry
bootstrap_docker_registry
)
start_components() (
local components=(db hegel tink-server boots tink-cli nginx)
for comp in "${components[@]}"; do
docker-compose -f "$DEPLOYDIR/docker-compose.yml" up --build -d "$comp"
sleep 3
check_container_status "$comp"
done
)
command_exists() (
command -v "$@" >/dev/null 2>&1
)
check_command() (
if ! command_exists "$1"; then
echo "$ERR Prerequisite executable command not found: $1"
return 1
fi
if ! [[ -s "$(which "$1")" ]]; then
echo "$ERR Prerequisite command is an empty file: $1"
fi
echo "$BLANK Found prerequisite: $1"
return 0
)
check_prerequisites() (
distro=$1
version=$2
echo "$INFO verifying prerequisites for $distro ($version)"
failed=0
check_command docker || failed=1
check_command docker-compose || failed=1
check_command ip || failed=1
check_command jq || failed=1
strategy=$(identify_network_strategy "$distro" "$version")
case "$strategy" in
"setup_networking_netplan")
check_command netplan || failed=1
;;
"setup_networking_ubuntu_legacy")
check_command ifdown || failed=1
check_command ifup || failed=1
;;
"setup_networking_centos")
check_command ifdown || failed=1
check_command ifup || failed=1
;;
"setup_networking_manually")
echo "$WARN this script cannot automatically configure your network."
;;
*)
echo "$ERR bug: unhandled network strategy: $strategy"
exit 1
;;
esac
if ((failed == 1)); then
echo "$ERR Prerequisites not met. Please install the missing commands and re-run $0."
exit 1
fi
)
whats_next() (
echo "$NEXT 1. Enter /deploy and run: source ../.env; docker-compose up -d"
echo "$BLANK 2. Try executing your first workflow."
echo "$BLANK Follow the steps described in https://tinkerbell.org/examples/hello-world/ to say 'Hello World!' with a workflow."
)
do_setup() (
# perform some very rudimentary platform detection
lsb_dist=$(get_distribution)
lsb_version=$(get_distro_version)
echo "$INFO starting tinkerbell stack setup"
check_prerequisites "$lsb_dist" "$lsb_version"
if ! [[ -f $ENV_FILE ]]; then
echo "$ERR Run './generate-env.sh network-interface > \"$ENV_FILE\"' before continuing."
exit 1
fi
# shellcheck disable=SC1090
source "$ENV_FILE"
if [[ -z $TINKERBELL_SKIP_NETWORKING ]]; then
setup_networking "$lsb_dist" "$lsb_version"
fi
setup_osie
generate_certificates
setup_docker_registry
echo "$INFO tinkerbell stack setup completed successfully on $lsb_dist server"
whats_next | tee /tmp/post-setup-message
)
# wrapped up in a function so that we have some protection against only getting
# half the file during "curl | sh"
do_setup

8
test/vagrant/go.mod Normal file
View File

@ -0,0 +1,8 @@
module vagrant_test
go 1.16
require (
github.com/gianarb/vagrant-go v0.0.0-20200902133321-62ba563fe383
github.com/tinkerbell/tink v0.0.0-20210705055947-8ea8a0e511be
)

675
test/vagrant/go.sum Normal file
View File

@ -0,0 +1,675 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
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.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
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/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
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/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
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/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/briandowns/spinner v1.8.0/go.mod h1://Zf9tMcxfRUA36V23M6YGEAv+kECGfvpnLTnb8n4XQ=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
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/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.0.0-20191001013358-cfbb681360f0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v17.12.0-ce-rc1.0.20200916142827-bd33bbf0497b+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
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/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/fatih/color v1.8.0/go.mod h1:3l45GVGkyrnYNl9HoIjnp2NnNWvh6hLAqD8yTfGjnw8=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gianarb/vagrant-go v0.0.0-20200902133321-62ba563fe383 h1:cy+lc/KmNnrmcyiAYqc8rIsBFK2tK5/H1Kg1CN4C8Vs=
github.com/gianarb/vagrant-go v0.0.0-20200902133321-62ba563fe383/go.mod h1:CeXdKywZ6zpJTvtfljhOUg4pxsCnlMY4AE540C70+C4=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
github.com/gobuffalo/envy v1.7.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w=
github.com/gobuffalo/logger v1.0.1/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs=
github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q=
github.com/gobuffalo/packr/v2 v2.7.1/go.mod h1:qYEvAazPaVxy7Y7KR0W8qYEE+RymX74kETFqjFoFlOc=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/godror/godror v0.13.3/go.mod h1:2ouUT4kdhUBk7TAkHWD4SN0CdI0pgEQbo8FVHhbSKWg=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/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=
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=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/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=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
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.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/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/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.15.2 h1:HC+hWRWf+v5zTMPyoaYTKIJih+4sd4XRWmj0qlG87Co=
github.com/grpc-ecosystem/grpc-gateway v1.15.2/go.mod h1:vO11I9oWA+KsxmfFQPhLnnIb1VDE24M+pdxZFiuZcA8=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/consul/sdk v0.3.0/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-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
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/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/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.1-0.20191011153232-f91d3411e481/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-oci8 v0.0.7/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.5/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.12.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
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-homedir v1.1.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/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/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/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/packethost/pkg v0.0.0-20200903155310-0433e0605550/go.mod h1:GSv7cTtIjns4yc0pyajaM1RE/KE4djJONoblFIRDrxA=
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
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-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
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_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.4.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rollbar/rollbar-go v1.0.2/go.mod h1:AcFs5f0I+c71bpHlXNNDbOWJiKwjFDtISeXco0L5PKQ=
github.com/rubenv/sql-migrate v0.0.0-20200616145509-8d140a17f351/go.mod h1:DCgfY80j8GYL7MLEfvcpSFvjD0L5yZq/aZUJmhZklyg=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
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/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.0.1-0.20200713175500-884edc58ad08/go.mod h1:yk5b0mALVusDL5fMM6Rd1wgnoO5jUPhwsQ6LQAJTidQ=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
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.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
github.com/stormcat24/protodep v0.0.0-20200505140716-b02c9ba62816/go.mod h1:mBd5PI4uI6NkqJpCyiWiYzWyTFs4QRDss/JTMC2b4kc=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
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/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/testcontainers/testcontainers-go v0.9.0/go.mod h1:b22BFXhRbg4PJmeMVWh6ftqjyZHgiIl3w274e9r3C2E=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tinkerbell/tink v0.0.0-20210705055947-8ea8a0e511be h1:OFLz/0N8t7xUtcDXqXn6+DR2EpsJdrKlFb6EsJ/rMPo=
github.com/tinkerbell/tink v0.0.0-20210705055947-8ea8a0e511be/go.mod h1:s4k7CORR0OMWd4cYwBqNBFPSJZhnSQxeKdDtMa/aspk=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
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=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/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-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/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-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
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=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
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=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/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=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
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-20180906233101-161cd47e91fd/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-20181114220301-adae6a3d119a/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-20181220203305-927f97764cc3/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-20190125091013-d26f9f9a57f3/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=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
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=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
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=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180202135801-37707fdb30a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
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-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/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-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/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=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 h1:myAQVi0cGEoqQVR5POX+8RR2mrocKqNN1hmeMqhX27k=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
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=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
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-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180810170437-e96c4e24768d/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/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=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
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-20191004055002-72853e10c5a3/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-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/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-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
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.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
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=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
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=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
google.golang.org/genproto v0.0.0-20190708153700-3bdd9d9f5532/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20201026171402-d4b8fe4fd877 h1:d4k3uIU763E31Rk4UZPA47oOoBymMsDImV3U4mGhX9E=
google.golang.org/genproto v0.0.0-20201026171402-d4b8fe4fd877/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.32.0 h1:zWTV+LMdc3kaiJMSTOFz2UgSBgx8RNQoTGiZu3fR9S0=
google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
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 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/gorp.v1 v1.7.2/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
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.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v0.0.0-20181223230014-1083505acf35/go.mod h1:R//lfYlUuTOTfblYI3lGoAAAebUdzjvbmQsuB7Ykd90=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
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=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=