14
.gitignore
vendored
14
.gitignore
vendored
@@ -1,20 +1,16 @@
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
speedrun
|
||||
^speedrun
|
||||
TODO
|
||||
.vscode
|
||||
.idea
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
dist/
|
||||
*.crt
|
||||
*.key
|
||||
*.csr
|
||||
*.srl
|
||||
|
||||
52
Makefile
Normal file
52
Makefile
Normal file
@@ -0,0 +1,52 @@
|
||||
GITCOMMIT=$(shell git rev-parse --short HEAD 2>/dev/null)
|
||||
DATE=$(shell date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||
VERSION=$(shell git branch --show-current)
|
||||
DIST=dist
|
||||
LINUX_PATH=$(DIST)/linux
|
||||
DARWIN_PATH=$(DIST)/darwin
|
||||
|
||||
all: requirements speedrun-linux speedrun-darwin portal-linux
|
||||
|
||||
clean:
|
||||
rm -rf dist
|
||||
|
||||
requirements:
|
||||
@go mod tidy -compat=1.17
|
||||
@go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
|
||||
@go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
|
||||
|
||||
speedrun-linux-amd64: requirements
|
||||
GOOS=linux GOARCH=amd64 go build -o $(DIST)/speedrun-linux-amd64 -ldflags "-X github.com/speedrunsh/speedrun/cmd/speedrun/cli.version=$(VERSION) -X github.com/speedrunsh/speedrun/cmd/speedrun/cli.commit=$(GITCOMMIT) -X github.com/speedrunsh/speedrun/cmd/speedrun/cli.date=$(DATE)" ./cmd/speedrun
|
||||
|
||||
speedrun-linux-arm64: requirements
|
||||
GOOS=linux GOARCH=arm64 go build -o $(DIST)/speedrun-linux-arm64 -ldflags "-X github.com/speedrunsh/speedrun/cmd/speedrun/cli.version=$(VERSION) -X github.com/speedrunsh/speedrun/cmd/speedrun/cli.commit=$(GITCOMMIT) -X github.com/speedrunsh/speedrun/cmd/speedrun/cli.date=$(DATE)" ./cmd/speedrun
|
||||
|
||||
speedrun-linux: speedrun-linux-amd64 speedrun-linux-arm64
|
||||
|
||||
speedrun-darwin-amd64: requirements
|
||||
GOOS=darwin GOARCH=amd64 go build -o $(DIST)/speedrun-darwin-amd64 -ldflags "-X github.com/speedrunsh/speedrun/cmd/speedrun/cli.version=$(VERSION) -X github.com/speedrunsh/speedrun/cmd/speedrun/cli.commit=$(GITCOMMIT) -X github.com/speedrunsh/speedrun/cmd/speedrun/cli.date=$(DATE)" ./cmd/speedrun
|
||||
|
||||
speedrun-darwin-arm64: requirements
|
||||
GOOS=darwin GOARCH=arm64 go build -o $(DIST)/speedrun-darwin-arm64 -ldflags "-X github.com/speedrunsh/speedrun/cmd/speedrun/cli.version=$(VERSION) -X github.com/speedrunsh/speedrun/cmd/speedrun/cli.commit=$(GITCOMMIT) -X github.com/speedrunsh/speedrun/cmd/speedrun/cli.date=$(DATE)" ./cmd/speedrun
|
||||
|
||||
speedrun-darwin: speedrun-darwin-amd64 speedrun-darwin-arm64
|
||||
|
||||
speedrun: speedrun-linux speedrun-darwin
|
||||
|
||||
|
||||
portal-linux-amd64: requirements
|
||||
GOOS=linux GOARCH=amd64 go build -o $(DIST)/portal-linux-amd64 ./cmd/portal
|
||||
# zip $(DIST)/portal-linux-amd64.zip $(DIST)/portal-linux-amd64
|
||||
|
||||
portal-linux-arm64: requirements
|
||||
GOOS=linux GOARCH=arm64 go build -o $(DIST)/portal-linux-arm64 ./cmd/portal
|
||||
# zip $(DIST)/portal-linux-arm64.zip $(DIST)/portal-linux-arm64
|
||||
|
||||
portal-linux: portal-linux-amd64 portal-linux-arm64
|
||||
|
||||
portal: portal-linux
|
||||
|
||||
dev: speedrun-darwin-arm64 portal-linux-amd64
|
||||
|
||||
proto:
|
||||
protoc --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. proto/portal/portal.proto
|
||||
83
README.md
83
README.md
@@ -1,77 +1,80 @@
|
||||
<p align="center">
|
||||
<a rel="nofollow">
|
||||
<img src="docs/logo.png?raw=true" width="200" style="max-width:100%;">
|
||||
<img src="assets/logo.png?raw=true" width="200" style="max-width:100%;">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
# Speedrun
|
||||
|
||||
[](https://github.com/dpogorzelski/speedrun/blob/master/LICENSE)
|
||||
[](https://goreportcard.com/report/github.com/dpogorzelski/speedrun)
|
||||
[](https://github.com/dpogorzelski/speedrun/actions/workflows/go.yml)
|
||||
|
||||
Speedrun is an action execution framework that works at scale.
|
||||
Speedrun helps you control your compute fleet with minimal effort.
|
||||
|
||||
It allows you to run any action/command across any number of servers, projects and cloud vendors with ease and fast (currently GCP only but AWS and Azure will be supported as well), example:
|
||||
Example (stop nginx across 3k machines):
|
||||
|
||||
```bash
|
||||
speedrun run systemctl stop nginx
|
||||
speedrun service stop nginx
|
||||
```
|
||||
|
||||
to stop nginx across 3k machines.
|
||||
|
||||
No hassles with setting up and maintaining a server with agents as speedrun has none. Single self-contained binary. Speedrun leverages SSH as transport with tight cloud vendor integration to take the burden of mundane things like key generation and propagation/revocation away from the user.
|
||||
|
||||
Server targeting (`--target`) is made as intuitive as possible, currently based on [gcloud topic filters](https://cloud.google.com/sdk/gcloud/reference/topic/filters) but in the future will be replaced by a generic selection mechanism to provide a seamless experience across different cloud vendors.
|
||||
|
||||
|
||||
Features:
|
||||
|
||||
* native cloud integration (currently Google Cloud only, AWS and Azure coming up!)
|
||||
* stateless and agentless
|
||||
* stateless
|
||||
* serverless
|
||||
* idempotent
|
||||
* no complex configuration required
|
||||
* single self-contained binary
|
||||
* can run against any number of servers and projects seamlessly
|
||||
* a plugin system is in the plan to allow anyone to integrate execution modules that will wrap complex functionality instead of running raw shell commands
|
||||
|
||||
* server discovery via native cloud integration (currently Google Cloud only, AWS and Azure coming up!)
|
||||
* extensible (plugin system is in the works)
|
||||
|
||||
## Installation
|
||||
|
||||
#### Homebrew (MacOS, Linux)
|
||||
```bash
|
||||
brew install dpogorzelski/tap/speedrun
|
||||
```
|
||||
#### MacOS, Linux, Windows
|
||||
|
||||
Download the precompiled binaries from here: [Releases](https://github.com/dpogorzelski/speedrun/releases)
|
||||
|
||||
#### Manual (MacOS, Linux, Windows)
|
||||
Download the precompiled binary from here: [Releases](https://github.com/dpogorzelski/speedrun/releases)
|
||||
## Usage
|
||||
|
||||
#### Quickstart
|
||||
|
||||
On a server:
|
||||
|
||||
`sudo ./portal --insecure`
|
||||
|
||||
On your machine:
|
||||
|
||||
```bash
|
||||
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/serviceaccount.json
|
||||
speedrun init
|
||||
speedrun key new
|
||||
speedrun key authorize
|
||||
speedrun run whoami
|
||||
speedrun run whoami --insecure
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
* picture first here
|
||||
|
||||
* speedrun client
|
||||
|
||||
* portal
|
||||
|
||||
* protocols
|
||||
|
||||
* service discovery
|
||||
|
||||
* language definition [expr/Language-Definition.md at master · antonmedv/expr · GitHub](https://github.com/antonmedv/expr/blob/master/docs/Language-Definition.md)
|
||||
|
||||
## Examples
|
||||
|
||||
Use 1000 concurrent SSH workers
|
||||
Stop Nginx on VMs that have a label `role` with value `nginx` and a label named `project` with value `someproject`
|
||||
|
||||
```bash
|
||||
speedrun run "uname -r" --concurrency 1000
|
||||
speedrun service stop nginx --target "labels.role == 'nginx' and labels.project == 'someproject'r"
|
||||
```
|
||||
|
||||
Stop Nginx on VMs matching the target selector
|
||||
Run arbitrary shell command on the target machines. Ignore Portal's certificate and connect via private IP address.
|
||||
|
||||
```bash
|
||||
speedrun run sudo systemctl stop nginx --target "labels.env=staging AND labels.app=foobar"
|
||||
```
|
||||
|
||||
Ignore SSH fingerprint mismatch and connect via private IP addresses
|
||||
|
||||
```bash
|
||||
speedrun run "ls -la" --target "labels.env != prod" --ignore-fingerprint --concurrency 1000 --use-private-ip
|
||||
speedrun run "ls -la" --target "labels.env != 'prod'" --insecure --use-private-ip
|
||||
```
|
||||
|
||||
Use a different config file
|
||||
@@ -82,7 +85,11 @@ speedrun run whoami -c /path/to/config.toml
|
||||
|
||||
## Configuration
|
||||
|
||||
Using certain flags repeteadly can be annoying, it's possible to persist their behavior via config file. Default config file is located at `~/.speedrun/config.toml` and can be re-initialized to it's default form via `speedrun init`.
|
||||
Instead of supplying certain flags repeatedly you can persist their behavior in the config file. Default config file is located at `~/.speedrun/config.toml` and default settings can be fetched via `speedrun init --print`.
|
||||
|
||||
#### Run portal as a systemd unit
|
||||
|
||||
#### Use self signed certificates during testing
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
8
build.sh
8
build.sh
@@ -1,8 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
GITCOMMIT=$(git rev-parse --short HEAD 2>/dev/null)
|
||||
DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||
VERSION=$(git branch --show-current)
|
||||
|
||||
go build -ldflags "-X speedrun/cmd.version=$VERSION -X speedrun/cmd.commit=$GITCOMMIT -X speedrun/cmd.date=$DATE"
|
||||
@@ -1,55 +0,0 @@
|
||||
package cloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/oauth2/google"
|
||||
"google.golang.org/api/compute/v1"
|
||||
"google.golang.org/api/oslogin/v1"
|
||||
)
|
||||
|
||||
type GCPClient struct {
|
||||
gce *compute.Service
|
||||
oslogin *oslogin.Service
|
||||
client_email string
|
||||
Project string
|
||||
}
|
||||
|
||||
func NewGCPClient(project string) (*GCPClient, error) {
|
||||
var err error
|
||||
ctx := context.Background()
|
||||
credentials, err := google.FindDefaultCredentials(ctx, compute.ComputeScope)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("couldn't fetch default client credentials: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var jsonCreds map[string]interface{}
|
||||
err = json.Unmarshal(credentials.JSON, &jsonCreds)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("couldn't decode default client credentials json: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gce, err := compute.NewService(ctx)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("couldn't initialize GCP client: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
osc, err := oslogin.NewService(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := &GCPClient{
|
||||
gce: gce,
|
||||
oslogin: osc,
|
||||
client_email: jsonCreds["client_email"].(string),
|
||||
Project: project,
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package cloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"google.golang.org/api/compute/v1"
|
||||
)
|
||||
|
||||
// GetInstances returns a list of external IP addresses used for the SHH connection
|
||||
func (c *GCPClient) GetInstances(filter string, usePrivateIP bool) ([]Instance, error) {
|
||||
instances := []Instance{}
|
||||
listCall := c.gce.Instances.AggregatedList(c.Project).Fields("nextPageToken", "items(Name,NetworkInterfaces)")
|
||||
var ctx context.Context
|
||||
|
||||
listCall.Filter(filter).Pages(ctx, func(list *compute.InstanceAggregatedList) error {
|
||||
for _, item := range list.Items {
|
||||
for _, instance := range item.Instances {
|
||||
i := &Instance{
|
||||
Name: instance.Name,
|
||||
}
|
||||
if usePrivateIP {
|
||||
i.Address = instance.NetworkInterfaces[0].NetworkIP
|
||||
} else {
|
||||
i.Address = instance.NetworkInterfaces[0].AccessConfigs[0].NatIP
|
||||
}
|
||||
|
||||
instances = append(instances, *i)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
_, err := listCall.Do()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return instances, nil
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
package cloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"speedrun/key"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/api/compute/v1"
|
||||
)
|
||||
|
||||
// addKeyToMetadataP updates SSH key entires in the project metadata
|
||||
func (c *GCPClient) AddKeyToMetadata(key *key.Key) error {
|
||||
projectData, err := c.gce.Projects.Get(c.Project).Do()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
item, err := formatSSHKey(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hasKey, same, i := hasItem(projectData.CommonInstanceMetadata, item)
|
||||
var items []*compute.MetadataItems
|
||||
|
||||
if hasKey && same {
|
||||
return nil
|
||||
} else if hasKey && !same {
|
||||
items = updateMetadata(projectData.CommonInstanceMetadata, item, i)
|
||||
} else if !hasKey {
|
||||
items = appendToMetadata(projectData.CommonInstanceMetadata, item)
|
||||
}
|
||||
|
||||
metadata := compute.Metadata{
|
||||
Fingerprint: projectData.CommonInstanceMetadata.Fingerprint,
|
||||
Items: items,
|
||||
}
|
||||
|
||||
setMetadata := c.gce.Projects.SetCommonInstanceMetadata(c.Project, &metadata)
|
||||
_, err = setMetadata.Do()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// removeKeyFromMetadata removes user's ssh public key from the project metadata
|
||||
func (c *GCPClient) RemoveKeyFromMetadata(key *key.Key) error {
|
||||
projectData, err := c.gce.Projects.Get(c.Project).Do()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
item, err := formatSSHKey(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hasKey, same, i := hasItem(projectData.CommonInstanceMetadata, item)
|
||||
var items []*compute.MetadataItems
|
||||
|
||||
if hasKey && same {
|
||||
removeFromMetadata(projectData.CommonInstanceMetadata, item, i)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
||||
metadata := compute.Metadata{
|
||||
Fingerprint: projectData.CommonInstanceMetadata.Fingerprint,
|
||||
Items: items,
|
||||
}
|
||||
|
||||
setMetadata := c.gce.Projects.SetCommonInstanceMetadata(c.Project, &metadata)
|
||||
_, err = setMetadata.Do()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Extracts username, algorithm and comment from a metadata SSH key item
|
||||
func parseMetadataitem(key string) (string, string, string) {
|
||||
t := strings.Split(key, " ")
|
||||
head, comment := t[0], t[len(t)-1]
|
||||
username := strings.Split(head, ":")[0]
|
||||
algo := strings.Split(head, ":")[1]
|
||||
return username, algo, comment
|
||||
}
|
||||
|
||||
// Verifies if a metadata item already exists for a given user/cipher/comment combination.
|
||||
// If true it also returns the index number at which the existing item can be found otherwise index is -1.
|
||||
func hasItem(md *compute.Metadata, x string) (bool, bool, int) {
|
||||
flatMD := flattenMetadata(md)
|
||||
if flatMD["ssh-keys"] == nil {
|
||||
return false, false, -1
|
||||
}
|
||||
|
||||
items := strings.Split(flatMD["ssh-keys"].(string), "\n")
|
||||
username, algo, comment := parseMetadataitem(x)
|
||||
|
||||
for i, e := range items {
|
||||
header := fmt.Sprintf("%s:%s", username, algo)
|
||||
if x == e {
|
||||
return true, true, i
|
||||
} else if strings.HasPrefix(e, header) && strings.HasSuffix(e, comment) {
|
||||
return true, false, i
|
||||
}
|
||||
}
|
||||
return false, false, -1
|
||||
}
|
||||
|
||||
// formatSSHKey formats public key item according to GCP guidelines
|
||||
func formatSSHKey(key *key.Key) (string, error) {
|
||||
authorizedKey, err := key.MarshalAuthorizedKey()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
v := fmt.Sprintf("%s:%s %s", key.User, authorizedKey, key.Comment)
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func appendToMetadata(md *compute.Metadata, item string) []*compute.MetadataItems {
|
||||
var items []string
|
||||
flatMD := flattenMetadata(md)
|
||||
if flatMD["ssh-keys"] == nil {
|
||||
items = append(items, item)
|
||||
flatMD["ssh-keys"] = strings.Join(items, "\n")
|
||||
return expandComputeMetadata(flatMD)
|
||||
}
|
||||
|
||||
items = strings.Split(flatMD["ssh-keys"].(string), "\n")
|
||||
items = append(items, item)
|
||||
flatMD["ssh-keys"] = strings.Join(items, "\n")
|
||||
return expandComputeMetadata(flatMD)
|
||||
}
|
||||
|
||||
func removeFromMetadata(md *compute.Metadata, item string, i int) []*compute.MetadataItems {
|
||||
var items []string
|
||||
flatMD := flattenMetadata(md)
|
||||
items = strings.Split(flatMD["ssh-keys"].(string), "\n")
|
||||
copy(items[i:], items[i+1:])
|
||||
items[len(items)-1] = ""
|
||||
items = items[:len(items)-1]
|
||||
flatMD["ssh-keys"] = strings.Join(items, "\n")
|
||||
return expandComputeMetadata(flatMD)
|
||||
}
|
||||
|
||||
func updateMetadata(md *compute.Metadata, item string, i int) []*compute.MetadataItems {
|
||||
var items []string
|
||||
flatMD := flattenMetadata(md)
|
||||
items = strings.Split(flatMD["ssh-keys"].(string), "\n")
|
||||
items[i] = item
|
||||
flatMD["ssh-keys"] = strings.Join(items, "\n")
|
||||
return expandComputeMetadata(flatMD)
|
||||
}
|
||||
|
||||
func expandComputeMetadata(m map[string]interface{}) []*compute.MetadataItems {
|
||||
metadata := make([]*compute.MetadataItems, len(m))
|
||||
var keys []string
|
||||
for key := range m {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
for _, key := range keys {
|
||||
v := m[key].(string)
|
||||
metadata = append(metadata, &compute.MetadataItems{
|
||||
Key: key,
|
||||
Value: &v,
|
||||
})
|
||||
}
|
||||
|
||||
return metadata
|
||||
}
|
||||
|
||||
func flattenMetadata(metadata *compute.Metadata) map[string]interface{} {
|
||||
metadataMap := make(map[string]interface{})
|
||||
for _, item := range metadata.Items {
|
||||
metadataMap[item.Key] = *item.Value
|
||||
}
|
||||
return metadataMap
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package cloud
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"speedrun/key"
|
||||
|
||||
"github.com/apex/log"
|
||||
"google.golang.org/api/oslogin/v1"
|
||||
)
|
||||
|
||||
func (c *GCPClient) AddUserKey(key *key.Key) error {
|
||||
parent := fmt.Sprintf("users/%s", c.client_email)
|
||||
|
||||
authorizedKey, err := key.MarshalAuthorizedKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sshPublicKey := &oslogin.SshPublicKey{
|
||||
Key: string(authorizedKey),
|
||||
}
|
||||
|
||||
_, err = c.oslogin.Users.ImportSshPublicKey(parent, sshPublicKey).Do()
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *GCPClient) RemoveUserKey(key *key.Key) error {
|
||||
authorizedKey, err := key.MarshalAuthorizedKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
name := fmt.Sprintf("users/%s/sshPublicKeys/%x", c.client_email, sha256.Sum256([]byte(authorizedKey)))
|
||||
_, err = c.oslogin.Users.SshPublicKeys.Delete(name).Do()
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *GCPClient) ListUserKeys() error {
|
||||
parent := fmt.Sprintf("users/%s", c.client_email)
|
||||
|
||||
profile, err := c.oslogin.Users.GetLoginProfile(parent).Do()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, k := range profile.SshPublicKeys {
|
||||
log.Info(k.Key)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *GCPClient) GetSAUsername() (string, error) {
|
||||
parent := fmt.Sprintf("users/%s", c.client_email)
|
||||
|
||||
profile, err := c.oslogin.Users.GetLoginProfile(parent).Do()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return profile.PosixAccounts[0].Username, nil
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package cloud
|
||||
|
||||
type Instance struct {
|
||||
Address string
|
||||
Name string
|
||||
}
|
||||
15
cmd/init.go
15
cmd/init.go
@@ -1,15 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"speedrun/config"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var initCmd = &cobra.Command{
|
||||
Use: "init",
|
||||
Short: "Initialize speedrun",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return config.Create()
|
||||
},
|
||||
}
|
||||
181
cmd/key.go
181
cmd/key.go
@@ -1,181 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"speedrun/cloud"
|
||||
"speedrun/key"
|
||||
|
||||
"github.com/apex/log"
|
||||
homedir "github.com/mitchellh/go-homedir"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var keyCmd = &cobra.Command{
|
||||
Use: "key",
|
||||
Short: "Manage ssh keys",
|
||||
TraverseChildren: true,
|
||||
}
|
||||
|
||||
var newKeyCmd = &cobra.Command{
|
||||
Use: "new",
|
||||
Short: "Create a new ssh key",
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
initConfig()
|
||||
},
|
||||
RunE: newKey,
|
||||
}
|
||||
|
||||
var authorizeKeyCmd = &cobra.Command{
|
||||
Use: "authorize",
|
||||
Short: "Authorize key for ssh access",
|
||||
Example: " speedrun key authorize",
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
initConfig()
|
||||
},
|
||||
RunE: authorizeKey,
|
||||
}
|
||||
|
||||
var revokeKeyCmd = &cobra.Command{
|
||||
Use: "revoke",
|
||||
Short: "Revoke ssh key",
|
||||
Example: " speedrun key revoke",
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
initConfig()
|
||||
},
|
||||
RunE: revokeKey,
|
||||
}
|
||||
|
||||
var listKeysCmd = &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List OS Login keys",
|
||||
Example: " speedrun key list",
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
initConfig()
|
||||
},
|
||||
RunE: listKeys,
|
||||
}
|
||||
|
||||
func init() {
|
||||
keyCmd.AddCommand(newKeyCmd)
|
||||
keyCmd.AddCommand(authorizeKeyCmd)
|
||||
keyCmd.AddCommand(revokeKeyCmd)
|
||||
keyCmd.AddCommand(listKeysCmd)
|
||||
authorizeKeyCmd.Flags().Bool("use-oslogin", false, "Authorize the key via OS Login rather than metadata")
|
||||
viper.BindPFlag("gcp.use-oslogin", authorizeKeyCmd.Flags().Lookup("use-oslogin"))
|
||||
}
|
||||
|
||||
func determineKeyFilePath() (string, error) {
|
||||
log.Debug("Determining private key path")
|
||||
home, err := homedir.Dir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
path := filepath.Join(home, ".speedrun/privatekey")
|
||||
return path, nil
|
||||
}
|
||||
|
||||
func newKey(cmd *cobra.Command, args []string) error {
|
||||
k, err := key.New()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path, err := determineKeyFilePath()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = k.Write(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Info("Private key created")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func authorizeKey(cmd *cobra.Command, args []string) error {
|
||||
project := viper.GetString("gcp.projectid")
|
||||
useOSlogin := viper.GetBool("gcp.use-oslogin")
|
||||
|
||||
gcpClient, err := cloud.NewGCPClient(project)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path, err := determineKeyFilePath()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
k, err := key.Read(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if useOSlogin {
|
||||
gcpClient.AddUserKey(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Info("Authorized key via OS Login")
|
||||
} else {
|
||||
gcpClient.AddKeyToMetadata(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Info("Authorized key in the project metadata")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func revokeKey(cmd *cobra.Command, args []string) error {
|
||||
project := viper.GetString("gcp.projectid")
|
||||
gcpClient, err := cloud.NewGCPClient(project)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path, err := determineKeyFilePath()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
k, err := key.Read(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info("Revoking public key")
|
||||
err = gcpClient.RemoveKeyFromMetadata(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = gcpClient.RemoveUserKey(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func listKeys(cmd *cobra.Command, args []string) error {
|
||||
project := viper.GetString("gcp.projectid")
|
||||
gcpClient, err := cloud.NewGCPClient(project)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info("Fetching OS Login keys")
|
||||
err = gcpClient.ListUserKeys()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
59
cmd/portal/cli/init.go
Normal file
59
cmd/portal/cli/init.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/pelletier/go-toml"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func init() {
|
||||
initCmd.Flags().BoolP("print", "p", false, "Print default config to stdout")
|
||||
}
|
||||
|
||||
var initCmd = &cobra.Command{
|
||||
Use: "init",
|
||||
Short: "Initialize portal",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
print, err := cmd.Flags().GetBool("print")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if print {
|
||||
c := viper.AllSettings()
|
||||
bs, err := toml.Marshal(c)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to marshal config: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println(string(bs))
|
||||
return nil
|
||||
}
|
||||
|
||||
dir := filepath.Dir(cfgFile)
|
||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
err = os.Mkdir(dir, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = viper.SafeWriteConfigAs(cfgFile)
|
||||
if err != nil {
|
||||
if _, ok := err.(viper.ConfigFileAlreadyExistsError); !ok {
|
||||
return fmt.Errorf("couldn't save config at \"%s\" (%s)", viper.ConfigFileUsed(), err)
|
||||
}
|
||||
} else {
|
||||
log.Infof("Your config was saved at \"%s\"", viper.ConfigFileUsed())
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Infof("Config already exists at \"%s\", no changes applied", viper.ConfigFileUsed())
|
||||
return nil
|
||||
},
|
||||
}
|
||||
128
cmd/portal/cli/root.go
Normal file
128
cmd/portal/cli/root.go
Normal file
@@ -0,0 +1,128 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/apex/log"
|
||||
jsonhandler "github.com/apex/log/handlers/json"
|
||||
texthandler "github.com/apex/log/handlers/text"
|
||||
"github.com/speedrunsh/speedrun/pkg/common/cryptoutil"
|
||||
"github.com/speedrunsh/speedrun/pkg/portal"
|
||||
portalpb "github.com/speedrunsh/speedrun/proto/portal"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"storj.io/drpc/drpcmux"
|
||||
"storj.io/drpc/drpcserver"
|
||||
)
|
||||
|
||||
var cfgFile string
|
||||
var version string
|
||||
var commit string
|
||||
var date string
|
||||
|
||||
func Execute() {
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "portal",
|
||||
Short: "Control your compute fleet at scale",
|
||||
Version: fmt.Sprintf("%s, commit: %s, date: %s", version, commit, date),
|
||||
SilenceUsage: true,
|
||||
SilenceErrors: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
insecure := viper.GetBool("tls.insecure")
|
||||
caPath := viper.GetString("tls.ca")
|
||||
certPath := viper.GetString("tls.cert")
|
||||
keyPath := viper.GetString("tls.key")
|
||||
|
||||
m := drpcmux.New()
|
||||
var err error
|
||||
err = portalpb.DRPCRegisterPortal(m, &portal.Server{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not register DRPC server: %v", err)
|
||||
}
|
||||
s := drpcserver.New(m)
|
||||
|
||||
var tlsConfig *tls.Config
|
||||
if insecure {
|
||||
log.Warn("Using insecure TLS configuration, this should be avoided in production environments")
|
||||
tlsConfig, err = cryptoutil.InsecureTLSConfig()
|
||||
} else {
|
||||
tlsConfig, err = cryptoutil.ServerTLSConfig(caPath, certPath, keyPath)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not initialize TLS config: %v", err)
|
||||
}
|
||||
|
||||
port := viper.GetInt("port")
|
||||
ip := viper.GetString("address")
|
||||
addr := fmt.Sprintf("%s:%d", ip, port)
|
||||
lis, err := tls.Listen("tcp", addr, tlsConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create TCP socket: %v", err)
|
||||
}
|
||||
defer lis.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
log.Infof("Starting portal on %s", addr)
|
||||
return s.Serve(ctx, lis)
|
||||
},
|
||||
}
|
||||
|
||||
dir := "/etc/portal"
|
||||
configPath := filepath.Join(dir, "config.toml")
|
||||
|
||||
cobra.OnInitialize(initConfig)
|
||||
rootCmd.AddCommand(initCmd)
|
||||
rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", configPath, "config file")
|
||||
rootCmd.PersistentFlags().StringP("loglevel", "l", "info", "Log level")
|
||||
rootCmd.PersistentFlags().BoolP("json", "j", false, "Output logs in JSON format")
|
||||
rootCmd.Flags().IntP("port", "p", 1337, "Port to listen on for connections")
|
||||
rootCmd.Flags().StringP("address", "a", "0.0.0.0", "Address to listen on for connections")
|
||||
rootCmd.Flags().Bool("insecure", false, "Skip client certificate verification")
|
||||
rootCmd.Flags().String("ca", "ca.crt", "Path to the CA cert")
|
||||
rootCmd.Flags().String("cert", "portal.crt", "Path to the server cert")
|
||||
rootCmd.Flags().String("key", "portal.key", "Path to the server key")
|
||||
|
||||
viper.BindPFlag("tls.insecure", rootCmd.Flags().Lookup("insecure"))
|
||||
viper.BindPFlag("tls.ca", rootCmd.Flags().Lookup("ca"))
|
||||
viper.BindPFlag("tls.cert", rootCmd.Flags().Lookup("cert"))
|
||||
viper.BindPFlag("tls.key", rootCmd.Flags().Lookup("key"))
|
||||
viper.BindPFlag("logging.loglevel", rootCmd.PersistentFlags().Lookup("loglevel"))
|
||||
viper.BindPFlag("logging.json", rootCmd.PersistentFlags().Lookup("json"))
|
||||
viper.BindPFlag("port", rootCmd.Flags().Lookup("port"))
|
||||
viper.BindPFlag("address", rootCmd.Flags().Lookup("address"))
|
||||
|
||||
rootCmd.DisableSuggestions = false
|
||||
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
log.Error(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func initConfig() {
|
||||
viper.SetConfigFile(cfgFile)
|
||||
viper.AutomaticEnv()
|
||||
|
||||
json := viper.GetBool("logging.json")
|
||||
if json {
|
||||
handler := jsonhandler.New(os.Stdout)
|
||||
log.SetHandler(handler)
|
||||
} else {
|
||||
handler := texthandler.New(os.Stdout)
|
||||
log.SetHandler(handler)
|
||||
}
|
||||
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
log.Warnf("Couldn't read config at \"%s\", starting with default settings", viper.ConfigFileUsed())
|
||||
}
|
||||
|
||||
lvl, err := log.ParseLevel(viper.GetString("logging.loglevel"))
|
||||
if err != nil {
|
||||
log.Fatalf("couldn't parse log level: %s (%s)", err, lvl)
|
||||
return
|
||||
}
|
||||
log.SetLevel(lvl)
|
||||
}
|
||||
9
cmd/portal/main.go
Normal file
9
cmd/portal/main.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/speedrunsh/speedrun/cmd/portal/cli"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cli.Execute()
|
||||
}
|
||||
72
cmd/root.go
72
cmd/root.go
@@ -1,72 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/apex/log"
|
||||
homedir "github.com/mitchellh/go-homedir"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var cfgFile string
|
||||
var version string
|
||||
var commit string
|
||||
var date string
|
||||
|
||||
//Execute runs the root command
|
||||
func Execute() {
|
||||
// cobra.OnInitialize(initConfig)
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "speedrun",
|
||||
Short: "Cloud first command execution",
|
||||
Version: fmt.Sprintf("%s, commit: %s, date: %s", version, commit, date),
|
||||
SilenceUsage: true,
|
||||
SilenceErrors: true,
|
||||
}
|
||||
|
||||
rootCmd.AddCommand(initCmd)
|
||||
rootCmd.AddCommand(keyCmd)
|
||||
rootCmd.AddCommand(runCmd)
|
||||
|
||||
home, err := homedir.Dir()
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
dir := filepath.Join(home, ".speedrun")
|
||||
path := filepath.Join(dir, "config.toml")
|
||||
|
||||
rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", path, "config file")
|
||||
rootCmd.PersistentFlags().StringP("loglevel", "l", "info", "Log level")
|
||||
viper.BindPFlag("loglevel", rootCmd.PersistentFlags().Lookup("loglevel"))
|
||||
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func initConfig() {
|
||||
dir, file := filepath.Split(cfgFile)
|
||||
viper.SetConfigName(file)
|
||||
viper.SetConfigType("toml")
|
||||
viper.AddConfigPath(dir)
|
||||
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
log.Fatal("Run `speedrun init` first")
|
||||
}
|
||||
} else {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
lvl, err := log.ParseLevel(viper.GetString("loglevel"))
|
||||
if err != nil {
|
||||
log.Fatalf("Couldn't parse log level: %s", err)
|
||||
return
|
||||
}
|
||||
log.SetLevel(lvl)
|
||||
|
||||
}
|
||||
101
cmd/run.go
101
cmd/run.go
@@ -1,101 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"speedrun/cloud"
|
||||
"speedrun/key"
|
||||
"speedrun/marathon"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var runCmd = &cobra.Command{
|
||||
Use: "run <command to run>",
|
||||
Short: "Run command on remote servers",
|
||||
Example: " speedrun run whoami\n speedrun run whoami --only-failures --target \"labels.foo = bar AND labels.environment = staging\"",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
initConfig()
|
||||
},
|
||||
RunE: run,
|
||||
}
|
||||
|
||||
func init() {
|
||||
runCmd.Flags().StringP("target", "t", "", "Fetch instances that match the target selection criteria")
|
||||
runCmd.Flags().String("projectid", "", "Override GCP project id")
|
||||
runCmd.Flags().Bool("only-failures", false, "Print only failures and errors")
|
||||
runCmd.Flags().Bool("ignore-fingerprint", false, "Ignore host's fingerprint mismatch")
|
||||
runCmd.Flags().Duration("timeout", time.Duration(10*time.Second), "SSH connection timeout")
|
||||
runCmd.Flags().Int("concurrency", 100, "Number of maximum concurrent SSH workers")
|
||||
runCmd.Flags().Bool("use-private-ip", false, "Connect to private IPs instead of public ones")
|
||||
runCmd.Flags().Bool("use-oslogin", false, "Authenticate via OS Login")
|
||||
viper.BindPFlag("gcp.projectid", runCmd.Flags().Lookup("projectid"))
|
||||
viper.BindPFlag("gcp.use-oslogin", runCmd.Flags().Lookup("use-oslogin"))
|
||||
viper.BindPFlag("ssh.timeout", runCmd.Flags().Lookup("timeout"))
|
||||
viper.BindPFlag("ssh.ignore-fingerprint", runCmd.Flags().Lookup("ignore-fingerprint"))
|
||||
viper.BindPFlag("ssh.only-failures", runCmd.Flags().Lookup("only-failures"))
|
||||
viper.BindPFlag("ssh.concurrency", runCmd.Flags().Lookup("concurrency"))
|
||||
viper.BindPFlag("ssh.use-private-ip", runCmd.Flags().Lookup("use-private-ip"))
|
||||
}
|
||||
|
||||
func run(cmd *cobra.Command, args []string) error {
|
||||
command := strings.Join(args, " ")
|
||||
project := viper.GetString("gcp.projectid")
|
||||
timeout := viper.GetDuration("ssh.timeout")
|
||||
ignoreFingerprint := viper.GetBool("ssh.ignore-fingerprint")
|
||||
onlyFailures := viper.GetBool("ssh.only-failures")
|
||||
concurrency := viper.GetInt("ssh.concurrency")
|
||||
usePrivateIP := viper.GetBool("ssh.use-private-ip")
|
||||
useOSlogin := viper.GetBool("gcp.use-oslogin")
|
||||
|
||||
target, err := cmd.Flags().GetString("target")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gcpClient, err := cloud.NewGCPClient(project)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path, err := determineKeyFilePath()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
k, err := key.Read(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info("Fetching instance list")
|
||||
instances, err := gcpClient.GetInstances(target, usePrivateIP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(instances) == 0 {
|
||||
log.Warn("No instances found")
|
||||
return nil
|
||||
}
|
||||
|
||||
if useOSlogin {
|
||||
user, err := gcpClient.GetSAUsername()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
k.User = user
|
||||
}
|
||||
|
||||
m := marathon.New(command, timeout, concurrency)
|
||||
err = m.Run(instances, k, ignoreFingerprint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.PrintResult(onlyFailures)
|
||||
return nil
|
||||
}
|
||||
61
cmd/speedrun/cli/init.go
Normal file
61
cmd/speedrun/cli/init.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/pelletier/go-toml"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func init() {
|
||||
initCmd.SetUsageTemplate(usage)
|
||||
initCmd.Flags().BoolP("print", "p", false, "Print default config to stdout")
|
||||
}
|
||||
|
||||
var initCmd = &cobra.Command{
|
||||
Use: "init",
|
||||
Short: "Initialize speedrun",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
viper.SetDefault("gcp.projectid", "")
|
||||
print, err := cmd.Flags().GetBool("print")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if print {
|
||||
c := viper.AllSettings()
|
||||
bs, err := toml.Marshal(c)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to marshal config: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println(string(bs))
|
||||
return nil
|
||||
}
|
||||
|
||||
dir := filepath.Dir(cfgFile)
|
||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
err = os.Mkdir(dir, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = viper.SafeWriteConfigAs(cfgFile)
|
||||
if err != nil {
|
||||
if _, ok := err.(viper.ConfigFileAlreadyExistsError); !ok {
|
||||
return fmt.Errorf("couldn't save config at \"%s\" (%s)", viper.ConfigFileUsed(), err)
|
||||
}
|
||||
} else {
|
||||
log.Infof("Your config was saved at \"%s\"", viper.ConfigFileUsed())
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Infof("Config already exists at \"%s\", no changes applied", viper.ConfigFileUsed())
|
||||
return nil
|
||||
},
|
||||
}
|
||||
97
cmd/speedrun/cli/root.go
Normal file
97
cmd/speedrun/cli/root.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/apex/log"
|
||||
jsonhandler "github.com/apex/log/handlers/json"
|
||||
texthandler "github.com/apex/log/handlers/text"
|
||||
homedir "github.com/mitchellh/go-homedir"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var cfgFile string
|
||||
var version string
|
||||
var commit string
|
||||
var date string
|
||||
|
||||
//go:embed templates/root.tmpl
|
||||
var rootUsage string
|
||||
|
||||
//go:embed templates/usage.tmpl
|
||||
var usage string
|
||||
|
||||
func Execute() {
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "speedrun",
|
||||
Short: "Control your compute fleet at scale",
|
||||
Version: fmt.Sprintf("%s, commit: %s, date: %s", version, commit, date),
|
||||
SilenceUsage: true,
|
||||
SilenceErrors: true,
|
||||
}
|
||||
|
||||
cobra.OnInitialize(initConfig)
|
||||
rootCmd.SetUsageTemplate(rootUsage)
|
||||
rootCmd.AddCommand(initCmd, runCmd, serviceCmd)
|
||||
|
||||
home, err := homedir.Dir()
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
dir := filepath.Join(home, ".speedrun")
|
||||
configPath := filepath.Join(dir, "config.toml")
|
||||
|
||||
rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", configPath, "config file")
|
||||
rootCmd.PersistentFlags().StringP("loglevel", "l", "info", "Log level")
|
||||
rootCmd.PersistentFlags().BoolP("json", "j", false, "Output logs in JSON format")
|
||||
rootCmd.PersistentFlags().StringP("target", "t", "", "Fetch instances that match the target selection criteria")
|
||||
rootCmd.PersistentFlags().Bool("insecure", false, "Skip server certificate verification")
|
||||
rootCmd.PersistentFlags().String("ca", "ca.crt", "Path to the CA cert")
|
||||
rootCmd.PersistentFlags().String("cert", "cert.crt", "Path to the client cert")
|
||||
rootCmd.PersistentFlags().String("key", "key.key", "Path to the client key")
|
||||
rootCmd.PersistentFlags().Bool("use-private-ip", false, "Connect to private IPs instead of public ones")
|
||||
|
||||
viper.BindPFlag("logging.loglevel", rootCmd.PersistentFlags().Lookup("loglevel"))
|
||||
viper.BindPFlag("logging.json", rootCmd.PersistentFlags().Lookup("json"))
|
||||
viper.BindPFlag("tls.insecure", rootCmd.PersistentFlags().Lookup("insecure"))
|
||||
viper.BindPFlag("tls.ca", rootCmd.PersistentFlags().Lookup("ca"))
|
||||
viper.BindPFlag("tls.cert", rootCmd.PersistentFlags().Lookup("cert"))
|
||||
viper.BindPFlag("tls.key", rootCmd.PersistentFlags().Lookup("key"))
|
||||
viper.BindPFlag("portal.use-private-ip", rootCmd.PersistentFlags().Lookup("use-private-ip"))
|
||||
|
||||
rootCmd.DisableSuggestions = false
|
||||
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
log.Error(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func initConfig() {
|
||||
viper.SetConfigFile(cfgFile)
|
||||
viper.AutomaticEnv()
|
||||
|
||||
json := viper.GetBool("logging.json")
|
||||
if json {
|
||||
handler := jsonhandler.New(os.Stdout)
|
||||
log.SetHandler(handler)
|
||||
} else {
|
||||
handler := texthandler.New(os.Stdout)
|
||||
log.SetHandler(handler)
|
||||
}
|
||||
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
log.Warnf("Couldn't read config at \"%s\", starting with default settings", viper.ConfigFileUsed())
|
||||
}
|
||||
|
||||
lvl, err := log.ParseLevel(viper.GetString("logging.loglevel"))
|
||||
if err != nil {
|
||||
log.Fatalf("couldn't parse log level: %s (%s)", err, lvl)
|
||||
return
|
||||
}
|
||||
log.SetLevel(lvl)
|
||||
}
|
||||
86
cmd/speedrun/cli/run.go
Normal file
86
cmd/speedrun/cli/run.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/alitto/pond"
|
||||
"github.com/speedrunsh/speedrun/pkg/speedrun/cloud"
|
||||
portalpb "github.com/speedrunsh/speedrun/proto/portal"
|
||||
"storj.io/drpc/drpcconn"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var runCmd = &cobra.Command{
|
||||
Use: "run <command to run>",
|
||||
Short: "Run a shell command on remote servers",
|
||||
Example: " speedrun run whoami\n speedrun run whoami --target \"labels.foo = bar AND labels.environment = staging\"",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
RunE: run,
|
||||
}
|
||||
|
||||
func init() {
|
||||
runCmd.SetUsageTemplate(usage)
|
||||
}
|
||||
|
||||
func run(cmd *cobra.Command, args []string) error {
|
||||
command := strings.Join(args, " ")
|
||||
s := strings.Split(command, " ")
|
||||
usePrivateIP := viper.GetBool("portal.use-private-ip")
|
||||
|
||||
tlsConfig, err := cloud.SetupTLS()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
target, err := cmd.Flags().GetString("target")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
instances, err := cloud.GetInstances(target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pool := pond.New(1000, 10000)
|
||||
for _, p := range instances {
|
||||
instance := p
|
||||
pool.Submit(func() {
|
||||
fields := log.Fields{
|
||||
"host": instance.Name,
|
||||
"address": instance.GetAddress(usePrivateIP),
|
||||
}
|
||||
log := log.WithFields(fields)
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", instance.GetAddress(usePrivateIP), 1337)
|
||||
rawconn, err := tls.Dial("tcp", addr, tlsConfig)
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
conn := drpcconn.New(rawconn)
|
||||
defer conn.Close()
|
||||
|
||||
c := portalpb.NewDRPCPortalClient(conn)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
|
||||
defer cancel()
|
||||
|
||||
r, err := c.RunCommand(ctx, &portalpb.CommandRequest{Name: s[0], Args: s[1:]})
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return
|
||||
}
|
||||
log.WithField("state", r.GetState()).Info(r.GetMessage())
|
||||
})
|
||||
}
|
||||
pool.StopAndWait()
|
||||
return nil
|
||||
}
|
||||
142
cmd/speedrun/cli/service.go
Normal file
142
cmd/speedrun/cli/service.go
Normal file
@@ -0,0 +1,142 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/alitto/pond"
|
||||
"github.com/apex/log"
|
||||
"github.com/speedrunsh/speedrun/pkg/speedrun/cloud"
|
||||
portalpb "github.com/speedrunsh/speedrun/proto/portal"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"storj.io/drpc/drpcconn"
|
||||
)
|
||||
|
||||
var serviceCmd = &cobra.Command{
|
||||
Use: "service",
|
||||
Short: "Manage services",
|
||||
TraverseChildren: true,
|
||||
}
|
||||
|
||||
var restartCmd = &cobra.Command{
|
||||
Use: "restart <servicename>",
|
||||
Short: "Restart a service",
|
||||
Example: " speedrun service restart nginx",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
RunE: action,
|
||||
}
|
||||
|
||||
var startCmd = &cobra.Command{
|
||||
Use: "start <servicename>",
|
||||
Short: "Start a service",
|
||||
Example: " speedrun service start nginx",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
RunE: action,
|
||||
}
|
||||
|
||||
var stopCmd = &cobra.Command{
|
||||
Use: "stop <servicename>",
|
||||
Short: "Stop a service",
|
||||
Example: " speedrun service stop nginx",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
RunE: action,
|
||||
}
|
||||
|
||||
var statusCmd = &cobra.Command{
|
||||
Use: "status <servicename>",
|
||||
Short: "Return the status of the service",
|
||||
Example: " speedrun service status nginx",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
RunE: action,
|
||||
}
|
||||
|
||||
func init() {
|
||||
serviceCmd.SetUsageTemplate(usage)
|
||||
serviceCmd.AddCommand(restartCmd)
|
||||
serviceCmd.AddCommand(startCmd)
|
||||
serviceCmd.AddCommand(stopCmd)
|
||||
serviceCmd.AddCommand(statusCmd)
|
||||
}
|
||||
|
||||
func action(cmd *cobra.Command, args []string) error {
|
||||
usePrivateIP := viper.GetBool("portal.use-private-ip")
|
||||
|
||||
tlsConfig, err := cloud.SetupTLS()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
target, err := cmd.Flags().GetString("target")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
portals, err := cloud.GetInstances(target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pool := pond.New(1000, 10000)
|
||||
for _, p := range portals {
|
||||
portal := p
|
||||
pool.Submit(func() {
|
||||
fields := log.Fields{
|
||||
"host": portal.Name,
|
||||
"address": portal.GetAddress(usePrivateIP),
|
||||
}
|
||||
log := log.WithFields(fields)
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", portal.GetAddress(usePrivateIP), 1337)
|
||||
rawconn, err := tls.Dial("tcp", addr, tlsConfig)
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
conn := drpcconn.New(rawconn)
|
||||
defer conn.Close()
|
||||
|
||||
c := portalpb.NewDRPCPortalClient(conn)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
|
||||
defer cancel()
|
||||
|
||||
switch cmd.Name() {
|
||||
case "restart":
|
||||
r, err := c.ServiceRestart(ctx, &portalpb.ServiceRequest{Name: strings.Join(args, " ")})
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return
|
||||
}
|
||||
log.WithField("state", r.GetState()).Info(r.GetMessage())
|
||||
case "start":
|
||||
r, err := c.ServiceStart(ctx, &portalpb.ServiceRequest{Name: strings.Join(args, " ")})
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return
|
||||
}
|
||||
log.WithField("state", r.GetState()).Info(r.GetMessage())
|
||||
case "stop":
|
||||
r, err := c.ServiceStop(ctx, &portalpb.ServiceRequest{Name: strings.Join(args, " ")})
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return
|
||||
}
|
||||
log.WithField("state", r.GetState()).Info(r.GetMessage())
|
||||
case "status":
|
||||
r, err := c.ServiceStatus(ctx, &portalpb.ServiceRequest{Name: strings.Join(args, " ")})
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return
|
||||
}
|
||||
log.WithField("state", r.GetState()).Infof("Loadstate: \"%s\", Activestate: \"%s\", Substate: \"%s\"", r.GetLoadstate(), r.GetActivestate(), r.GetSubstate())
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
pool.StopAndWait()
|
||||
return nil
|
||||
}
|
||||
18
cmd/speedrun/cli/templates/root.tmpl
Normal file
18
cmd/speedrun/cli/templates/root.tmpl
Normal file
@@ -0,0 +1,18 @@
|
||||
Usage:{{if .Runnable}}
|
||||
{{.UseLine}}{{end}}{{if .HasAvailableSubCommands}}
|
||||
{{.CommandPath}} [command]{{end}}
|
||||
|
||||
Core Commands:{{range .Commands}}{{if (or (eq .Name "help") (eq .Name "init") (eq .Name "key") (eq .Name "portal") (eq .Name "completion"))}}
|
||||
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}
|
||||
|
||||
Action Commands:{{range .Commands}}{{if (or (eq .Name "run") (eq .Name "exec") (eq .Name "service"))}}
|
||||
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}
|
||||
{{if .HasAvailableLocalFlags}}
|
||||
Flags:
|
||||
{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}
|
||||
|
||||
Global Flags:
|
||||
{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}}
|
||||
|
||||
Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}}
|
||||
{{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}
|
||||
23
cmd/speedrun/cli/templates/usage.tmpl
Normal file
23
cmd/speedrun/cli/templates/usage.tmpl
Normal file
@@ -0,0 +1,23 @@
|
||||
Usage:{{if .Runnable}}
|
||||
{{.UseLine}}{{end}}{{if .HasAvailableSubCommands}}
|
||||
{{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}}
|
||||
|
||||
Aliases:
|
||||
{{.NameAndAliases}}{{end}}{{if .HasExample}}
|
||||
|
||||
Examples:
|
||||
{{.Example}}{{end}}{{if .HasAvailableSubCommands}}
|
||||
|
||||
Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
|
||||
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
|
||||
|
||||
Flags:
|
||||
{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}
|
||||
|
||||
Global Flags:
|
||||
{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}}
|
||||
|
||||
Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}}
|
||||
{{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
|
||||
|
||||
Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
|
||||
9
cmd/speedrun/main.go
Normal file
9
cmd/speedrun/main.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/speedrunsh/speedrun/cmd/speedrun/cli"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cli.Execute()
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package colors
|
||||
|
||||
import (
|
||||
"github.com/jwalton/gchalk"
|
||||
)
|
||||
|
||||
// Green returns a green string
|
||||
func Green(s string) string {
|
||||
return gchalk.Green(s)
|
||||
}
|
||||
|
||||
// Yellow returns a green string
|
||||
func Yellow(s string) string {
|
||||
return gchalk.Yellow(s)
|
||||
}
|
||||
|
||||
// Red returns a green string
|
||||
func Red(s string) string {
|
||||
return gchalk.Red(s)
|
||||
}
|
||||
|
||||
// Blue returns a blue string
|
||||
func Blue(s string) string {
|
||||
return gchalk.Blue(s)
|
||||
}
|
||||
|
||||
// White returns a white string
|
||||
func White(s string) string {
|
||||
return gchalk.White(s)
|
||||
}
|
||||
|
||||
// Purple returns a purple string
|
||||
func Purple(s string) string {
|
||||
return gchalk.RGB(196, 16, 224)(s)
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/manifoldco/promptui"
|
||||
homedir "github.com/mitchellh/go-homedir"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
//Create generates a new config
|
||||
func Create() error {
|
||||
viper.SetDefault("loglevel", "info")
|
||||
project := promptui.Prompt{
|
||||
Label: "Project id",
|
||||
Validate: func(input string) error {
|
||||
match, err := regexp.MatchString("^[a-z][a-z0-9-]{6,30}", input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !match {
|
||||
return errors.New("invalid projectid")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
prompt := promptui.Select{
|
||||
Label: "Pick a cloud provider",
|
||||
Items: []string{"Google Cloud"},
|
||||
HideHelp: true,
|
||||
}
|
||||
|
||||
_, result, err := prompt.Run()
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
switch result {
|
||||
case "Google Cloud":
|
||||
result, err := project.Run()
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
viper.SetDefault("gcp.projectid", result)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
home, err := homedir.Dir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dir := filepath.Join(home, ".speedrun")
|
||||
path := filepath.Join(dir, "config.toml")
|
||||
|
||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
err = os.Mkdir(dir, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = viper.WriteConfigAs(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Infof("Your config was saved at: %s", path)
|
||||
return nil
|
||||
}
|
||||
74
go.mod
74
go.mod
@@ -1,61 +1,55 @@
|
||||
module speedrun
|
||||
module github.com/speedrunsh/speedrun
|
||||
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/alitto/pond v1.5.1
|
||||
github.com/alitto/pond v1.7.0
|
||||
github.com/apex/log v1.9.0
|
||||
github.com/cheggaaa/pb/v3 v3.0.8
|
||||
github.com/jwalton/gchalk v1.0.3
|
||||
github.com/manifoldco/promptui v0.8.0
|
||||
github.com/melbahja/goph v1.2.1
|
||||
github.com/mikesmitty/edkey v0.0.0-20170222072505-3356ea4e686a
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/spf13/cobra v1.2.1
|
||||
github.com/spf13/viper v1.8.1
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97
|
||||
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914
|
||||
google.golang.org/api v0.52.0
|
||||
github.com/spf13/cobra v1.3.0
|
||||
github.com/spf13/viper v1.10.1
|
||||
google.golang.org/api v0.65.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.89.0 // indirect
|
||||
github.com/VividCortex/ewma v1.2.0 // indirect
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
|
||||
github.com/fatih/color v1.12.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.0.5 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.1.1 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/juju/ansiterm v0.0.0-20210706145210-9283cdf370b5 // indirect
|
||||
github.com/jwalton/go-supportscolor v1.0.0 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/lunixbochs/vtclean v1.0.0 // indirect
|
||||
github.com/magiconair/properties v1.8.5 // indirect
|
||||
github.com/mattn/go-colorable v0.1.8 // indirect
|
||||
github.com/mattn/go-isatty v0.0.13 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.1 // indirect
|
||||
github.com/pelletier/go-toml v1.9.3 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.3 // indirect
|
||||
github.com/pelletier/go-toml v1.9.4
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pkg/sftp v1.13.2 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/spf13/afero v1.6.0 // indirect
|
||||
github.com/spf13/cast v1.4.0 // indirect
|
||||
github.com/spf13/afero v1.8.0 // indirect
|
||||
github.com/spf13/cast v1.4.1 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/subosito/gotenv v1.2.0 // indirect
|
||||
go.opencensus.io v0.23.0 // indirect
|
||||
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420 // indirect
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect
|
||||
golang.org/x/text v0.3.6 // indirect
|
||||
golang.org/x/net v0.0.0-20220111093109-d55c255bac03 // indirect
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20210729151513-df9385d47c1b // indirect
|
||||
google.golang.org/grpc v1.39.0 // indirect
|
||||
google.golang.org/protobuf v1.27.1 // indirect
|
||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||
google.golang.org/grpc v1.43.0 // indirect
|
||||
gopkg.in/ini.v1 v1.66.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute v1.0.0 // indirect
|
||||
github.com/godbus/dbus/v5 v5.0.6 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/zeebo/errs v1.2.2 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220111164026-67b88f271998 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/antonmedv/expr v1.9.0
|
||||
github.com/coreos/go-systemd/v22 v22.3.2
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
google.golang.org/protobuf v1.27.1
|
||||
storj.io/drpc v0.0.26
|
||||
)
|
||||
|
||||
377
go.sum
377
go.sum
@@ -3,6 +3,7 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||
@@ -15,25 +16,32 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
||||
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
|
||||
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
|
||||
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
|
||||
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
||||
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
||||
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
|
||||
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
|
||||
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
|
||||
cloud.google.com/go v0.88.0/go.mod h1:dnKwfYbP9hQhefiUvpbcAyoGSHUrOxR20JVElLiUvEY=
|
||||
cloud.google.com/go v0.89.0 h1:ZT4GU+y59fC95Mfdn2RtxuzN2gc69dzlVevQK8Ykyqs=
|
||||
cloud.google.com/go v0.89.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
|
||||
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
|
||||
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
|
||||
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
|
||||
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
|
||||
cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM=
|
||||
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
|
||||
cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
|
||||
cloud.google.com/go/compute v1.0.0 h1:SJYBzih8Jj9EUm6IDirxKG0I0AGWduhtb6BmdqWarw4=
|
||||
cloud.google.com/go/compute v1.0.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||
cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
@@ -43,15 +51,22 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
|
||||
github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
|
||||
github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=
|
||||
github.com/alitto/pond v1.5.1 h1:HwOA8M/QB8lpkqzj8lnCEvC+44lHbPrrD5qHaJ9HRYI=
|
||||
github.com/alitto/pond v1.5.1/go.mod h1:LPLCPu5q4FAhvZsJB9OsNcXE+pUMu7lwf7fzPZH0HPs=
|
||||
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
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/alitto/pond v1.7.0 h1:o/V4qQmhT6EOXkg1PdCz2tF9X3RjMTU6hhlHq1k2t1g=
|
||||
github.com/alitto/pond v1.7.0/go.mod h1:/TYBaKCXvQ8Qiy3TfOoKeu6K7AVAhMpvu4itSpGdws0=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/antonmedv/expr v1.9.0 h1:j4HI3NHEdgDnN9p6oI6Ndr0G5QryMY0FNxT4ONrFDGU=
|
||||
github.com/antonmedv/expr v1.9.0/go.mod h1:5qsM3oLGDND7sDmQGDXHkYfkjYMUX14qsgqmHhwGEk8=
|
||||
github.com/apex/log v1.9.0 h1:FHtw/xuaM8AgmvDDTI9fiwoAL25Sq2cxojnZICUU8l0=
|
||||
github.com/apex/log v1.9.0/go.mod h1:m82fZlWIuiWzWP04XCTXmnX0xRkYYbCdYn8jbJeLBEA=
|
||||
github.com/apex/logs v1.0.0/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo=
|
||||
@@ -59,28 +74,42 @@ github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy
|
||||
github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
|
||||
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.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cheggaaa/pb/v3 v3.0.8 h1:bC8oemdChbke2FHIIGy9mn4DPJ2caZYQnfbRqwmdCoA=
|
||||
github.com/cheggaaa/pb/v3 v3.0.8/go.mod h1:UICbiLec/XO6Hw6k+BHEtHeQFzzBH4i2/qk/ow1EJTA=
|
||||
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
|
||||
github.com/census-instrumentation/opencensus-proto v0.3.0/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/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||
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/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -91,20 +120,31 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc=
|
||||
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
|
||||
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
||||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||
github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
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-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-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
|
||||
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
@@ -169,163 +209,185 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf
|
||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210715191844-86eeefc3e471/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
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 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
||||
github.com/googleapis/gax-go/v2 v2.1.1 h1:dp3bWCh+PPO1zjRRiCSczJav13sBvG4UhNyVTa1KqdU=
|
||||
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
|
||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
|
||||
github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1/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-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
|
||||
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
|
||||
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/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/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
|
||||
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
|
||||
github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
|
||||
github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
|
||||
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
|
||||
github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU=
|
||||
github.com/juju/ansiterm v0.0.0-20210706145210-9283cdf370b5 h1:Q5klzs6BL5FkassBX65t+KkG0XjYcjxEm+GNcQAsuaw=
|
||||
github.com/juju/ansiterm v0.0.0-20210706145210-9283cdf370b5/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU=
|
||||
github.com/jwalton/gchalk v1.0.3 h1:Eo/Ig+8efrpVpNI1ZoiJ+fLFHGXH7Q7+pBzOpG4Mib4=
|
||||
github.com/jwalton/gchalk v1.0.3/go.mod h1:kmvsubrIhnHSklat2ZWNj7zlLs3SS2wGNgsBVPtill4=
|
||||
github.com/jwalton/go-supportscolor v1.0.0 h1:Do3OE2y/iUibg79+QhkRE6G2evYKEv2bwi6sGs8Nd7s=
|
||||
github.com/jwalton/go-supportscolor v1.0.0/go.mod h1:hFVUAZV2cWg+WFFC4v8pT2X/S2qUUBYMioBD9AINXGs=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
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/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8=
|
||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
|
||||
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
|
||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/manifoldco/promptui v0.8.0 h1:R95mMF+McvXZQ7j1g8ucVZE1gLP3Sv6j9vlF9kyRqQo=
|
||||
github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
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.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
|
||||
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/melbahja/goph v1.2.1 h1:msPxbLxf1PnbxRQGhv9mVqm7T16tPo3wqLWah0hJhKQ=
|
||||
github.com/melbahja/goph v1.2.1/go.mod h1:y+wS4c0UtZOLSwNz6ktaGiyUeYZBeT1e8PiSz+YK77o=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mikesmitty/edkey v0.0.0-20170222072505-3356ea4e686a h1:eU8j/ClY2Ty3qdHnn0TyW3ivFoPC/0F1gQZz8yTxbbE=
|
||||
github.com/mikesmitty/edkey v0.0.0-20170222072505-3356ea4e686a/go.mod h1:v8eSC2SMp9/7FTKUncp7fH9IwPfw+ysMObcEz5FWheQ=
|
||||
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/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
|
||||
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
|
||||
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
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/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
|
||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
|
||||
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
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/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ=
|
||||
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
|
||||
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
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/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||
github.com/pkg/sftp v1.12.0/go.mod h1:fUqqXB5vEgVCZ131L+9say31RAri6aF6KDViawhxKK8=
|
||||
github.com/pkg/sftp v1.13.2 h1:taJnKntsWgU+qae21Rx52lIwndAdKrj0mfUNQsz1z4Q=
|
||||
github.com/pkg/sftp v1.13.2/go.mod h1:LzqnAvaD5TWeNBsZpfKxSYn1MbjWwOsCIAFFJbpIsK8=
|
||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/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.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/rivo/tview v0.0.0-20200219210816-cd38d7432498/go.mod h1:6lkG1x+13OShEf0EaOCaTQYyB7d5nSbb181KtjlS+84=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig=
|
||||
github.com/sanity-io/litter v1.2.0/go.mod h1:JF6pZUFgu2Q0sBZ+HSV35P8TVPI1TTzEwyu9FXAw2W4=
|
||||
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/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/assertions v1.0.0 h1:UVQPSSmc3qtTi+zPPkCXvZX9VvW/xT/NsRvKfwY81a8=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
|
||||
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs=
|
||||
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
|
||||
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.4.0 h1:WhlbjwB9EGCc8W5Rxdkus+wmH2ASRwwTJk6tgHKwdqQ=
|
||||
github.com/spf13/cast v1.4.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw=
|
||||
github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
|
||||
github.com/spf13/afero v1.8.0 h1:5MmtuhAgYeU6qpa7w7bP0dv6MBYuup0vekhSpSkoq60=
|
||||
github.com/spf13/afero v1.8.0/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo=
|
||||
github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
|
||||
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v1.3.0 h1:R7cSvGu+Vv+qX0gW5R/85dx2kmmJT5z5NM8ifdYjdn0=
|
||||
github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44=
|
||||
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
|
||||
github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM=
|
||||
github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk=
|
||||
github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU=
|
||||
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/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
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=
|
||||
@@ -342,14 +404,19 @@ github.com/tj/go-buffer v1.1.0/go.mod h1:iyiJpfFcR2B9sXu7KvjbT9fpM4mOelRSDTbntVj
|
||||
github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0=
|
||||
github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao=
|
||||
github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4=
|
||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
|
||||
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
|
||||
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
|
||||
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
||||
github.com/zeebo/errs v1.2.2 h1:5NFypMTuSdoySVTqlNs1dEoU21QVamMQJxW/Fii5O7g=
|
||||
github.com/zeebo/errs v1.2.2/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
|
||||
go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
|
||||
go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs=
|
||||
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=
|
||||
@@ -362,19 +429,19 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
||||
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/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -410,11 +477,12 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
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-20181201002055-351d144fa1fc/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-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
@@ -422,9 +490,11 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
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-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
@@ -443,13 +513,17 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420 h1:a8jGStKg0XqKDlKqjLrXn0ioF5MH36pT7Z0BRTqLhbk=
|
||||
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
|
||||
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220111093109-d55c255bac03 h1:0FB83qp0AzVJm+0wcIlauAjJ+tNdh7jLuacRYCIVv7s=
|
||||
golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
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=
|
||||
@@ -461,11 +535,13 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ
|
||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914 h1:3B43BWw0xEBsLZ/NO1VALz6fppU3481pik+2Ksv45z8=
|
||||
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -479,26 +555,32 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-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-20181122145206-62eef0e2fa9b/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-20190215142949-d0b11bdaac8a/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-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-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -514,10 +596,11 @@ golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201218084310-7d0127a74742/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -529,14 +612,22 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320 h1:0jf+tOCoZ3LyutmCOWpVni1chK4VfFLhRsDK7MhqGRY=
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -544,8 +635,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
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=
|
||||
@@ -555,7 +647,6 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
|
||||
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=
|
||||
@@ -563,9 +654,9 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw
|
||||
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-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
@@ -598,6 +689,7 @@ golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4f
|
||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
@@ -630,14 +722,20 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q
|
||||
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
|
||||
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
|
||||
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
|
||||
google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
|
||||
google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
|
||||
google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
|
||||
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
|
||||
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
|
||||
google.golang.org/api v0.52.0 h1:m5FLEd6dp5CU1F0tMWyqDi2XjchviIz8ntzOSz7w8As=
|
||||
google.golang.org/api v0.52.0/go.mod h1:Him/adpjt0sxtkWViy0b6xyKW/SD71CwdJ7HqJo7SrU=
|
||||
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
|
||||
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
|
||||
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
|
||||
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
|
||||
google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU=
|
||||
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
|
||||
google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw=
|
||||
google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
|
||||
google.golang.org/api v0.65.0 h1:MTW9c+LIBAbwoS1Gb+YV7NjFBt2f7GtAS5hIzh2NjgQ=
|
||||
google.golang.org/api v0.65.0/go.mod h1:ArYhxgGadlWmqO1IqVujw6Cs8IdD33bTmzKo2Sh+cbg=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
@@ -681,7 +779,9 @@ google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6D
|
||||
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
@@ -693,11 +793,26 @@ google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxH
|
||||
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
|
||||
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
|
||||
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
|
||||
google.golang.org/genproto v0.0.0-20210721163202-f1cecdd8b78a/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
||||
google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
||||
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
||||
google.golang.org/genproto v0.0.0-20210729151513-df9385d47c1b h1:4xoALQmXxqVdDdLimpPyPeDdsJzo+nFTJw9euAMpqgM=
|
||||
google.golang.org/genproto v0.0.0-20210729151513-df9385d47c1b/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
||||
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
||||
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
|
||||
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220111164026-67b88f271998 h1:g/x+MYjJYDEP3OBCYYmwIbt4x6k3gryb+ohyOR7PXfI=
|
||||
google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
@@ -717,12 +832,16 @@ google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA5
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.39.0 h1:Klz8I9kdtkIN6EpHHUOMLCYhTn/2WAe5a0s1hcBkdTI=
|
||||
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||
google.golang.org/grpc v1.43.0 h1:Eeu7bZtDZ2DpRCsLhUlcrLnvYaMK1Gz86a+hMVvELmM=
|
||||
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
@@ -738,18 +857,22 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
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 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
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/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI=
|
||||
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
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.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
@@ -767,3 +890,5 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
storj.io/drpc v0.0.26 h1:T6jJzjby7QUa/2XHR1qMxTCENpDHEw4/o+kfDfZQqQI=
|
||||
storj.io/drpc v0.0.26/go.mod h1:ofQUDPQbbIymRDKE0tms48k8bLP5Y+dsI9CbXGv3gko=
|
||||
|
||||
17
init/portal.service
Normal file
17
init/portal.service
Normal file
@@ -0,0 +1,17 @@
|
||||
[Unit]
|
||||
Description=Portal
|
||||
Documentation=https://speedrun.sh
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
ExecStart=/usr/local/bin/portal
|
||||
KillMode=process
|
||||
KillSignal=SIGINT
|
||||
Restart=on-failure
|
||||
RestartSec=2
|
||||
TasksMax=infinity
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
124
key/key.go
124
key/key.go
@@ -1,124 +0,0 @@
|
||||
package key
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/gob"
|
||||
"encoding/pem"
|
||||
"io/ioutil"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/melbahja/goph"
|
||||
"github.com/mikesmitty/edkey"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
const Comment = "speedrun"
|
||||
|
||||
type Key struct {
|
||||
User string
|
||||
Comment string
|
||||
Key []byte
|
||||
}
|
||||
|
||||
func New() (*Key, error) {
|
||||
key := &Key{}
|
||||
_, rawKey, err := ed25519.GenerateKey(rand.Reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pemKey := &pem.Block{
|
||||
Type: "OPENSSH PRIVATE KEY",
|
||||
Bytes: edkey.MarshalED25519PrivateKey(rawKey),
|
||||
}
|
||||
privateKey := pem.EncodeToMemory(pemKey)
|
||||
key.Key = privateKey
|
||||
|
||||
user, err := user.Current()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key.User = user.Username
|
||||
key.Comment = Comment
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func Read(path string) (*Key, error) {
|
||||
cleanPath := filepath.Clean(path)
|
||||
absPath, err := filepath.Abs(cleanPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
file, err := ioutil.ReadFile(absPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b64Result, err := base64.StdEncoding.DecodeString(string(file))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
key := &Key{}
|
||||
buf := bytes.NewBuffer(b64Result)
|
||||
enc := gob.NewDecoder(buf)
|
||||
|
||||
err = enc.Decode(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return key, nil
|
||||
|
||||
}
|
||||
|
||||
func (k *Key) Write(path string) error {
|
||||
var buf bytes.Buffer
|
||||
enc := gob.NewEncoder(&buf)
|
||||
err := enc.Encode(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b64Result := base64.StdEncoding.EncodeToString(buf.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debugf("Writing priviate key to %s", path)
|
||||
err = ioutil.WriteFile(path, []byte(b64Result), 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (k *Key) MarshalAuthorizedKey() (string, error) {
|
||||
privKey, err := ssh.ParsePrivateKey(k.Key)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
authorizedKey := ssh.MarshalAuthorizedKey(privKey.PublicKey())
|
||||
trimmedKey := strings.TrimSuffix(string(authorizedKey), "\n")
|
||||
return trimmedKey, nil
|
||||
}
|
||||
|
||||
func (k *Key) GetAuth() (goph.Auth, error) {
|
||||
privKey, err := ssh.ParsePrivateKey(k.Key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return goph.Auth{
|
||||
ssh.PublicKeys(privKey),
|
||||
}, nil
|
||||
}
|
||||
16
main.go
16
main.go
@@ -1,16 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"speedrun/cmd"
|
||||
|
||||
"github.com/apex/log"
|
||||
loghandler "github.com/apex/log/handlers/cli"
|
||||
)
|
||||
|
||||
func main() {
|
||||
h := loghandler.New(os.Stdout)
|
||||
h.Padding = 0
|
||||
log.SetHandler(h)
|
||||
cmd.Execute()
|
||||
}
|
||||
@@ -1,190 +0,0 @@
|
||||
package marathon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"speedrun/cloud"
|
||||
"speedrun/colors"
|
||||
"speedrun/key"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/alitto/pond"
|
||||
"github.com/apex/log"
|
||||
"github.com/cheggaaa/pb/v3"
|
||||
"github.com/melbahja/goph"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/spf13/viper"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// Marathon represents the instance of the execution of a command against a number of target servers
|
||||
type Marathon struct {
|
||||
sync.Mutex
|
||||
errors map[string]error
|
||||
failures map[string]string
|
||||
successes map[string]string
|
||||
Command string
|
||||
Timeout time.Duration
|
||||
Concurrency int
|
||||
}
|
||||
|
||||
// New creates a new instance of the Marathon type
|
||||
func New(command string, timeout time.Duration, concurrency int) *Marathon {
|
||||
r := Marathon{
|
||||
errors: make(map[string]error),
|
||||
failures: make(map[string]string),
|
||||
successes: make(map[string]string),
|
||||
Command: command,
|
||||
Timeout: timeout,
|
||||
Concurrency: concurrency,
|
||||
}
|
||||
|
||||
return &r
|
||||
}
|
||||
|
||||
// Run runs a given command on servers in the addresses list
|
||||
func (m *Marathon) Run(instances []cloud.Instance, key *key.Key, ignoreFingerprint bool) error {
|
||||
auth, err := key.GetAuth()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = checkHostsFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cb := verifyHost
|
||||
if ignoreFingerprint {
|
||||
cb = ssh.InsecureIgnoreHostKey()
|
||||
}
|
||||
|
||||
pool := pond.New(m.Concurrency, 10000)
|
||||
|
||||
bar := pb.New(len(instances))
|
||||
lvl, err := log.ParseLevel(viper.GetString("loglevel"))
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't parse log level: %s", err)
|
||||
}
|
||||
|
||||
if lvl > 0 {
|
||||
bar.SetMaxWidth(1)
|
||||
bar.SetTemplateString(fmt.Sprintf("%s Running [%s]: {{counters . }}", colors.Blue("•"), colors.Purple(m.Command)))
|
||||
bar.Start()
|
||||
}
|
||||
|
||||
for _, i := range instances {
|
||||
instance := i
|
||||
log.Debugf("Adding %s to the queue", instance.Name)
|
||||
pool.Submit(func() {
|
||||
var client *goph.Client
|
||||
var err error
|
||||
|
||||
client, err = goph.NewConn(&goph.Config{
|
||||
User: key.User,
|
||||
Addr: instance.Address,
|
||||
Port: 22,
|
||||
Auth: auth,
|
||||
Callback: cb,
|
||||
Timeout: m.Timeout,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.WithField("host", instance.Name).Debugf("Error encountered while trying to connect: %s", err)
|
||||
m.Lock()
|
||||
bar.Increment()
|
||||
m.errors[instance.Name] = err
|
||||
m.Unlock()
|
||||
return
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
out, err := client.Run(m.Command)
|
||||
if err != nil {
|
||||
m.Lock()
|
||||
bar.Increment()
|
||||
m.failures[instance.Name] = formatOutput(string(out))
|
||||
m.Unlock()
|
||||
return
|
||||
}
|
||||
m.Lock()
|
||||
bar.Increment()
|
||||
m.successes[instance.Name] = formatOutput(string(out))
|
||||
m.Unlock()
|
||||
})
|
||||
}
|
||||
pool.StopAndWait()
|
||||
bar.Finish()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VerifyHost chekcks that the remote host's fingerprint matches the know one to avoid MITM.
|
||||
// If the host is new the fingerprint is added to known hostss file
|
||||
func verifyHost(host string, remote net.Addr, key ssh.PublicKey) error {
|
||||
home, err := homedir.Dir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
knownhosts := filepath.Join(home, ".speedrun", "known_hosts")
|
||||
|
||||
hostFound, err := goph.CheckKnownHost(host, remote, key, knownhosts)
|
||||
if hostFound && err != nil {
|
||||
log.Debugf("Host fingerprint known")
|
||||
return err
|
||||
}
|
||||
|
||||
if !hostFound && err != nil {
|
||||
if err.Error() == "knownhosts: key is unknown" {
|
||||
log.Debugf("Adding host %s to ~/.speedrun/known_hosts", host)
|
||||
return goph.AddKnownHost(host, remote, key, knownhosts)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if hostFound {
|
||||
log.Debugf("Host %s is already known", host)
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkHostsFile() error {
|
||||
home, err := homedir.Dir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
knownhosts := filepath.Join(home, ".speedrun", "known_hosts")
|
||||
|
||||
if _, err := os.Stat(knownhosts); os.IsNotExist(err) {
|
||||
_, err = os.Create(knownhosts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// PrintResult prints the results of the ssh command run
|
||||
func (m *Marathon) PrintResult(failures bool) {
|
||||
if !failures {
|
||||
for host, msg := range m.successes {
|
||||
fmt.Printf(" %s:\n%s\n", colors.Green(host), colors.White(msg))
|
||||
}
|
||||
}
|
||||
|
||||
for host, msg := range m.failures {
|
||||
fmt.Printf(" %s:\n%s\n", colors.Yellow(host), colors.White(msg))
|
||||
}
|
||||
|
||||
for host, msg := range m.errors {
|
||||
fmt.Printf(" %s:\n %s\n\n", colors.Red(host), colors.White(msg.Error()))
|
||||
}
|
||||
fmt.Printf("%s: %d\n%s: %d\n%s: %d\n", colors.Green("Success"), len(m.successes), colors.Yellow("Failure"), len(m.failures), colors.Red("Error"), len(m.errors))
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package marathon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func formatOutput(body string) string {
|
||||
f := []string{}
|
||||
for _, line := range strings.Split(body, "\n") {
|
||||
line = fmt.Sprintf(" %s", line)
|
||||
f = append(f, line)
|
||||
}
|
||||
|
||||
f = append(f[:len(f)-1], "")
|
||||
return strings.Join(f, "\n")
|
||||
}
|
||||
90
pkg/common/cryptoutil/tls.go
Normal file
90
pkg/common/cryptoutil/tls.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package cryptoutil
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func InsecureTLSConfig() (*tls.Config, error) {
|
||||
publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
template := x509.Certificate{SerialNumber: big.NewInt(1)}
|
||||
certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey, privateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bytes, err := x509.MarshalPKCS8PrivateKey(privateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keyPEM := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: bytes})
|
||||
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
|
||||
|
||||
tlsCert, err := tls.X509KeyPair(certPEM, keyPEM)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &tls.Config{
|
||||
MinVersion: tls.VersionTLS13,
|
||||
CurvePreferences: []tls.CurveID{tls.X25519},
|
||||
CipherSuites: []uint16{tls.TLS_CHACHA20_POLY1305_SHA256},
|
||||
Certificates: []tls.Certificate{tlsCert},
|
||||
InsecureSkipVerify: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ClientTLSConfig(caPath, certPath, keyPath string) (*tls.Config, error) {
|
||||
caCert, err := ioutil.ReadFile(caPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
caCertPool := x509.NewCertPool()
|
||||
caCertPool.AppendCertsFromPEM(caCert)
|
||||
|
||||
cert, err := tls.LoadX509KeyPair(certPath, keyPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &tls.Config{
|
||||
MinVersion: tls.VersionTLS13,
|
||||
CurvePreferences: []tls.CurveID{tls.X25519},
|
||||
CipherSuites: []uint16{tls.TLS_CHACHA20_POLY1305_SHA256},
|
||||
Certificates: []tls.Certificate{cert},
|
||||
RootCAs: caCertPool,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ServerTLSConfig(caPath, certPath, keyPath string) (*tls.Config, error) {
|
||||
caCert, err := ioutil.ReadFile(caPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
caCertPool := x509.NewCertPool()
|
||||
caCertPool.AppendCertsFromPEM(caCert)
|
||||
|
||||
cert, err := tls.LoadX509KeyPair(certPath, keyPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &tls.Config{
|
||||
MinVersion: tls.VersionTLS13,
|
||||
CurvePreferences: []tls.CurveID{tls.X25519},
|
||||
CipherSuites: []uint16{tls.TLS_CHACHA20_POLY1305_SHA256},
|
||||
Certificates: []tls.Certificate{cert},
|
||||
ClientCAs: caCertPool,
|
||||
ClientAuth: tls.RequireAndVerifyClientCert,
|
||||
}, nil
|
||||
}
|
||||
28
pkg/portal/command.go
Normal file
28
pkg/portal/command.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package portal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/apex/log"
|
||||
|
||||
"github.com/speedrunsh/speedrun/proto/portal"
|
||||
)
|
||||
|
||||
func (s *Server) RunCommand(ctx context.Context, in *portal.CommandRequest) (*portal.CommandResponse, error) {
|
||||
fields := log.Fields{
|
||||
"context": "command",
|
||||
}
|
||||
log := log.WithFields(fields)
|
||||
|
||||
log.Debugf("Received command: %s %s", in.GetName(), in.GetArgs())
|
||||
cmd := exec.Command(in.GetName(), in.GetArgs()...)
|
||||
stdout, err := cmd.CombinedOutput()
|
||||
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
return &portal.CommandResponse{Message: strings.TrimSpace(string(stdout))}, nil
|
||||
}
|
||||
7
pkg/portal/server.go
Normal file
7
pkg/portal/server.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package portal
|
||||
|
||||
import "github.com/speedrunsh/speedrun/proto/portal"
|
||||
|
||||
type Server struct {
|
||||
portal.DRPCPortalUnimplementedServer
|
||||
}
|
||||
158
pkg/portal/service.go
Normal file
158
pkg/portal/service.go
Normal file
@@ -0,0 +1,158 @@
|
||||
package portal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/coreos/go-systemd/v22/dbus"
|
||||
"github.com/speedrunsh/speedrun/proto/portal"
|
||||
)
|
||||
|
||||
func (s *Server) ServiceRestart(ctx context.Context, service *portal.ServiceRequest) (*portal.ServiceResponse, error) {
|
||||
fields := log.Fields{
|
||||
"context": "service",
|
||||
"command": "restart",
|
||||
"name": service.GetName(),
|
||||
}
|
||||
log := log.WithFields(fields)
|
||||
log.Debug("Received service restart request")
|
||||
|
||||
conn, err := dbus.NewWithContext(ctx)
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
responseChan := make(chan string, 1)
|
||||
serviceName := fmt.Sprintf("%s.service", service.GetName())
|
||||
_, err = conn.RestartUnitContext(ctx, serviceName, "replace", responseChan)
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := <-responseChan
|
||||
log.Debugf("Service restart result: %v", res)
|
||||
return &portal.ServiceResponse{State: portal.State_CHANGED, Message: strings.Title(res)}, nil
|
||||
}
|
||||
|
||||
func (s *Server) ServiceStop(ctx context.Context, service *portal.ServiceRequest) (*portal.ServiceResponse, error) {
|
||||
fields := log.Fields{
|
||||
"context": "service",
|
||||
"command": "stop",
|
||||
"name": service.GetName(),
|
||||
}
|
||||
log := log.WithFields(fields)
|
||||
log.Debug("Received service stop request")
|
||||
|
||||
conn, err := dbus.NewWithContext(ctx)
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
responseChan := make(chan string, 1)
|
||||
serviceName := fmt.Sprintf("%s.service", service.GetName())
|
||||
list, err := conn.ListUnitsByNamesContext(ctx, []string{serviceName})
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
log.Debugf("Fetched service list by name: %v", list)
|
||||
if list[0].ActiveState == "inactive" {
|
||||
return &portal.ServiceResponse{State: portal.State_UNCHANGED, Message: "Service already stopped"}, nil
|
||||
}
|
||||
|
||||
_, err = conn.StopUnitContext(ctx, serviceName, "replace", responseChan)
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := <-responseChan
|
||||
log.Debugf("Service stop result: %v", res)
|
||||
return &portal.ServiceResponse{State: portal.State_CHANGED, Message: strings.Title(res)}, nil
|
||||
|
||||
}
|
||||
|
||||
func (s *Server) ServiceStart(ctx context.Context, service *portal.ServiceRequest) (*portal.ServiceResponse, error) {
|
||||
fields := log.Fields{
|
||||
"context": "service",
|
||||
"command": "start",
|
||||
"name": service.GetName(),
|
||||
}
|
||||
log := log.WithFields(fields)
|
||||
log.Debug("Received service start request")
|
||||
|
||||
conn, err := dbus.NewWithContext(ctx)
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
responseChan := make(chan string, 1)
|
||||
serviceName := fmt.Sprintf("%s.service", service.GetName())
|
||||
list, err := conn.ListUnitsByNamesContext(ctx, []string{serviceName})
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
log.Debugf("Fetched service list by name: %v", list)
|
||||
if list[0].ActiveState == "active" {
|
||||
return &portal.ServiceResponse{State: portal.State_UNCHANGED, Message: "Service already running"}, nil
|
||||
}
|
||||
|
||||
_, err = conn.StartUnitContext(ctx, serviceName, "replace", responseChan)
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := <-responseChan
|
||||
log.Debugf("Service start result: %v", res)
|
||||
return &portal.ServiceResponse{State: portal.State_CHANGED, Message: strings.Title(res)}, nil
|
||||
|
||||
}
|
||||
|
||||
func (s *Server) ServiceStatus(ctx context.Context, service *portal.ServiceRequest) (*portal.ServiceStatusResponse, error) {
|
||||
fields := log.Fields{
|
||||
"context": "service",
|
||||
"command": "status",
|
||||
"name": service.GetName(),
|
||||
}
|
||||
log := log.WithFields(fields)
|
||||
log.Debug("Received service status request")
|
||||
|
||||
conn, err := dbus.NewWithContext(ctx)
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
serviceName := fmt.Sprintf("%s.service", service.GetName())
|
||||
res, err := conn.ListUnitsByNamesContext(ctx, []string{serviceName})
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
log.Debugf("Fetched service list by name: %v", res[0])
|
||||
|
||||
if res[0].LoadState == "not-found" {
|
||||
log.Error("service not found")
|
||||
return nil, fmt.Errorf("service not found")
|
||||
}
|
||||
|
||||
return &portal.ServiceStatusResponse{
|
||||
State: portal.State_UNCHANGED,
|
||||
Activestate: res[0].ActiveState,
|
||||
Loadstate: res[0].LoadState,
|
||||
Substate: res[0].SubState,
|
||||
}, nil
|
||||
|
||||
}
|
||||
53
pkg/speedrun/cloud/google.go
Normal file
53
pkg/speedrun/cloud/google.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package cloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"google.golang.org/api/compute/v1"
|
||||
)
|
||||
|
||||
type GoogleClient struct {
|
||||
*compute.Service
|
||||
}
|
||||
|
||||
func NewGCPClient() (*GoogleClient, error) {
|
||||
var err error
|
||||
ctx := context.Background()
|
||||
|
||||
gce, err := compute.NewService(ctx)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("couldn't initialize GCP client: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &GoogleClient{gce}, nil
|
||||
}
|
||||
|
||||
// GetInstances returns a list of external IP addresses used for the SHH connection
|
||||
func (c *GoogleClient) GetInstances(project string) ([]Instance, error) {
|
||||
instances := []Instance{}
|
||||
listCall := c.Instances.AggregatedList(project).Fields("nextPageToken", "items(Name,NetworkInterfaces,Labels)")
|
||||
var ctx context.Context
|
||||
|
||||
listCall.Pages(ctx, func(list *compute.InstanceAggregatedList) error {
|
||||
for _, item := range list.Items {
|
||||
for _, instance := range item.Instances {
|
||||
i := Instance{
|
||||
Name: instance.Name,
|
||||
PrivateAddress: instance.NetworkInterfaces[0].NetworkIP,
|
||||
PublicAddress: instance.NetworkInterfaces[0].AccessConfigs[0].NatIP,
|
||||
Labels: instance.Labels,
|
||||
}
|
||||
instances = append(instances, i)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
_, err := listCall.Do()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return instances, nil
|
||||
}
|
||||
93
pkg/speedrun/cloud/instance.go
Normal file
93
pkg/speedrun/cloud/instance.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package cloud
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
|
||||
"github.com/antonmedv/expr"
|
||||
"github.com/apex/log"
|
||||
"github.com/speedrunsh/speedrun/pkg/common/cryptoutil"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type Instance struct {
|
||||
PublicAddress string
|
||||
PrivateAddress string
|
||||
Name string
|
||||
Labels map[string]string
|
||||
}
|
||||
|
||||
func (i Instance) GetAddress(private bool) string {
|
||||
if private {
|
||||
return i.PrivateAddress
|
||||
}
|
||||
|
||||
return i.PublicAddress
|
||||
}
|
||||
|
||||
func GetInstances(target string) ([]Instance, error) {
|
||||
project := viper.GetString("gcp.projectid")
|
||||
|
||||
gcpClient, err := NewGCPClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Info("Fetching instance list")
|
||||
instances, err := gcpClient.GetInstances(project)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
subset, err := filter(instances, target)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(subset) == 0 {
|
||||
return nil, fmt.Errorf("no instances found")
|
||||
}
|
||||
|
||||
return subset, nil
|
||||
}
|
||||
|
||||
func SetupTLS() (*tls.Config, error) {
|
||||
insecure := viper.GetBool("tls.insecure")
|
||||
caPath := viper.GetString("tls.ca")
|
||||
certPath := viper.GetString("tls.cert")
|
||||
keyPath := viper.GetString("tls.key")
|
||||
|
||||
if insecure {
|
||||
log.Warn("Using insecure TLS configuration, this should be avoided in production environments")
|
||||
return cryptoutil.InsecureTLSConfig()
|
||||
} else {
|
||||
return cryptoutil.ClientTLSConfig(caPath, certPath, keyPath)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func filter(instnces []Instance, target string) ([]Instance, error) {
|
||||
var subset []Instance
|
||||
|
||||
program, err := expr.Compile(target, expr.Env(Instance{}), expr.AsBool())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, instance := range instnces {
|
||||
output, err := expr.Run(program, instance)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
match, ok := output.(bool)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if match {
|
||||
subset = append(subset, instance)
|
||||
}
|
||||
}
|
||||
return subset, nil
|
||||
}
|
||||
10
proto/Makefile
Normal file
10
proto/Makefile
Normal file
@@ -0,0 +1,10 @@
|
||||
.PHONY: requirements portal
|
||||
|
||||
all: requirements portal
|
||||
|
||||
requirements:
|
||||
@go mod download
|
||||
@go install storj.io/drpc/cmd/protoc-gen-go-drpc@latest
|
||||
|
||||
portal:
|
||||
protoc --go_out=paths=source_relative:. --go-drpc_out=paths=source_relative:. portal/*.proto
|
||||
687
proto/portal/portal.pb.go
Normal file
687
proto/portal/portal.pb.go
Normal file
@@ -0,0 +1,687 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.17.3
|
||||
// source: portal/portal.proto
|
||||
|
||||
package portal
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type State int32
|
||||
|
||||
const (
|
||||
State_UNKNOWN State = 0
|
||||
State_CHANGED State = 1
|
||||
State_UNCHANGED State = 2
|
||||
)
|
||||
|
||||
// Enum value maps for State.
|
||||
var (
|
||||
State_name = map[int32]string{
|
||||
0: "UNKNOWN",
|
||||
1: "CHANGED",
|
||||
2: "UNCHANGED",
|
||||
}
|
||||
State_value = map[string]int32{
|
||||
"UNKNOWN": 0,
|
||||
"CHANGED": 1,
|
||||
"UNCHANGED": 2,
|
||||
}
|
||||
)
|
||||
|
||||
func (x State) Enum() *State {
|
||||
p := new(State)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x State) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (State) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_portal_portal_proto_enumTypes[0].Descriptor()
|
||||
}
|
||||
|
||||
func (State) Type() protoreflect.EnumType {
|
||||
return &file_portal_portal_proto_enumTypes[0]
|
||||
}
|
||||
|
||||
func (x State) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use State.Descriptor instead.
|
||||
func (State) EnumDescriptor() ([]byte, []int) {
|
||||
return file_portal_portal_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
type CommandRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Args []string `protobuf:"bytes,2,rep,name=args,proto3" json:"args,omitempty"`
|
||||
}
|
||||
|
||||
func (x *CommandRequest) Reset() {
|
||||
*x = CommandRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_portal_portal_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *CommandRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*CommandRequest) ProtoMessage() {}
|
||||
|
||||
func (x *CommandRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_portal_portal_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use CommandRequest.ProtoReflect.Descriptor instead.
|
||||
func (*CommandRequest) Descriptor() ([]byte, []int) {
|
||||
return file_portal_portal_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *CommandRequest) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *CommandRequest) GetArgs() []string {
|
||||
if x != nil {
|
||||
return x.Args
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type CommandResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
State State `protobuf:"varint,1,opt,name=state,proto3,enum=portal.State" json:"state,omitempty"`
|
||||
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
|
||||
}
|
||||
|
||||
func (x *CommandResponse) Reset() {
|
||||
*x = CommandResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_portal_portal_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *CommandResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*CommandResponse) ProtoMessage() {}
|
||||
|
||||
func (x *CommandResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_portal_portal_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use CommandResponse.ProtoReflect.Descriptor instead.
|
||||
func (*CommandResponse) Descriptor() ([]byte, []int) {
|
||||
return file_portal_portal_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *CommandResponse) GetState() State {
|
||||
if x != nil {
|
||||
return x.State
|
||||
}
|
||||
return State_UNKNOWN
|
||||
}
|
||||
|
||||
func (x *CommandResponse) GetMessage() string {
|
||||
if x != nil {
|
||||
return x.Message
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ServiceRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ServiceRequest) Reset() {
|
||||
*x = ServiceRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_portal_portal_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ServiceRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ServiceRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ServiceRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_portal_portal_proto_msgTypes[2]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ServiceRequest.ProtoReflect.Descriptor instead.
|
||||
func (*ServiceRequest) Descriptor() ([]byte, []int) {
|
||||
return file_portal_portal_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *ServiceRequest) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ServiceResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
State State `protobuf:"varint,1,opt,name=state,proto3,enum=portal.State" json:"state,omitempty"`
|
||||
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ServiceResponse) Reset() {
|
||||
*x = ServiceResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_portal_portal_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ServiceResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ServiceResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ServiceResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_portal_portal_proto_msgTypes[3]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ServiceResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ServiceResponse) Descriptor() ([]byte, []int) {
|
||||
return file_portal_portal_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *ServiceResponse) GetState() State {
|
||||
if x != nil {
|
||||
return x.State
|
||||
}
|
||||
return State_UNKNOWN
|
||||
}
|
||||
|
||||
func (x *ServiceResponse) GetMessage() string {
|
||||
if x != nil {
|
||||
return x.Message
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ServiceStatusResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
State State `protobuf:"varint,1,opt,name=state,proto3,enum=portal.State" json:"state,omitempty"`
|
||||
Loadstate string `protobuf:"bytes,2,opt,name=loadstate,proto3" json:"loadstate,omitempty"`
|
||||
Activestate string `protobuf:"bytes,3,opt,name=activestate,proto3" json:"activestate,omitempty"`
|
||||
Substate string `protobuf:"bytes,4,opt,name=substate,proto3" json:"substate,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ServiceStatusResponse) Reset() {
|
||||
*x = ServiceStatusResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_portal_portal_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ServiceStatusResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ServiceStatusResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ServiceStatusResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_portal_portal_proto_msgTypes[4]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ServiceStatusResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ServiceStatusResponse) Descriptor() ([]byte, []int) {
|
||||
return file_portal_portal_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *ServiceStatusResponse) GetState() State {
|
||||
if x != nil {
|
||||
return x.State
|
||||
}
|
||||
return State_UNKNOWN
|
||||
}
|
||||
|
||||
func (x *ServiceStatusResponse) GetLoadstate() string {
|
||||
if x != nil {
|
||||
return x.Loadstate
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ServiceStatusResponse) GetActivestate() string {
|
||||
if x != nil {
|
||||
return x.Activestate
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ServiceStatusResponse) GetSubstate() string {
|
||||
if x != nil {
|
||||
return x.Substate
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type CPUusageRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
}
|
||||
|
||||
func (x *CPUusageRequest) Reset() {
|
||||
*x = CPUusageRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_portal_portal_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *CPUusageRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*CPUusageRequest) ProtoMessage() {}
|
||||
|
||||
func (x *CPUusageRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_portal_portal_proto_msgTypes[5]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use CPUusageRequest.ProtoReflect.Descriptor instead.
|
||||
func (*CPUusageRequest) Descriptor() ([]byte, []int) {
|
||||
return file_portal_portal_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
type CPUusageResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Loadavg1 int32 `protobuf:"varint,1,opt,name=loadavg1,proto3" json:"loadavg1,omitempty"`
|
||||
Loadavg5 int32 `protobuf:"varint,2,opt,name=loadavg5,proto3" json:"loadavg5,omitempty"`
|
||||
Loadavg15 int32 `protobuf:"varint,3,opt,name=loadavg15,proto3" json:"loadavg15,omitempty"`
|
||||
}
|
||||
|
||||
func (x *CPUusageResponse) Reset() {
|
||||
*x = CPUusageResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_portal_portal_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *CPUusageResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*CPUusageResponse) ProtoMessage() {}
|
||||
|
||||
func (x *CPUusageResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_portal_portal_proto_msgTypes[6]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use CPUusageResponse.ProtoReflect.Descriptor instead.
|
||||
func (*CPUusageResponse) Descriptor() ([]byte, []int) {
|
||||
return file_portal_portal_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *CPUusageResponse) GetLoadavg1() int32 {
|
||||
if x != nil {
|
||||
return x.Loadavg1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *CPUusageResponse) GetLoadavg5() int32 {
|
||||
if x != nil {
|
||||
return x.Loadavg5
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *CPUusageResponse) GetLoadavg15() int32 {
|
||||
if x != nil {
|
||||
return x.Loadavg15
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var File_portal_portal_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_portal_portal_proto_rawDesc = []byte{
|
||||
0x0a, 0x13, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2f, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x22, 0x38, 0x0a,
|
||||
0x0e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
|
||||
0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
|
||||
0x09, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x22, 0x50, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x6d, 0x61,
|
||||
0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x73, 0x74,
|
||||
0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0d, 0x2e, 0x70, 0x6f, 0x72, 0x74,
|
||||
0x61, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12,
|
||||
0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x24, 0x0a, 0x0e, 0x53, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22,
|
||||
0x50, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x0e, 0x32, 0x0d, 0x2e, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65,
|
||||
0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61,
|
||||
0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
||||
0x65, 0x22, 0x98, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61,
|
||||
0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x73,
|
||||
0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0d, 0x2e, 0x70, 0x6f, 0x72,
|
||||
0x74, 0x61, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65,
|
||||
0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x20,
|
||||
0x0a, 0x0b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x73, 0x74, 0x61, 0x74, 0x65,
|
||||
0x12, 0x1a, 0x0a, 0x08, 0x73, 0x75, 0x62, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x08, 0x73, 0x75, 0x62, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x11, 0x0a, 0x0f,
|
||||
0x43, 0x50, 0x55, 0x75, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22,
|
||||
0x68, 0x0a, 0x10, 0x43, 0x50, 0x55, 0x75, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x61, 0x64, 0x61, 0x76, 0x67, 0x31, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x6c, 0x6f, 0x61, 0x64, 0x61, 0x76, 0x67, 0x31, 0x12,
|
||||
0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x61, 0x64, 0x61, 0x76, 0x67, 0x35, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x05, 0x52, 0x08, 0x6c, 0x6f, 0x61, 0x64, 0x61, 0x76, 0x67, 0x35, 0x12, 0x1c, 0x0a, 0x09, 0x6c,
|
||||
0x6f, 0x61, 0x64, 0x61, 0x76, 0x67, 0x31, 0x35, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09,
|
||||
0x6c, 0x6f, 0x61, 0x64, 0x61, 0x76, 0x67, 0x31, 0x35, 0x2a, 0x30, 0x0a, 0x05, 0x53, 0x74, 0x61,
|
||||
0x74, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12,
|
||||
0x0b, 0x0a, 0x07, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09,
|
||||
0x55, 0x4e, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x44, 0x10, 0x02, 0x32, 0x9e, 0x03, 0x0a, 0x06,
|
||||
0x50, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x12, 0x43, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x16, 0x2e, 0x70, 0x6f, 0x72, 0x74, 0x61,
|
||||
0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x17, 0x2e, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x0c, 0x53,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x16, 0x2e, 0x70, 0x6f,
|
||||
0x72, 0x74, 0x61, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x53, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x40,
|
||||
0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x6f, 0x70, 0x12, 0x16, 0x2e,
|
||||
0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x53,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
|
||||
0x12, 0x48, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75,
|
||||
0x73, 0x12, 0x16, 0x2e, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69,
|
||||
0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x70, 0x6f, 0x72, 0x74,
|
||||
0x61, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x0a, 0x52, 0x75,
|
||||
0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x16, 0x2e, 0x70, 0x6f, 0x72, 0x74, 0x61,
|
||||
0x6c, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x17, 0x2e, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
|
||||
0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x08, 0x43,
|
||||
0x50, 0x55, 0x75, 0x73, 0x61, 0x67, 0x65, 0x12, 0x17, 0x2e, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c,
|
||||
0x2e, 0x43, 0x50, 0x55, 0x75, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x18, 0x2e, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x43, 0x50, 0x55, 0x75, 0x73, 0x61,
|
||||
0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x2d, 0x5a, 0x2b,
|
||||
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x70, 0x65, 0x65, 0x64,
|
||||
0x72, 0x75, 0x6e, 0x73, 0x68, 0x2f, 0x73, 0x70, 0x65, 0x65, 0x64, 0x72, 0x75, 0x6e, 0x2f, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_portal_portal_proto_rawDescOnce sync.Once
|
||||
file_portal_portal_proto_rawDescData = file_portal_portal_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_portal_portal_proto_rawDescGZIP() []byte {
|
||||
file_portal_portal_proto_rawDescOnce.Do(func() {
|
||||
file_portal_portal_proto_rawDescData = protoimpl.X.CompressGZIP(file_portal_portal_proto_rawDescData)
|
||||
})
|
||||
return file_portal_portal_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_portal_portal_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_portal_portal_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
|
||||
var file_portal_portal_proto_goTypes = []interface{}{
|
||||
(State)(0), // 0: portal.State
|
||||
(*CommandRequest)(nil), // 1: portal.CommandRequest
|
||||
(*CommandResponse)(nil), // 2: portal.CommandResponse
|
||||
(*ServiceRequest)(nil), // 3: portal.ServiceRequest
|
||||
(*ServiceResponse)(nil), // 4: portal.ServiceResponse
|
||||
(*ServiceStatusResponse)(nil), // 5: portal.ServiceStatusResponse
|
||||
(*CPUusageRequest)(nil), // 6: portal.CPUusageRequest
|
||||
(*CPUusageResponse)(nil), // 7: portal.CPUusageResponse
|
||||
}
|
||||
var file_portal_portal_proto_depIdxs = []int32{
|
||||
0, // 0: portal.CommandResponse.state:type_name -> portal.State
|
||||
0, // 1: portal.ServiceResponse.state:type_name -> portal.State
|
||||
0, // 2: portal.ServiceStatusResponse.state:type_name -> portal.State
|
||||
3, // 3: portal.Portal.ServiceRestart:input_type -> portal.ServiceRequest
|
||||
3, // 4: portal.Portal.ServiceStart:input_type -> portal.ServiceRequest
|
||||
3, // 5: portal.Portal.ServiceStop:input_type -> portal.ServiceRequest
|
||||
3, // 6: portal.Portal.ServiceStatus:input_type -> portal.ServiceRequest
|
||||
1, // 7: portal.Portal.RunCommand:input_type -> portal.CommandRequest
|
||||
6, // 8: portal.Portal.CPUusage:input_type -> portal.CPUusageRequest
|
||||
4, // 9: portal.Portal.ServiceRestart:output_type -> portal.ServiceResponse
|
||||
4, // 10: portal.Portal.ServiceStart:output_type -> portal.ServiceResponse
|
||||
4, // 11: portal.Portal.ServiceStop:output_type -> portal.ServiceResponse
|
||||
5, // 12: portal.Portal.ServiceStatus:output_type -> portal.ServiceStatusResponse
|
||||
2, // 13: portal.Portal.RunCommand:output_type -> portal.CommandResponse
|
||||
7, // 14: portal.Portal.CPUusage:output_type -> portal.CPUusageResponse
|
||||
9, // [9:15] is the sub-list for method output_type
|
||||
3, // [3:9] is the sub-list for method input_type
|
||||
3, // [3:3] is the sub-list for extension type_name
|
||||
3, // [3:3] is the sub-list for extension extendee
|
||||
0, // [0:3] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_portal_portal_proto_init() }
|
||||
func file_portal_portal_proto_init() {
|
||||
if File_portal_portal_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_portal_portal_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*CommandRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_portal_portal_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*CommandResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_portal_portal_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ServiceRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_portal_portal_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ServiceResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_portal_portal_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ServiceStatusResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_portal_portal_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*CPUusageRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_portal_portal_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*CPUusageResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_portal_portal_proto_rawDesc,
|
||||
NumEnums: 1,
|
||||
NumMessages: 7,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_portal_portal_proto_goTypes,
|
||||
DependencyIndexes: file_portal_portal_proto_depIdxs,
|
||||
EnumInfos: file_portal_portal_proto_enumTypes,
|
||||
MessageInfos: file_portal_portal_proto_msgTypes,
|
||||
}.Build()
|
||||
File_portal_portal_proto = out.File
|
||||
file_portal_portal_proto_rawDesc = nil
|
||||
file_portal_portal_proto_goTypes = nil
|
||||
file_portal_portal_proto_depIdxs = nil
|
||||
}
|
||||
56
proto/portal/portal.proto
Normal file
56
proto/portal/portal.proto
Normal file
@@ -0,0 +1,56 @@
|
||||
syntax = "proto3";
|
||||
option go_package = "github.com/speedrunsh/speedrun/proto/portal";
|
||||
package portal;
|
||||
|
||||
enum State {
|
||||
UNKNOWN = 0;
|
||||
CHANGED = 1;
|
||||
UNCHANGED = 2;
|
||||
}
|
||||
|
||||
message CommandRequest {
|
||||
string name = 1;
|
||||
repeated string args = 2;
|
||||
}
|
||||
|
||||
message CommandResponse {
|
||||
State state = 1;
|
||||
string message = 2;
|
||||
}
|
||||
|
||||
message ServiceRequest {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
message ServiceResponse {
|
||||
State state = 1;
|
||||
string message = 2;
|
||||
}
|
||||
|
||||
message ServiceStatusResponse {
|
||||
State state = 1;
|
||||
string loadstate = 2;
|
||||
string activestate = 3;
|
||||
string substate = 4;
|
||||
}
|
||||
|
||||
message CPUusageRequest {}
|
||||
|
||||
message CPUusageResponse {
|
||||
int32 loadavg1 = 1;
|
||||
int32 loadavg5 = 2;
|
||||
int32 loadavg15 = 3;
|
||||
}
|
||||
|
||||
service Portal {
|
||||
rpc ServiceRestart(ServiceRequest) returns (ServiceResponse) {}
|
||||
rpc ServiceStart(ServiceRequest) returns (ServiceResponse) {}
|
||||
rpc ServiceStop(ServiceRequest) returns (ServiceResponse) {}
|
||||
rpc ServiceStatus(ServiceRequest) returns (ServiceStatusResponse) {}
|
||||
rpc RunCommand(CommandRequest) returns (CommandResponse) {}
|
||||
rpc CPUusage(CPUusageRequest) returns (CPUusageResponse) {
|
||||
} // --target group1 --target group2
|
||||
// rpc CPUProfile(CPUProfileRequest) returns (CPUProfileResponse) {}
|
||||
// rpc MemProfile(MemProfileRequest) returns (MemProfileResponse) {}
|
||||
// rpc EnsureMountedDisk()
|
||||
}
|
||||
311
proto/portal/portal_drpc.pb.go
Normal file
311
proto/portal/portal_drpc.pb.go
Normal file
@@ -0,0 +1,311 @@
|
||||
// Code generated by protoc-gen-go-drpc. DO NOT EDIT.
|
||||
// protoc-gen-go-drpc version: v0.0.26
|
||||
// source: portal/portal.proto
|
||||
|
||||
package portal
|
||||
|
||||
import (
|
||||
context "context"
|
||||
errors "errors"
|
||||
protojson "google.golang.org/protobuf/encoding/protojson"
|
||||
proto "google.golang.org/protobuf/proto"
|
||||
drpc "storj.io/drpc"
|
||||
drpcerr "storj.io/drpc/drpcerr"
|
||||
)
|
||||
|
||||
type drpcEncoding_File_portal_portal_proto struct{}
|
||||
|
||||
func (drpcEncoding_File_portal_portal_proto) Marshal(msg drpc.Message) ([]byte, error) {
|
||||
return proto.Marshal(msg.(proto.Message))
|
||||
}
|
||||
|
||||
func (drpcEncoding_File_portal_portal_proto) MarshalAppend(buf []byte, msg drpc.Message) ([]byte, error) {
|
||||
return proto.MarshalOptions{}.MarshalAppend(buf, msg.(proto.Message))
|
||||
}
|
||||
|
||||
func (drpcEncoding_File_portal_portal_proto) Unmarshal(buf []byte, msg drpc.Message) error {
|
||||
return proto.Unmarshal(buf, msg.(proto.Message))
|
||||
}
|
||||
|
||||
func (drpcEncoding_File_portal_portal_proto) JSONMarshal(msg drpc.Message) ([]byte, error) {
|
||||
return protojson.Marshal(msg.(proto.Message))
|
||||
}
|
||||
|
||||
func (drpcEncoding_File_portal_portal_proto) JSONUnmarshal(buf []byte, msg drpc.Message) error {
|
||||
return protojson.Unmarshal(buf, msg.(proto.Message))
|
||||
}
|
||||
|
||||
type DRPCPortalClient interface {
|
||||
DRPCConn() drpc.Conn
|
||||
|
||||
ServiceRestart(ctx context.Context, in *ServiceRequest) (*ServiceResponse, error)
|
||||
ServiceStart(ctx context.Context, in *ServiceRequest) (*ServiceResponse, error)
|
||||
ServiceStop(ctx context.Context, in *ServiceRequest) (*ServiceResponse, error)
|
||||
ServiceStatus(ctx context.Context, in *ServiceRequest) (*ServiceStatusResponse, error)
|
||||
RunCommand(ctx context.Context, in *CommandRequest) (*CommandResponse, error)
|
||||
CPUusage(ctx context.Context, in *CPUusageRequest) (*CPUusageResponse, error)
|
||||
}
|
||||
|
||||
type drpcPortalClient struct {
|
||||
cc drpc.Conn
|
||||
}
|
||||
|
||||
func NewDRPCPortalClient(cc drpc.Conn) DRPCPortalClient {
|
||||
return &drpcPortalClient{cc}
|
||||
}
|
||||
|
||||
func (c *drpcPortalClient) DRPCConn() drpc.Conn { return c.cc }
|
||||
|
||||
func (c *drpcPortalClient) ServiceRestart(ctx context.Context, in *ServiceRequest) (*ServiceResponse, error) {
|
||||
out := new(ServiceResponse)
|
||||
err := c.cc.Invoke(ctx, "/portal.Portal/ServiceRestart", drpcEncoding_File_portal_portal_proto{}, in, out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *drpcPortalClient) ServiceStart(ctx context.Context, in *ServiceRequest) (*ServiceResponse, error) {
|
||||
out := new(ServiceResponse)
|
||||
err := c.cc.Invoke(ctx, "/portal.Portal/ServiceStart", drpcEncoding_File_portal_portal_proto{}, in, out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *drpcPortalClient) ServiceStop(ctx context.Context, in *ServiceRequest) (*ServiceResponse, error) {
|
||||
out := new(ServiceResponse)
|
||||
err := c.cc.Invoke(ctx, "/portal.Portal/ServiceStop", drpcEncoding_File_portal_portal_proto{}, in, out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *drpcPortalClient) ServiceStatus(ctx context.Context, in *ServiceRequest) (*ServiceStatusResponse, error) {
|
||||
out := new(ServiceStatusResponse)
|
||||
err := c.cc.Invoke(ctx, "/portal.Portal/ServiceStatus", drpcEncoding_File_portal_portal_proto{}, in, out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *drpcPortalClient) RunCommand(ctx context.Context, in *CommandRequest) (*CommandResponse, error) {
|
||||
out := new(CommandResponse)
|
||||
err := c.cc.Invoke(ctx, "/portal.Portal/RunCommand", drpcEncoding_File_portal_portal_proto{}, in, out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *drpcPortalClient) CPUusage(ctx context.Context, in *CPUusageRequest) (*CPUusageResponse, error) {
|
||||
out := new(CPUusageResponse)
|
||||
err := c.cc.Invoke(ctx, "/portal.Portal/CPUusage", drpcEncoding_File_portal_portal_proto{}, in, out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
type DRPCPortalServer interface {
|
||||
ServiceRestart(context.Context, *ServiceRequest) (*ServiceResponse, error)
|
||||
ServiceStart(context.Context, *ServiceRequest) (*ServiceResponse, error)
|
||||
ServiceStop(context.Context, *ServiceRequest) (*ServiceResponse, error)
|
||||
ServiceStatus(context.Context, *ServiceRequest) (*ServiceStatusResponse, error)
|
||||
RunCommand(context.Context, *CommandRequest) (*CommandResponse, error)
|
||||
CPUusage(context.Context, *CPUusageRequest) (*CPUusageResponse, error)
|
||||
}
|
||||
|
||||
type DRPCPortalUnimplementedServer struct{}
|
||||
|
||||
func (s *DRPCPortalUnimplementedServer) ServiceRestart(context.Context, *ServiceRequest) (*ServiceResponse, error) {
|
||||
return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented)
|
||||
}
|
||||
|
||||
func (s *DRPCPortalUnimplementedServer) ServiceStart(context.Context, *ServiceRequest) (*ServiceResponse, error) {
|
||||
return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented)
|
||||
}
|
||||
|
||||
func (s *DRPCPortalUnimplementedServer) ServiceStop(context.Context, *ServiceRequest) (*ServiceResponse, error) {
|
||||
return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented)
|
||||
}
|
||||
|
||||
func (s *DRPCPortalUnimplementedServer) ServiceStatus(context.Context, *ServiceRequest) (*ServiceStatusResponse, error) {
|
||||
return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented)
|
||||
}
|
||||
|
||||
func (s *DRPCPortalUnimplementedServer) RunCommand(context.Context, *CommandRequest) (*CommandResponse, error) {
|
||||
return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented)
|
||||
}
|
||||
|
||||
func (s *DRPCPortalUnimplementedServer) CPUusage(context.Context, *CPUusageRequest) (*CPUusageResponse, error) {
|
||||
return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented)
|
||||
}
|
||||
|
||||
type DRPCPortalDescription struct{}
|
||||
|
||||
func (DRPCPortalDescription) NumMethods() int { return 6 }
|
||||
|
||||
func (DRPCPortalDescription) Method(n int) (string, drpc.Encoding, drpc.Receiver, interface{}, bool) {
|
||||
switch n {
|
||||
case 0:
|
||||
return "/portal.Portal/ServiceRestart", drpcEncoding_File_portal_portal_proto{},
|
||||
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
|
||||
return srv.(DRPCPortalServer).
|
||||
ServiceRestart(
|
||||
ctx,
|
||||
in1.(*ServiceRequest),
|
||||
)
|
||||
}, DRPCPortalServer.ServiceRestart, true
|
||||
case 1:
|
||||
return "/portal.Portal/ServiceStart", drpcEncoding_File_portal_portal_proto{},
|
||||
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
|
||||
return srv.(DRPCPortalServer).
|
||||
ServiceStart(
|
||||
ctx,
|
||||
in1.(*ServiceRequest),
|
||||
)
|
||||
}, DRPCPortalServer.ServiceStart, true
|
||||
case 2:
|
||||
return "/portal.Portal/ServiceStop", drpcEncoding_File_portal_portal_proto{},
|
||||
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
|
||||
return srv.(DRPCPortalServer).
|
||||
ServiceStop(
|
||||
ctx,
|
||||
in1.(*ServiceRequest),
|
||||
)
|
||||
}, DRPCPortalServer.ServiceStop, true
|
||||
case 3:
|
||||
return "/portal.Portal/ServiceStatus", drpcEncoding_File_portal_portal_proto{},
|
||||
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
|
||||
return srv.(DRPCPortalServer).
|
||||
ServiceStatus(
|
||||
ctx,
|
||||
in1.(*ServiceRequest),
|
||||
)
|
||||
}, DRPCPortalServer.ServiceStatus, true
|
||||
case 4:
|
||||
return "/portal.Portal/RunCommand", drpcEncoding_File_portal_portal_proto{},
|
||||
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
|
||||
return srv.(DRPCPortalServer).
|
||||
RunCommand(
|
||||
ctx,
|
||||
in1.(*CommandRequest),
|
||||
)
|
||||
}, DRPCPortalServer.RunCommand, true
|
||||
case 5:
|
||||
return "/portal.Portal/CPUusage", drpcEncoding_File_portal_portal_proto{},
|
||||
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
|
||||
return srv.(DRPCPortalServer).
|
||||
CPUusage(
|
||||
ctx,
|
||||
in1.(*CPUusageRequest),
|
||||
)
|
||||
}, DRPCPortalServer.CPUusage, true
|
||||
default:
|
||||
return "", nil, nil, nil, false
|
||||
}
|
||||
}
|
||||
|
||||
func DRPCRegisterPortal(mux drpc.Mux, impl DRPCPortalServer) error {
|
||||
return mux.Register(impl, DRPCPortalDescription{})
|
||||
}
|
||||
|
||||
type DRPCPortal_ServiceRestartStream interface {
|
||||
drpc.Stream
|
||||
SendAndClose(*ServiceResponse) error
|
||||
}
|
||||
|
||||
type drpcPortal_ServiceRestartStream struct {
|
||||
drpc.Stream
|
||||
}
|
||||
|
||||
func (x *drpcPortal_ServiceRestartStream) SendAndClose(m *ServiceResponse) error {
|
||||
if err := x.MsgSend(m, drpcEncoding_File_portal_portal_proto{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return x.CloseSend()
|
||||
}
|
||||
|
||||
type DRPCPortal_ServiceStartStream interface {
|
||||
drpc.Stream
|
||||
SendAndClose(*ServiceResponse) error
|
||||
}
|
||||
|
||||
type drpcPortal_ServiceStartStream struct {
|
||||
drpc.Stream
|
||||
}
|
||||
|
||||
func (x *drpcPortal_ServiceStartStream) SendAndClose(m *ServiceResponse) error {
|
||||
if err := x.MsgSend(m, drpcEncoding_File_portal_portal_proto{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return x.CloseSend()
|
||||
}
|
||||
|
||||
type DRPCPortal_ServiceStopStream interface {
|
||||
drpc.Stream
|
||||
SendAndClose(*ServiceResponse) error
|
||||
}
|
||||
|
||||
type drpcPortal_ServiceStopStream struct {
|
||||
drpc.Stream
|
||||
}
|
||||
|
||||
func (x *drpcPortal_ServiceStopStream) SendAndClose(m *ServiceResponse) error {
|
||||
if err := x.MsgSend(m, drpcEncoding_File_portal_portal_proto{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return x.CloseSend()
|
||||
}
|
||||
|
||||
type DRPCPortal_ServiceStatusStream interface {
|
||||
drpc.Stream
|
||||
SendAndClose(*ServiceStatusResponse) error
|
||||
}
|
||||
|
||||
type drpcPortal_ServiceStatusStream struct {
|
||||
drpc.Stream
|
||||
}
|
||||
|
||||
func (x *drpcPortal_ServiceStatusStream) SendAndClose(m *ServiceStatusResponse) error {
|
||||
if err := x.MsgSend(m, drpcEncoding_File_portal_portal_proto{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return x.CloseSend()
|
||||
}
|
||||
|
||||
type DRPCPortal_RunCommandStream interface {
|
||||
drpc.Stream
|
||||
SendAndClose(*CommandResponse) error
|
||||
}
|
||||
|
||||
type drpcPortal_RunCommandStream struct {
|
||||
drpc.Stream
|
||||
}
|
||||
|
||||
func (x *drpcPortal_RunCommandStream) SendAndClose(m *CommandResponse) error {
|
||||
if err := x.MsgSend(m, drpcEncoding_File_portal_portal_proto{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return x.CloseSend()
|
||||
}
|
||||
|
||||
type DRPCPortal_CPUusageStream interface {
|
||||
drpc.Stream
|
||||
SendAndClose(*CPUusageResponse) error
|
||||
}
|
||||
|
||||
type drpcPortal_CPUusageStream struct {
|
||||
drpc.Stream
|
||||
}
|
||||
|
||||
func (x *drpcPortal_CPUusageStream) SendAndClose(m *CPUusageResponse) error {
|
||||
if err := x.MsgSend(m, drpcEncoding_File_portal_portal_proto{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return x.CloseSend()
|
||||
}
|
||||
23
scripts/generate_fake_ca.sh
Executable file
23
scripts/generate_fake_ca.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
openssl ecparam -name secp384r1 -genkey -noout -out ca.key
|
||||
openssl req -new -x509 -key ca.key -out ca.crt -days 365 -config <(
|
||||
cat <<-EOF
|
||||
[req]
|
||||
distinguished_name = req_distinguished_name
|
||||
default_md = sha512
|
||||
req_extensions = v3_req
|
||||
prompt = no
|
||||
|
||||
[req_distinguished_name]
|
||||
C = SE
|
||||
O = Speedrun
|
||||
CN = Fake CA
|
||||
|
||||
[v3_req]
|
||||
subjectKeyIdentifier=hash
|
||||
basicConstraints=critical,CA:TRUE
|
||||
keyUsage=critical,keyCertSign,cRLSign
|
||||
EOF
|
||||
) -extensions v3_req
|
||||
46
scripts/generate_portal_cert.sh
Executable file
46
scripts/generate_portal_cert.sh
Executable file
@@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
openssl ecparam -name secp384r1 -genkey -noout -out portal.key
|
||||
openssl req -new -key portal.key -out portal.csr -config <(
|
||||
cat <<-EOF
|
||||
[req]
|
||||
distinguished_name = req_distinguished_name
|
||||
req_extensions = v3_req
|
||||
prompt = no
|
||||
|
||||
[req_distinguished_name]
|
||||
C = SE
|
||||
O = Speedrun
|
||||
CN = portal
|
||||
|
||||
[v3_req]
|
||||
keyUsage = keyEncipherment, dataEncipherment
|
||||
extendedKeyUsage = serverAuth
|
||||
subjectAltName = @alt_names
|
||||
[alt_names]
|
||||
IP.1 = 34.74.21.99
|
||||
EOF
|
||||
)
|
||||
|
||||
openssl x509 -req -in portal.csr -CA ca.crt -CAkey ca.key -out portal.crt -days 365 -sha512 -CAcreateserial -extensions v3_req -extfile <(
|
||||
cat <<-EOF
|
||||
[req]
|
||||
distinguished_name = req_distinguished_name
|
||||
req_extensions = v3_req
|
||||
prompt = no
|
||||
|
||||
[req_distinguished_name]
|
||||
C = SE
|
||||
O = Speedrun
|
||||
CN = portal
|
||||
|
||||
[v3_req]
|
||||
keyUsage = keyEncipherment, dataEncipherment
|
||||
extendedKeyUsage = serverAuth
|
||||
subjectAltName = @alt_names
|
||||
[alt_names]
|
||||
IP.1 = 34.74.21.99
|
||||
EOF
|
||||
)
|
||||
rm portal.csr
|
||||
40
scripts/generate_speedrun_cert.sh
Executable file
40
scripts/generate_speedrun_cert.sh
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
openssl ecparam -name secp384r1 -genkey -noout -out speedrun.key
|
||||
openssl req -new -key speedrun.key -out speedrun.csr -config <(
|
||||
cat <<-EOF
|
||||
[req]
|
||||
distinguished_name = req_distinguished_name
|
||||
req_extensions = v3_req
|
||||
prompt = no
|
||||
|
||||
[req_distinguished_name]
|
||||
C = SE
|
||||
O = Speedrun
|
||||
CN = speedrun
|
||||
|
||||
[v3_req]
|
||||
keyUsage = keyEncipherment, dataEncipherment
|
||||
extendedKeyUsage = clientAuth
|
||||
EOF
|
||||
)
|
||||
|
||||
openssl x509 -req -in speedrun.csr -CA ca.crt -CAkey ca.key -out speedrun.crt -days 365 -sha512 -CAcreateserial -extensions v3_req -extfile <(
|
||||
cat <<-EOF
|
||||
[req]
|
||||
distinguished_name = req_distinguished_name
|
||||
req_extensions = v3_req
|
||||
prompt = no
|
||||
|
||||
[req_distinguished_name]
|
||||
C = SE
|
||||
O = Speedrun
|
||||
CN = speedrun
|
||||
|
||||
[v3_req]
|
||||
keyUsage = keyEncipherment, dataEncipherment
|
||||
extendedKeyUsage = clientAuth
|
||||
EOF
|
||||
)
|
||||
rm speedrun.csr
|
||||
Reference in New Issue
Block a user